/*
    TiMidity++ -- MIDI to WAVE converter and player
    Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
    Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>

    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 2 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, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
	
    effect.c
*/
/*
 * REVERB EFFECT FOR TIMIDITY++-1.X (Version 0.06e  1999/1/28)
 * Copyright (C) 1997,1998,1999  Masaki Kiryu <mkiryu@usa.net>
 *                           (http://w3mb.kcom.ne.jp/~mkiryu/)
 * reverb.h
 */

/*
source code layout	
エフェクト実態は上部 エフェクト発行等は下部 
include, define, extern
VST
EFFECT Utilities
EFFECT core
GS EFFECT core
XG EFFECT core
SYSTEM EFFECT
GS EFFECT conv do
XG EFFECT conv do
SD EFFECT conv do
timidity_effect
master_effect
inialize_effect
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */

#ifndef NO_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include <math.h>
#include <stdlib.h>
#include "timidity.h"
#include "controls.h"
#include "tables.h"
#include "common.h"
#include "instrum.h"
#include "playmidi.h"
#include "output.h"
#define EFFECT_PRIVATE 1
#include "thread.h"
#include "effect.h"
#include "mt19937ar.h"
#include "sndfontini.h"

#if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_X86_) || defined(__X86__) || defined(__I86__)
#define IX86CPU 1
#endif

#if (defined(_MSC_VER) && !defined(__POCC__)) || \
	defined(__BORLANDC__)
#define CALLINGCONV __fastcall
#elif defined(__GNUC__)
#define CALLINGCONV __attribute__((fastcall))
#else
#define CALLINGCONV /**/
#endif


#define SYS_EFFECT_PRE_LPF
// check readmidi.c recompute_delay_status_gs() recompute_reverb_status_gs() recompute_chorus_status_gs()  

#ifndef POW2
#if 1 // lite
#define POW2(val) exp((float)(M_LN2 * val))
#else // precision
#define POW2(val) pow(2.0, val)
#endif
#endif /* POW2 */


static inline FLOAT_T sq(FLOAT_T var)
{
	return var * var;
}

/* #define SYS_EFFECT_CLIP*/
#ifdef SYS_EFFECT_CLIP
#ifdef EFFECT_LEVEL_FLOAT
#define CLIP_AMP_MAX ((FLOAT_T)1.0)
#define CLIP_AMP_MIN ((FLOAT_T)-1.0)
#else
#define CLIP_AMP_MAX ((1L << (MAX_BITS - GUARD_BITS - 1)) - 1)
#define CLIP_AMP_MIN (-1L << (MAX_BITS - GUARD_BITS - 1))
#endif
#endif /* SYS_EFFECT_CLIP */

#define CONV_LV_16BIT(level)  ((level << 9) | (level << 2) | (level >> 5))  /* 7 to 16.16 */
#define CONV_LV_24BIT(level)  ((level << 17) | (level << 10) | (level << 3) | (level >> 4))  /* 7 to 8.24 */

static const int32 iONE24 = TIM_FSCALE(1.0, 24);


// standard insertion input volume
#ifdef EFFECT_LEVEL_FLOAT // level float
const FLOAT_T ins_level = (double)(1.0) // ??
const FLOAT_T div_ins_level = 1.0 / (double)(1.0) // ??
#else // level int
const FLOAT_T ins_level = (double)((1<<(SAMPLE_BITS + AMP_BITS - 1))-1);
const FLOAT_T div_ins_level = 1.0 / (double)((1<<(SAMPLE_BITS + AMP_BITS - 1))-1);
#endif


///r
const FLOAT_T div_int_max = 1.0 / (double)2147483647; // effect level int32

//static double REV_INP_LEV = 1.0;
//#define MASTER_CHORUS_LEVEL 1.7
//#define MASTER_DELAY_LEVEL 1.0

///r
// readmidi.c
extern int play_system_mode;
extern enum play_system_modes;
// timidity.c
extern int opt_reverb_control;
extern unsigned char opt_normal_chorus_plus;





/**************** test *********************/
//#define RDTSC_TEST // test
#ifdef RDTSC_TEST
uint64 rdtsc_count_pr = 0, rdtsc_count = 0;
static inline uint64 rdtsc(void) 
{
	uint64 now=0;
	_asm {
		rdtsc
		mov dword ptr [now], eax
		mov dword ptr [now+4], edx
	}
	return now;
}
#define RDTSC_TEST1 {rdtsc_count_pr = rdtsc();}
#define RDTSC_TEST2 {rdtsc_count = rdtsc(); rdtsc_count -= rdtsc_count_pr;}
#else
#define RDTSC_TEST1
#define RDTSC_TEST2
#endif



/**************** VST *********************/

#ifdef VST_LOADER_ENABLE
#ifdef __W32__
HMODULE hVSTHost = NULL;
#if defined(VSTWRAP_EXT)
#if defined(DATA_T_DOUBLE)
static mix_vst_effectD p_mix_vst_effect_mo = 0;
static mix_vst_effectD p_mix_vst_effect_st = 0;
static channel_vst_sendD p_channel_vst_send = 0;
static channel_vst_returnD p_channel_vst_return = 0;
static reverb_vst_effectD p_do_reverb_vst = 0;
static chorus_vst_effectD p_do_chorus_vst = 0;
#elif defined(DATA_T_FLOAT)
static mix_vst_effectF p_mix_vst_effect_mo = 0;
static mix_vst_effectF p_mix_vst_effect_st = 0;
static channel_vst_sendF p_channel_vst_send = 0;
static channel_vst_returnF p_channel_vst_return = 0;
static reverb_vst_effectF p_do_reverb_vst = 0;
static chorus_vst_effectF p_do_chorus_vst = 0;
#else // DATA_T_INT32
static mix_vst_effectF p_mix_vst_effect_mo = 0;
static mix_vst_effectF p_mix_vst_effect_st = 0;
static channel_vst_send32 p_channel_vst_send = 0;
static channel_vst_return32 p_channel_vst_return = 0;
static reverb_vst_effect32 p_do_reverb_vst = 0;
static chorus_vst_effect32 p_do_chorus_vst = 0;
#endif /* DATA_T_DOUBLE */
#else // VSTWRAP_EXT 0
static mix_vst_effectF p_mix_vst_effect_mo = 0;
static mix_vst_effectF p_mix_vst_effect_st = 0;
static channel_vst_send32 p_channel_vst_send = 0;
static channel_vst_return32 p_channel_vst_return = 0;
static int p_do_reverb_vst = 0; // no Reverb VST
static int p_do_chorus_vst = 0; // no Chorus VST
#endif /* VSTWRAP_EXT */
#else // __W32__ 0
	/* TODO */
#endif /* __W32__ */
#endif /* VST_LOADER_ENABLE */


#ifdef VST_LOADER_ENABLE
static float vst_samplerate = DEFAULT_RATE;

///// cnv VST
#define VST_MAX_GUARD_SIGNED ((1 << (MAX_BITS - GUARD_BITS - 1)) - 1)
const FLOAT_T mlt_vst_guard = (FLOAT_T)VST_MAX_GUARD_SIGNED;
const FLOAT_T div_vst_guard = 1.0 / (double)(VST_MAX_GUARD_SIGNED + 1);

#if defined(DATA_T_DOUBLE) || defined(DATA_T_FLOAT)
// float/doubleの場合 VST仕様のレベル(-1.0~+1.0)にする必要がある
#if (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static inline void cnv_level_vst_send(DATA_T *buf, int32 count)
{
	int32 i;
	__m256d coef = _mm256_set1_pd(div_vst_guard);
	for (i = 0; i < count; i += 8){
		MM256_LS_MUL_PD(&buf[i], coef);
		MM256_LS_MUL_PD(&buf[i + 4], coef);
	}
}

static inline void cnv_level_vst_return(DATA_T *buf, int32 count)
{
	int32 i;
	__m256d coef = _mm256_set1_pd(mlt_vst_guard);
	for (i = 0; i < count; i += 8){
		MM256_LS_MUL_PD(&buf[i], coef);
		MM256_LS_MUL_PD(&buf[i + 4], coef);
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static inline void cnv_level_vst_send(DATA_T *buf, int32 count)
{
	int32 i;
	__m256 coef = _mm256_set1_ps((float)div_vst_guard);
	for (i = 0; i < count; i += 8)
		MM256_LS_MUL_PS(&buf[i], coef);
}

static inline void cnv_level_vst_return(DATA_T *buf, int32 count)
{
	int32 i;
	__m256 coef = _mm256_set1_ps((float)mlt_vst_guard);
	for (i = 0; i < count; i += 8)
		MM256_LS_MUL_PS(&buf[i], coef);
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static inline void cnv_level_vst_send(DATA_T *buf, int32 count)
{
	int32 i;
	__m128d coef = _mm_set1_pd(div_vst_guard);
	for (i = 0; i < count; i += 8){
		MM_LS_MUL_PD(&buf[i], coef);
		MM_LS_MUL_PD(&buf[i + 2], coef);
		MM_LS_MUL_PD(&buf[i + 4], coef);
		MM_LS_MUL_PD(&buf[i + 6], coef);
	}
}

static inline void cnv_level_vst_return(DATA_T *buf, int32 count)
{
	int32 i;
	__m128d coef = _mm_set1_pd(mlt_vst_guard);
	for (i = 0; i < count; i += 8){
		MM_LS_MUL_PD(&buf[i], coef);
		MM_LS_MUL_PD(&buf[i + 2], coef);
		MM_LS_MUL_PD(&buf[i + 4], coef);
		MM_LS_MUL_PD(&buf[i + 6], coef);
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static inline void cnv_level_vst_send(DATA_T *buf, int32 count)
{
	int32 i;
	__m128 coef = _mm_set1_ps((float)div_vst_guard);
	for (i = 0; i < count; i += 8){
		MM_LS_MUL_PS(&buf[i], coef);
		MM_LS_MUL_PS(&buf[i + 4], coef);
	}
}

static inline void cnv_level_vst_return(DATA_T *buf, int32 count)
{
	int32 i;
	__m128 coef = _mm_set1_ps((float)mlt_vst_guard);
	for (i = 0; i < count; i += 8){
		MM_LS_MUL_PS(&buf[i], coef);
		MM_LS_MUL_PS(&buf[i + 4], coef);
	}
}
#else
static inline void cnv_level_vst_send(DATA_T *buf, int32 count)
{
	int32 i;
	for (i = 0; i < count; i++)
		buf[i] *= div_vst_guard;
}

static inline void cnv_level_vst_return(DATA_T *buf, int32 count)
{
	int32 i;
	for (i = 0; i < count; i++)
		buf[i] *= mlt_vst_guard;
}
#endif
#endif
#endif /* VST_LOADER_ENABLE */


///// Reverb VST
static inline void do_reverb_vst(DATA_T *buf, int32 count)
{
#if defined(VST_LOADER_ENABLE) && defined(VSTWRAP_EXT)
#ifdef __W32__
#if defined(DATA_T_DOUBLE)
	cnv_level_vst_send(buf, count);
	(*p_do_reverb_vst)((double*)buf, count, vst_samplerate);
	cnv_level_vst_return(buf, count);
#elif defined(DATA_T_FLOAT)
	cnv_level_vst_send(buf, count);
	(*p_do_reverb_vst)((float*)buf, count, vst_samplerate);
	cnv_level_vst_return(buf, count);
#else // DATA_T_INT32
	(*p_do_reverb_vst)((int32*)buf, count, vst_samplerate);
#endif /* DATA_T_DOUBLE */
#else // __W32__ 0
	/* TODO */
#endif /* __W32__ */
#endif /* VSTWRAP_EXT */
}

///// Chorus VST
static inline void do_chorus_vst(DATA_T *buf, int32 count)
{
#if defined(VST_LOADER_ENABLE) && defined(VSTWRAP_EXT)
#ifdef __W32__
#if defined(DATA_T_DOUBLE)
	cnv_level_vst_send(buf, count);
	(*p_do_chorus_vst)((double*)buf, count, vst_samplerate);
	cnv_level_vst_return(buf, count);
#elif defined(DATA_T_FLOAT)
	cnv_level_vst_send(buf, count);
	(*p_do_chorus_vst)((float*)buf, count, vst_samplerate);
	cnv_level_vst_return(buf, count);
#else // DATA_T_INT32
	(*p_do_chorus_vst)((int32*)buf, count, vst_samplerate);
#endif /* DATA_T_DOUBLE */
#else // __W32__ 0
	/* TODO */
#endif /* __W32__ */
#endif /* VSTWRAP_EXT */
}

///// Master VST
#ifdef VST_LOADER_ENABLE
/*
出力変換前にVST
出力ビットに関係なくDATA_T型 (double/float/int32)でVSTに渡る
DATA_T_DOUBLEの場合 VSTWRAP_EXTの場合
	(double conv) (VST) (double conv) // GUARD_BITSのレベル変更
DATA_T_DOUBLEの場合
	float pre_vst_buffer[]を使用して
	(double-float conv) (VST) (float-double conv) // GUARD_BITSのレベル変更
DATA_T_FLOATの場合
	(float conv) (VST) (float conv) // GUARD_BITSのレベル変更
DATA_T_INT32
	float pre_vst_buffer[]を使用して
	(int32-float conv) (VST) (float-int32 conv) // GUARD_BITSのレベル変更
*/
#if (defined(DATA_T_DOUBLE) && !defined(VSTWRAP_EXT)) || (!defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT))
static ALIGN float pre_vst_buffer[AUDIO_BUFFER_SIZE * 2]; // 2ch

static inline void pre_vst_buffer_send(DATA_T *in_buf, int32 count)
{
	int32 i;
	for (i = 0; i < count; i++)
		pre_vst_buffer[i] = div_vst_guard * in_buf[i];
}

static inline void pre_vst_buffer_return(DATA_T *out_buf, int32 count)
{
	int32 i;
	for (i = 0; i < count; i++)
		out_buf[i] = mlt_vst_guard * pre_vst_buffer[i];
}
#endif

static inline void do_master_vst(DATA_T *buf, int32 nsamples, int mono)
{
#ifdef __W32__
	if (!hVSTHost || nsamples <= 0)
		return;
#if defined(DATA_T_DOUBLE)
#if defined(VSTWRAP_EXT) // if support effectProcessing int64/double
	if (mono){
		cnv_level_vst_send(buf, nsamples);
		(*p_mix_vst_effect_mo)((double*)buf, nsamples, vst_samplerate);
		cnv_level_vst_return(buf, nsamples);
	}else{
		cnv_level_vst_send(buf, nsamples);
		(*p_mix_vst_effect_st)((double*)buf, nsamples, vst_samplerate);
		cnv_level_vst_return(buf, nsamples);
	}
#else
	if (mono){
		pre_vst_buffer_send(buf, nsamples);
		(*p_mix_vst_effect_mo)((float*)pre_vst_buffer, nsamples, vst_samplerate);
		pre_vst_buffer_return(buf, nsamples);
	}else{
		pre_vst_buffer_send(buf, nsamples);
		(*p_mix_vst_effect_st)((float*)pre_vst_buffer, nsamples, vst_samplerate);
		pre_vst_buffer_return(buf, nsamples);
	}
#endif /* VSTWRAP_EXT */
#elif defined(DATA_T_FLOAT)
	if (mono){
		cnv_level_vst_send(buf, nsamples);
		(*p_mix_vst_effect_mo)((float*)buf, nsamples, vst_samplerate);
		cnv_level_vst_return(buf, nsamples);
	}else{
		cnv_level_vst_send(buf, nsamples);
		(*p_mix_vst_effect_st)((float*)buf, nsamples, vst_samplerate);
		cnv_level_vst_return(buf, nsamples);
	}
#else // DATA_T_INT32
	if (mono){
		pre_vst_buffer_send(buf, nsamples);
		(*p_mix_vst_effect_mo)((float*)pre_vst_buffer, nsamples, vst_samplerate);
		pre_vst_buffer_return(buf, nsamples);
	}else{
		pre_vst_buffer_send(buf, nsamples);
		(*p_mix_vst_effect_st)((float*)pre_vst_buffer, nsamples, vst_samplerate);
		pre_vst_buffer_return(buf, nsamples);
	}
#endif /* DATA_T_DOUBLE */
#else // __W32__ 0
	/* TODO */
#endif /* __W32__ */
}
#endif /* VST_LOADER_ENABLE */

///// Channel VST
#ifdef VST_LOADER_ENABLE
#ifdef __W32__
#if !defined(VSTWRAP_EXT) && (defined(DATA_T_DOUBLE) || defined(DATA_T_FLOAT))
int32 ALIGN vst_ch_buffer[VST_CHANNEL_MAX][AUDIO_BUFFER_SIZE * 2];
int32 *vst_ch_vpblist[MAX_CHANNELS];
#endif

// float/doubleの場合 VST仕様のレベル(-1.0~+1.0)にする必要がある , DATA_T == VST data_type
#if defined(VSTWRAP_EXT) && (defined(DATA_T_DOUBLE) || defined(DATA_T_FLOAT))
#if (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static inline void channel_vst_return(DATA_T *out_buf, DATA_T *in_buf, int32 count)
{
	int i;
	__m256d coef = _mm256_set1_pd(mlt_vst_guard);
	for(i = 0; i < count; i += 8){
		_mm256_store_pd(&out_buf[i], _mm256_mul_pd(_mm256_load_pd(&in_buf[i]), coef));
		_mm256_store_pd(&out_buf[i + 4], _mm256_mul_pd(_mm256_load_pd(&in_buf[i + 4]), coef));
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static inline void channel_vst_return(DATA_T *out_buf, DATA_T *in_buf, int32 count)
{
	int i;
	__m256 coef = _mm256_set1_ps(mlt_vst_guard);
	for(i = 0; i < count; i += 8){
		_mm256_store_ps(&out_buf[i], _mm256_mul_ps(_mm256_load_ps(&in_buf[i]), coef));
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static inline void channel_vst_return(DATA_T *out_buf, DATA_T *in_buf, int32 count)
{
	int i;
	__m128d coef = _mm_set1_pd(mlt_vst_guard);
	for(i = 0; i < count; i += 8){
		_mm_store_pd(&out_buf[i], _mm_mul_pd(_mm_load_pd(&in_buf[i]), coef));
		_mm_store_pd(&out_buf[i + 2], _mm_mul_pd(_mm_load_pd(&in_buf[i + 2]), coef));
		_mm_store_pd(&out_buf[i + 4], _mm_mul_pd(_mm_load_pd(&in_buf[i + 4]), coef));
		_mm_store_pd(&out_buf[i + 6], _mm_mul_pd(_mm_load_pd(&in_buf[i + 6]), coef));
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static inline void channel_vst_return(DATA_T *out_buf, DATA_T *in_buf, int32 count)
{
	int i;
	__m128 coef = _mm_set1_ps(mlt_vst_guard);
	for(i = 0; i < count; i += 8){
		_mm_store_ps(&out_buf[i], _mm_mul_ps(_mm_load_ps(&in_buf[i]), coef));
		_mm_store_ps(&out_buf[i + 4], _mm_mul_ps(_mm_load_ps(&in_buf[i + 4]), coef));
	}
}
#else//
static inline void channel_vst_return(DATA_T *out_buf, DATA_T *in_buf, int32 count)
{
	int32 i;
	for (i = 0; i < count; i++)
		out_buf[i] = mlt_vst_guard * in_buf[i];
}
#endif // USE_X86_EXT_INTRIN
#else // ! defined(VSTWRAP_EXT) && (defined(DATA_T_DOUBLE) || defined(DATA_T_FLOAT))
// VST data type がint32の場合はレベル変更しない
static inline void channel_vst_return_int32(DATA_T *out_buf, int32 *in_buf, int32 count)
{
	int32 i;
	for (i = 0; i < count; i++)
		out_buf[i] = in_buf[i];
}
#endif

void do_channel_vst(DATA_T *out_buf, DATA_T **in_buf, int32 nsamples, int ch)
{
	int j, max_ch = ch >= VST_CHANNEL_MAX ? VST_CHANNEL_MAX : ch;

#if defined(VSTWRAP_EXT) // support channelEffect float/double
#if defined(DATA_T_DOUBLE) || defined(DATA_T_FLOAT)
	for(j = 0; j <= max_ch; j++)
		cnv_level_vst_send(in_buf[j], nsamples);
	(*p_channel_vst_send)(in_buf, nsamples, vst_samplerate, NULL);
	channel_vst_return(out_buf, (DATA_T *)(*p_channel_vst_return)(), nsamples);
#else // DATA_T_INT32
	(*p_channel_vst_send)((long**)in_buf, nsamples, vst_samplerate, NULL);
	channel_vst_return_int32(out_buf, (DATA_T *)(*p_channel_vst_return)(), nsamples);
#endif // DATA_T_INT32

#else // wrapper def
#if defined(DATA_T_DOUBLE) || defined(DATA_T_FLOAT)
	// convert DATA_T to int32
	for(j = 0; j <= max_ch; j++) {
		DATA_T *tmp = in_buf[j];
		for(i = 0; i < nsamples; i++)
			vst_ch_vpblist[j][i] = tmp[i];
	}
	(*p_channel_vst_send)(vst_ch_vpblist, nsamples, vst_samplerate, NULL);
	// convert int32 to DATA_T output
	channel_vst_return_int32(out_buf, (int32*)(*p_channel_vst_return)(), nsamples);
#else // DATA_T_INT32
	(*p_channel_vst_send)(in_buf, nsamples, vst_samplerate, NULL);
	channel_vst_return_int32(out_buf, (int32*)(*p_channel_vst_return)(), nsamples);
#endif // DATA_T_INT32
#endif // wrapper def
}
#endif // __W32__
#endif // VST_LOADER_ENABLE

static void init_vst_effect(void)
{
#ifdef VST_LOADER_ENABLE
#ifdef __W32__
	int i, error = 0;

	if (!hVSTHost) {
		return;
	}
	vst_samplerate = (float)(play_mode->rate);

	// Master VST
#if defined(DATA_T_DOUBLE) && defined(VSTWRAP_EXT) // support effectProcessing int64/double
	p_mix_vst_effect_mo = (mix_vst_effectD) GetProcAddress(hVSTHost, "effectProcessingDoubleMono");
	p_mix_vst_effect_st = (mix_vst_effectD) GetProcAddress(hVSTHost, "effectProcessingDouble");
#else
	p_mix_vst_effect_mo = (mix_vst_effectF) GetProcAddress(hVSTHost, "effectProcessingFloatMono");
	p_mix_vst_effect_st = (mix_vst_effectF) GetProcAddress(hVSTHost, "effectProcessingFloat");
#endif /* DATA_T_DOUBLE */
	if (!p_mix_vst_effect_mo || !p_mix_vst_effect_st) {
#ifdef _WIN64
		const char libname[] = "timvstwrap_x64.dll";
#else
		const char libname[] = "timvstwrap.dll";
#endif
		const char funcname[] = "effectProcessing"
#if defined(DATA_T_DOUBLE) && defined(VSTWRAP_EXT)
			"Double/Mono";
#else
			"Float/Mono";
#endif /* DATA_T_DOUBLE */
		ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
			  "%s could not be found in %s", funcname, libname);
		error++;
	}
#if (!defined(VSTWRAP_EXT) && defined(DATA_T_DOUBLE)) || (!defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT))
	memset(pre_vst_buffer, 0, sizeof(pre_vst_buffer));
#endif

	// Channel VST	
#if defined(VSTWRAP_EXT) // support float/double
#if defined(DATA_T_DOUBLE)
	p_channel_vst_send = (channel_vst_sendD) GetProcAddress(hVSTHost, "channelEffect_InOutD");
	p_channel_vst_return = (channel_vst_returnD) GetProcAddress(hVSTHost, "channelEffect_GetInOutResultBufferD");
#elif defined(DATA_T_FLOAT)
	p_channel_vst_send = (channel_vst_sendF) GetProcAddress(hVSTHost, "channelEffect_InOutF");
	p_channel_vst_return = (channel_vst_returnF) GetProcAddress(hVSTHost, "channelEffect_GetInOutResultBufferF");
#else // DATA_T_INT32
	p_channel_vst_send = (channel_vst_send32) GetProcAddress(hVSTHost, "channelEffect_InOut");
	p_channel_vst_return = (channel_vst_return32) GetProcAddress(hVSTHost, "channelEffect_GetInOutResultBuffer");
#endif /* DATA_T_DOUBLE */
#else // VSTWRAP_EXT 0

#endif /* VSTWRAP_EXT */
	if (!p_channel_vst_send || !p_channel_vst_return) {
#ifdef _WIN64
		const char libname[] = "timvstwrap_x64.dll";
#else
		const char libname[] = "timvstwrap.dll";
#endif
		const char funcname[] = "channelEffect_"
#if defined(VSTWRAP_EXT)
#if defined(DATA_T_DOUBLE)
			"InOutD/GetInOutResultBufferD";
#elif defined(DATA_T_FLOAT)
			"InOutF/GetInOutResultBufferF";
#else // DATA_T_INT32
			"InOut/GetInOutResultBuffer";
#endif /* DATA_T_DOUBLE */
#else // VSTWRAP_EXT 0
			"InOut/GetInOutResultBuffer";
#endif /* VSTWRAP_EXT */
		ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
			  "%s could not be found in %s", funcname, libname);
		error++;
	}
#if !defined(VSTWRAP_EXT) && (defined(DATA_T_DOUBLE) || defined(DATA_T_FLOAT))
	if(vst_ch_vpblist[0] == NULL){
		for(i = 0; i < VST_CHANNEL_MAX; i++)
			vst_ch_vpblist[i] = &vst_ch_buffer[i];
	}
	memset(vst_ch_buffer, 0, sizeof(vst_ch_buffer));
#endif

	// Reverb VST
#if defined(VSTWRAP_EXT)
#if defined(DATA_T_DOUBLE)
	p_do_reverb_vst = (reverb_vst_effectD) GetProcAddress(hVSTHost, "ReverbEffectProcessingDouble");
#elif defined(DATA_T_FLOAT)
	p_do_reverb_vst = (reverb_vst_effectF) GetProcAddress(hVSTHost, "ReverbEffectProcessingFloat");
#else // DATA_T_INT32
	p_do_reverb_vst = (reverb_vst_effect32) GetProcAddress(hVSTHost, "ReverbEffectProcessingInt32");
#endif /* DATA_T_DOUBLE */
#endif /* VSTWRAP_EXT */
	if (!p_do_reverb_vst) {
#ifdef _WIN64
		const char libname[] = "timvstwrap_x64.dll";
#else
		const char libname[] = "timvstwrap.dll";
#endif
		const char funcname[] = "Reverb" "EffectProcessing"
#if defined(DATA_T_DOUBLE)
			"Double";
#elif defined(DATA_T_FLOAT)
			"Float";
#else // DATA_T_INT32
			"Int32";
#endif /* DATA_T_DOUBLE */
		ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
			  "%s could not be found in %s", funcname, libname);
		error++;
	}

	// Chorus VST	
#if defined(VSTWRAP_EXT)
#if defined(DATA_T_DOUBLE)
	p_do_chorus_vst = (chorus_vst_effectD) GetProcAddress(hVSTHost, "ChorusEffectProcessingDouble");
#elif defined(DATA_T_FLOAT)
	p_do_chorus_vst = (chorus_vst_effectF) GetProcAddress(hVSTHost, "ChorusEffectProcessingFloat");
#else // DATA_T_INT32
	p_do_chorus_vst = (chorus_vst_effect32) GetProcAddress(hVSTHost, "ChorusEffectProcessingInt32");
#endif /* DATA_T_DOUBLE */
#endif /* VSTWRAP_EXT */
	if (!p_do_chorus_vst) {
#ifdef _WIN64
		const char libname[] = "timvstwrap_x64.dll";
#else
		const char libname[] = "timvstwrap.dll";
#endif
		const char funcname[] = "Chorus" "EffectProcessing"
#if defined(DATA_T_DOUBLE)
			"Double";
#elif defined(DATA_T_FLOAT)
			"Float";
#else // DATA_T_INT32
			"Int32";
#endif /* DATA_T_DOUBLE */
		ctl->cmsg(CMSG_FATAL, VERB_NORMAL,
			  "%s could not be found in %s", funcname, libname);
		error++;
	}

	if(error){
		FreeLibrary(hVSTHost);
		hVSTHost = NULL;
		return;
	}

#else // __W32__ 0
	/* TODO */
#endif /* __W32__ */
#endif /* VST_LOADER_ENABLE */
}




/********************************** EFFECT Utilities *************************************/

//static DATA_T efx_buffer[AUDIO_BUFFER_SIZE * 2]; // tmp buffer

/*! panning (pan = [0, 127]) */
#if !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static inline int32 do_left_panning(int32 sample, int32 pan)
{
	return imuldiv8(sample, 256 - pan - pan);
}

static inline int32 do_right_panning(int32 sample, int32 pan)
{
	return imuldiv8(sample, pan + pan);
}
#else /* floating-point implementation */
// MIDIパラメータによるのパンについて
// パン計算はエフェクト外に出してGS/XG規格に合わせて calc_panning()
// 毎回パン係数を計算しないで panl, panr で保持する
// それ以外のパンについて レベル変化が少なそうなGM2テーブルにする
static inline DATA_T do_left_panning(DATA_T sample, int32 pan)
{
	return sample * (FLOAT_T)gm2_vol_table[127 - pan] * DIV_127;
}

static inline DATA_T do_right_panning(DATA_T sample, int32 pan)
{
	return sample * (FLOAT_T)gm2_vol_table[pan] * DIV_127;
}
#endif /* OPT_MODE != 0 */

static inline int clip_int(int val, int min, int max)
{
	return ((val > max) ? max : (val < min) ? min : val);
}

static inline float clip_float(float val, float min, float max)
{
	return ((val > max) ? max : (val < min) ? min : val);
}

static inline double clip_double(double val, double min, double max)
{
	return ((val > max) ? max : (val < min) ? min : val);
}

static inline FLOAT_T clip_FLOAT_T(FLOAT_T val, FLOAT_T min, FLOAT_T max)
{
	return ((val > max) ? max : (val < min) ? min : val);
}

///r
// mix 0.0~1.0 (mix=0.0 param1, mix=0.5 param1*0.5+param2*0.5, mix=1.0 param2
static inline double mix_double(double mix, double param1, double param2)
{
	return param1 * (1.0 - mix) + param2 * mix;
}

static inline int32 Sample_FtoI(double v)
{
	if (v<0)return ( (-v * (double)LONG_MIN) - 0.5 );
	return (v * (double)LONG_MAX + 0.5);
}

static inline double Sample_ItoF(int32 v)
{
	if (v<0)return (-(double)v / (double)LONG_MIN);
	return ((double)v / (double)LONG_MAX);
}



static double calc_pan_xg_left(int val)
{	
	if(val == 0)
		return 1.0;
	else if(val == 127)
		return 0.0;
	else if(val == 64)
		return 0.5;
	else
		return 1.0 - ((double)(clip_int(val, 1, 127) - 0x40) * DIV_63 + 0.5);
}

static double calc_pan_xg_right(int val)
{
	if(val == 0)
		return 0.0;
	else if(val == 127)
		return 1.0;
	else if(val == 64)
		return 0.5;
	else
		return (double)(clip_int(val, 1, 127) - 0x40) * DIV_63 + 0.5;
}

///r
static double calc_xg_level(int val, struct effect_xg_t *st)
{
	if(val == 0)
		return 0.0;
//	return (FLOAT_T)val * DIV_127;
	return pow((FLOAT_T)val * DIV_127, 0.5); 
}

static double calc_dry_xg(int val, struct effect_xg_t *st)
{
	switch(st->connection) {
	case XG_CONN_SYSTEM:
	case XG_CONN_SYSTEM_CHORUS:
	case XG_CONN_SYSTEM_REVERB:
		return 0.0;
	case XG_CONN_INSERTION:
	default:
		if(val == 0)
			return 1.0;
		else if(val == 127)
			return 0.0;
		else if(val == 64)
			return 0.5;
		else
			return 1.0 - ((double)(clip_int(val, 1, 127) - 0x40) * DIV_63 + 0.5);
	}
}

static double calc_wet_xg(int val, struct effect_xg_t *st)
{
	switch(st->connection) {
	case XG_CONN_SYSTEM:
	case XG_CONN_SYSTEM_CHORUS:
	case XG_CONN_SYSTEM_REVERB:
		return 1.0;
	case XG_CONN_INSERTION:
	default:
		if(val == 0)
			return 0.0;
		else if(val == 127)
			return 1.0;
		else if(val == 64)
			return 0.5;
		else
			return (double)(clip_int(val, 1, 127) - 0x40) * DIV_63 + 0.5;
	}
}

static double calc_pan_gs_left(int val)
{
	if(val == 0)
		return 1.0;
	else if(val == 127)
		return 0.0;
	else if(val == 64)
		return 0.5;
	else
		return 1.0 - ((double)(clip_int(val, 1, 127) - 0x40) * DIV_63 + 0.5);
}

static double calc_pan_gs_right(int val)
{
	if(val == 0)
		return 0.0;
	else if(val == 127)
		return 1.0;
	else if(val == 64)
		return 0.5;
	else
		return (double)(clip_int(val, 1, 127) - 0x40) * DIV_63 + 0.5;
}

static double calc_dry_gs(int val)
{
	//if(val == 0)
	//	return 1.0;
	//else if(val == 127)
	//	return 0.0;
	//else if(val == 64)
	//	return 0.5;
	//else
	//	return 1.0 - ((double)(clip_int(val, 1, 127) - 0x40) * DIV_63 + 0.5);
	if(val == 127)
		return 0.0;
	else if(val <= 64)
		return 1.0;
	else
		return (double)(127 - clip_int(val, 0, 127)) * DIV_63;
}

static double calc_wet_gs(int val)
{
	//if(val == 0)
	//	return 0.0;
	//else if(val == 127)
	//	return 1.0;
	//else if(val == 64)
	//	return 0.5;
	//else
	//	return (double)(clip_int(val, 1, 127) - 0x40) * DIV_63 + 0.5;
	if(val == 0)
		return 0.0;
	else if(val >= 64)
		return 1.0;
	else
		return (double)(clip_int(val, 0, 127) - 0x1) * DIV_63;
}

static double calc_gs_level(int val)
{
	if(val == 0)
		return 0.0;
//	return (FLOAT_T)val * DIV_127;
	return pow((FLOAT_T)val * DIV_127, 0.5); 
}

static double calc_balance_dry_sd(int val)
{
	return (FLOAT_T)(100 - clip_int(val, 0, 100)) * DIV_100;
}

static double calc_balance_wet_sd(int val)
{
	return (FLOAT_T)(clip_int(val, 0, 100)) * DIV_100;
}

static double calc_mix_dry_sd(int val)
{
	//if(val == 0)
	//	return 1.0;
	//else if(val == 127)
	//	return 0.0;
	//else if(val == 64)
	//	return 0.5;
	//else
	//	return 1.0 - ((double)(clip_int(val, 1, 127) - 0x40) * DIV_63 + 0.5);
	if(val == 127)
		return 0.0;
	else if(val <= 64)
		return 1.0;
	else
		return (double)(127 - clip_int(val, 0, 127)) * DIV_63;
}

static double calc_mix_wet_sd(int val)
{
	//if(val == 0)
	//	return 0.0;
	//else if(val == 127)
	//	return 1.0;
	//else if(val == 64)
	//	return 0.5;
	//else
	//	return (double)(clip_int(val, 1, 127) - 0x40) * DIV_63 + 0.5;
	if(val == 0)
		return 0.0;
	else if(val >= 64)
		return 1.0;
	else
		return (double)(clip_int(val, 0, 127) - 0x1) * DIV_63;
}

static double calc_pan_sd_left(int val)
{
	return (FLOAT_T)gm2_pan_table[127 - clip_int(val, 0, 127)] * DIV_127;
}

static double calc_pan_sd_right(int val)
{
	return (FLOAT_T)gm2_pan_table[clip_int(val, 0, 127)] * DIV_127;
}

static double calc_sd_level(int val)
{
	return (FLOAT_T)clip_int(val, 0, 127) * DIV_127;
}

static double calc_option_level(int val)
{
	return (FLOAT_T)clip_int(val, 0, 127) * DIV_127;
}

static double calc_option_wet(int val)
{
	if(val == 0)
		return 0.0;
	else if(val == 127)
		return 1.0;
	else if(val == 64)
		return 0.5;
	else
		return (double)(clip_int(val, 1, 127) - 0x40) * DIV_63 + 0.5;
}

static double calc_option_dry(int val)
{
	if(val == 0)
		return 1.0;
	else if(val == 127)
		return 0.0;
	else if(val == 64)
		return 0.5;
	else
		return 1.0 - ((double)(clip_int(val, 1, 127) - 0x40) * DIV_63 + 0.5);
}


static void send_efx_buffer(EffectList *ef, DATA_T *buf, int32 count)
{
	if(count <= 0)
		return;
 	memcpy(ef->efx_buf, buf, sizeof(DATA_T) * count);
}


#if (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void return_efx_buffer(EffectList *ef, DATA_T *buf, int32 count, double wet, double dry, double level)
{
	int i;
	DATA_T *ebuf = ef->efx_buf;
	__m256d vec_wet = _mm256_set1_pd(wet * level), vec_dry = _mm256_set1_pd(dry * level);
	for(i = 0; i < count; i += 8){
		_mm256_store_pd(&buf[i], MM256_FMA2_PD(_mm256_load_pd(&buf[i]), vec_dry, _mm256_load_pd(&ebuf[i]), vec_wet));
		_mm256_store_pd(&buf[i + 4], MM256_FMA2_PD(_mm256_load_pd(&buf[i + 4]), vec_dry, _mm256_load_pd(&ebuf[i + 4]), vec_wet));
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void return_efx_buffer(EffectList *ef, DATA_T *buf, int32 count, double wet, double dry, double level)
{
	int i;
	DATA_T *ebuf = ef->efx_buf;
	__m256 vec_wet = _mm256_set1_ps((float)(wet * level)), vec_dry = _mm256_set1_ps((float)(dry * level));
	for(i = 0; i < count; i += 8){
		_mm256_store_ps(&buf[i], MM256_FMA2_PS(_mm256_load_ps(&buf[i]), vec_dry, _mm256_load_ps(&ebuf[i]), vec_wet));
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static void return_efx_buffer(EffectList *ef, DATA_T *buf, int32 count, double wet, double dry, double level)
{
	int i;
	DATA_T *ebuf = ef->efx_buf;
	__m128d vec_wet = _mm_set1_pd(wet * level), vec_dry = _mm_set1_pd(dry * level);
	for(i = 0; i < count; i += 8){
		_mm_store_pd(&buf[i], MM_FMA2_PD(_mm_load_pd(&buf[i]), vec_dry,	_mm_load_pd(&ebuf[i]), vec_wet));
		_mm_store_pd(&buf[i + 2], MM_FMA2_PD(_mm_load_pd(&buf[i + 2]), vec_dry,_mm_load_pd(&ebuf[i + 2]), vec_wet));
		_mm_store_pd(&buf[i + 4], MM_FMA2_PD(_mm_load_pd(&buf[i + 4]), vec_dry,	_mm_load_pd(&ebuf[i + 4]), vec_wet));
		_mm_store_pd(&buf[i + 6], MM_FMA2_PD(_mm_load_pd(&buf[i + 6]), vec_dry,	_mm_load_pd(&ebuf[i + 6]), vec_wet));
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void return_efx_buffer(EffectList *ef, DATA_T *buf, int32 count, double wet, double dry, double level)
{
	int i;
	DATA_T *ebuf = ef->efx_buf;
	__m128 vec_wet = _mm_set1_ps((float)(wet * level)), vec_dry = _mm_set1_ps((float)(dry * level));
	for(i = 0; i < count; i += 8){
		_mm_store_ps(&buf[i], MM_FMA2_PS(_mm_load_ps(&buf[i]), vec_dry, _mm_load_ps(&ebuf[i]), vec_wet));
		_mm_store_ps(&buf[i + 4], MM_FMA2_PS(_mm_load_ps(&buf[i + 4]), vec_dry, _mm_load_ps(&ebuf[i + 4]), vec_wet));
	}
}
#else
static void return_efx_buffer(EffectList *ef, DATA_T *buf, int32 count, double wet, double dry, double level)
{
	int i;
	DATA_T *ebuf = ef->efx_buf;
	FLOAT_T wet2 = wet * level, dry2 = dry * level;
	
	for(i = 0; i < count; i++) {
		buf[i] = ebuf[i] * wet2 + buf[i] * dry2;
		i++;
		buf[i] = ebuf[i] * wet2 + buf[i] * dry2;
	}
}
#endif


#if (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void return_efx_buffer_left(EffectList *ef, DATA_T *buf, int32 count, double wet, double dry, double level)
{
	int i;
	DATA_T *ebuf = ef->efx_buf;
	FLOAT_T wet2 = wet * level, dry2 = dry * level;
	__m256d vec_wet = _mm256_set_pd(0.0, wet2, 0.0, wet2);
	__m256d vec_dry = _mm256_set_pd(1.0, dry2, 1.0, dry2);
	for(i = 0; i < count; i += 8){
		_mm256_store_pd(&buf[i], MM256_FMA2_PD(_mm256_load_pd(&buf[i]), vec_dry, _mm256_load_pd(&ebuf[i]), vec_wet));
		_mm256_store_pd(&buf[i + 4], MM256_FMA2_PD(_mm256_load_pd(&buf[i + 4]), vec_dry, _mm256_load_pd(&ebuf[i + 4]), vec_wet));
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void return_efx_buffer_left(EffectList *ef, DATA_T *buf, int32 count, double wet, double dry, double level)
{
	int i;
	DATA_T *ebuf = ef->efx_buf;
	float wet2 = wet * level, dry2 = dry * level;
	__m128 vec_wets = _mm_set_ps(0.0, wet2, 0.0, wet2);
	__m128 vec_drys = _mm_set_ps(1.0, dry2, 1.0, dry2);	
	__m256 vec_wet = MM256_SET2X_PS(vec_wets, vec_wets);
	__m256 vec_dry = MM256_SET2X_PS(vec_drys, vec_drys);
	for(i = 0; i < count; i += 8){
		_mm256_store_ps(&buf[i], MM256_FMA2_PS(_mm256_load_ps(&buf[i]), vec_dry, _mm256_load_ps(&ebuf[i]), vec_wet));
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void return_efx_buffer_left(EffectList *ef, DATA_T *buf, int32 count, double wet, double dry, double level)
{
	int i;
	DATA_T *ebuf = ef->efx_buf;
	float wet2 = wet * level, dry2 = dry * level;
	__m128 vec_wet = _mm_set_ps(0.0, wet2, 0.0, wet2);
	__m128 vec_dry = _mm_set_ps(1.0, dry2, 1.0, dry2);
	for(i = 0; i < count; i += 8){
		_mm_store_ps(&buf[i], MM_FMA2_PS(_mm_load_ps(&buf[i]), vec_dry, _mm_load_ps(&ebuf[i]), vec_wet));
		_mm_store_ps(&buf[i + 4], MM_FMA2_PS(_mm_load_ps(&buf[i + 4]), vec_dry, _mm_load_ps(&ebuf[i + 4]), vec_wet));
	}
}
#else
static void return_efx_buffer_left(EffectList *ef, DATA_T *buf, int32 count, double wet, double dry, double level)
{
	int i;
	DATA_T *ebuf = ef->efx_buf;
	FLOAT_T wet2 = wet * level, dry2 = dry * level;
	for(i = 0; i < count; i++) {
		buf[i] = ebuf[i] * wet2 + buf[i] * dry2;
		i++;
	}
}
#endif

#if (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void return_efx_buffer_right(EffectList *ef, DATA_T *buf, int32 count, double wet, double dry, double level)
{
	int i;
	DATA_T *ebuf = ef->efx_buf;
	FLOAT_T wet2 = wet * level, dry2 = dry * level;
	__m256d vec_wet = _mm256_set_pd(wet2, 0.0, wet2, 0.0);
	__m256d vec_dry = _mm256_set_pd(dry2, 1.0, dry2, 1.0);
	for(i = 0; i < count; i += 8){
		_mm256_store_pd(&buf[i], MM256_FMA2_PD(_mm256_load_pd(&buf[i]), vec_dry, _mm256_load_pd(&ebuf[i]), vec_wet));
		_mm256_store_pd(&buf[i + 4], MM256_FMA2_PD(_mm256_load_pd(&buf[i + 4]), vec_dry, _mm256_load_pd(&ebuf[i + 4]), vec_wet));
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void return_efx_buffer_right(EffectList *ef, DATA_T *buf, int32 count, double wet, double dry, double level)
{
	int i;
	DATA_T *ebuf = ef->efx_buf;
	float wet2 = wet * level, dry2 = dry * level;
	__m128 vec_wets = _mm_set_ps(wet2, 0.0, wet2, 0.0);
	__m128 vec_drys = _mm_set_ps(dry2, 1.0, dry2, 1.0);	
	__m256 vec_wet = MM256_SET2X_PS(vec_wets, vec_wets);
	__m256 vec_dry = MM256_SET2X_PS(vec_drys, vec_drys);
	for(i = 0; i < count; i += 8){
		_mm256_store_ps(&buf[i], MM256_FMA2_PS(_mm256_load_ps(&buf[i]), vec_dry, _mm256_load_ps(&ebuf[i]), vec_wet));
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void return_efx_buffer_right(EffectList *ef, DATA_T *buf, int32 count, double wet, double dry, double level)
{
	int i;
	DATA_T *ebuf = ef->efx_buf;
	float wet2 = wet * level, dry2 = dry * level;
	__m128 vec_wet = _mm_set_ps(wet2, 0.0, wet2, 0.0);
	__m128 vec_dry = _mm_set_ps(dry2, 1.0, dry2, 1.0);
	for(i = 0; i < count; i += 8){
		_mm_store_ps(&buf[i], MM_FMA2_PS(_mm_load_ps(&buf[i]), vec_dry, _mm_load_ps(&ebuf[i]), vec_wet));
		_mm_store_ps(&buf[i + 4], MM_FMA2_PS(_mm_load_ps(&buf[i + 4]), vec_dry, _mm_load_ps(&ebuf[i + 4]), vec_wet));
	}
}
#else
static void return_efx_buffer_right(EffectList *ef, DATA_T *buf, int32 count, double wet, double dry, double level)
{
	int i;
	DATA_T inputl, inputr;
	DATA_T *ebuf = ef->efx_buf;
	FLOAT_T wet2 = wet * level, dry2 = dry * level;
	for(i = 0; i < count; i++) {
		i++;
		buf[i] = ebuf[i] * wet2 + buf[i] * dry2;
	}
}
#endif


// stereo mix to mono
#define DIV_MIX_LEVEL (0.7071)
#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static const int32 DIV_MIX_LEVELi = TIM_FSCALE(DIV_MIX_LEVEL, 24);
#endif /* OPT_MODE == 1 */

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void CALLINGCONV effect_mix_mono(int32 *buf, int32 count)
{
	int32 i;
	int32 tmp;

	for (i = 0; i < count; i++) {
		tmp = imuldiv24(buf[i] + buf[i + 1], DIV_MIX_LEVELi);
		buf[i] = tmp;
		i++;
		buf[i] = tmp;
	}
}
/* floating-point implementation */
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void effect_mix_mono(DATA_T *buf, int32 count)
{
	int32 i;
	__m256d vmix = _mm256_set1_pd((double)DIV_MIX_LEVEL);
	for(i = 0; i < count; i += 8) {
		__m256d vtmp1, vtmp2;
		vtmp1 = _mm256_load_pd(&buf[i]); // [0,1,2,3]
		vtmp2 = _mm256_shuffle_pd(vtmp1, vtmp1, 0x05); // [1,0,3,2]
		_mm256_store_pd(&buf[i], _mm256_mul_pd(_mm256_add_pd(vtmp1, vtmp2), vmix));
		vtmp1 = _mm256_load_pd(&buf[i + 4]); // [0,1]
		vtmp2 = _mm256_shuffle_pd(vtmp1, vtmp1, 0x05); // [1,0]
		_mm256_store_pd(&buf[i + 4], _mm256_mul_pd(_mm256_add_pd(vtmp1, vtmp2), vmix));
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void effect_mix_mono(DATA_T *buf, int32 count)
{
	int32 i;
	__m256 vmix = _mm256_set1_ps((float)DIV_MIX_LEVEL);
	for(i = 0; i < count; i += 8) {
		__m256 vtmp1, vtmp2;
		vtmp1 = _mm256_load_ps(&buf[i]); // [0,1,2,3,4,5,6,7]
		vtmp2 = _mm256_shuffle_ps(vtmp1, vtmp1, 0xb1); // [1,0,3,2,5,4,7,6]
		_mm256_store_ps(&buf[i], _mm256_mul_ps(_mm256_add_ps(vtmp1, vtmp2), vmix));
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static void effect_mix_mono(DATA_T *buf, int32 count)
{
	int32 i;
	__m128d vmix = _mm_set1_pd((double)DIV_MIX_LEVEL);
	for(i = 0; i < count; i += 4) {
		__m128d vtmp1, vtmp2;
		vtmp1 = _mm_load_pd(&buf[i]); // [0,1]
		vtmp2 = _mm_shuffle_pd(vtmp1, vtmp1, 0x01); // [1,0]
		_mm_store_pd(&buf[i], _mm_mul_pd(_mm_add_pd(vtmp1, vtmp2), vmix));
		vtmp1 = _mm_load_pd(&buf[i + 2]); // [0,1]
		vtmp2 = _mm_shuffle_pd(vtmp1, vtmp1, 0x01); // [1,0]
		_mm_store_pd(&buf[i + 2], _mm_mul_pd(_mm_add_pd(vtmp1, vtmp2), vmix));
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void effect_mix_mono(DATA_T *buf, int32 count)
{
	int32 i;
	__m128 vmix = _mm_set1_ps((float)DIV_MIX_LEVEL);
	for(i = 0; i < count; i += 8) {
		__m128 vtmp1, vtmp2;
		vtmp1 = _mm_load_ps(&buf[i]); // [0,1,2,3]
		vtmp2 = _mm_shuffle_ps(vtmp1, vtmp1, 0xb1); // [1,0,3,2]
		_mm_store_ps(&buf[i], _mm_mul_ps(_mm_add_ps(vtmp1, vtmp2), vmix));
		vtmp1 = _mm_load_ps(&buf[i + 4]); // [0,1,2,3]
		vtmp2 = _mm_shuffle_ps(vtmp1, vtmp1, 0xb1); // [1,0,3,2]
		_mm_store_ps(&buf[i + 4], _mm_mul_ps(_mm_add_ps(vtmp1, vtmp2), vmix));
	}
}
#else
static void effect_mix_mono(DATA_T *buf, int32 count)
{
	int32 i;

	for(i = 0; i < count; i++) {
		DATA_T tmp = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
		buf[i] = tmp;
		buf[++i] = tmp;
	}
}
#endif /* OPT_MODE == 1 */


// left to mono // left to right
#if (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void effect_left_mono(DATA_T *buf, int32 count)
{
	int32 i;

	for(i = 0; i < count; i += 8) {
		__m256 vtmp = _mm256_load_ps(&buf[i]);
		_mm256_store_ps(&buf[i], _mm256_shuffle_ps(vtmp, vtmp, 0xa0));
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void effect_left_mono(DATA_T *buf, int32 count)
{
	int32 i;

	for(i = 0; i < count; i += 8) {
		__m256d vtmp;
		vtmp = _mm256_load_pd(&buf[i]);
		_mm256_store_pd(&buf[i], _mm256_shuffle_pd(vtmp, vtmp, 0x0));
		vtmp = _mm256_load_pd(&buf[i + 4]);
		_mm256_store_pd(&buf[i + 4], _mm256_shuffle_pd(vtmp, vtmp, 0x0));
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void effect_left_mono(DATA_T *buf, int32 count)
{
	int32 i;

	for(i = 0; i < count; i += 8) {
		__m128 vtmp;
		vtmp = _mm_load_ps(&buf[i]);
		_mm_store_ps(&buf[i], _mm_shuffle_ps(vtmp, vtmp, 0xa0));
		vtmp = _mm_load_ps(&buf[i + 4]);
		_mm_store_ps(&buf[i + 4], _mm_shuffle_ps(vtmp, vtmp, 0xa0));
	}
}
#elif 1 
static void effect_left_mono(DATA_T *buf, int32 count)
{
	int32 i;

	for(i = 0; i < count; i += 8) {
		buf[i + 1] = buf[i];
		buf[i + 3] = buf[i + 2];
		buf[i + 5] = buf[i + 4];
		buf[i + 7] = buf[i + 6];
	}
}
#else
static void effect_left_mono(DATA_T *buf, int32 count)
{
	int32 i;

	for(i = 0; i < count; i += 2) {
		buf[i + 1] = buf[i];
	}
}
#endif


#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
// mono to stereo, left to stereo
static void CALLINGCONV effect_panning_mono_stereo(int32 *buf, int32 count, int32 panl, int32 panr)
{
	int32 i;
	int32 tmp;

	for (i = 0; i < count; i++) {
		tmp = buf[i];
		buf[i] = imuldiv24(tmp, panl);
		i++;
		buf[i] = imuldiv24(tmp, panr);
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void effect_panning_mono_stereo(DATA_T *buf, int32 count, double panl, double panr)
{
	int32 i;	
	__m128 vec_pans = _mm_set_ps(panr, panl, panr, panl);
	__m256 vec_pan = MM256_SET2X_PS(vec_pans, vec_pans);
	for(i = 0; i < count; i += 8){
		__m256 vtmp1, vtmp2;
		vtmp1 = _mm256_load_ps(&buf[i]); // [0,1,2,3,4,5,6,7]
		vtmp2 = _mm256_shuffle_ps(vtmp1, vtmp1, 0xa0); // [0,0,2,2,4,4,6,6]
		_mm256_store_ps(&buf[i], _mm256_mul_ps(vtmp2, vec_pan));
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void effect_panning_mono_stereo(DATA_T *buf, int32 count, double panl, double panr)
{
	int32 i;
	__m256d vec_pan = _mm256_set_pd(panr, panl, panr, panl);
	for(i = 0; i < count; i += 8){
		__m256d vtmp1, vtmp2;
		vtmp1 = _mm256_load_pd(&buf[i]); // [0,1,2,3]
		vtmp2 = _mm256_shuffle_pd(vtmp1, vtmp1, 0x00); // [0,0,2,2]
		_mm256_store_pd(&buf[i], _mm256_mul_pd(vtmp2, vec_pan));
		vtmp1 = _mm256_load_pd(&buf[i + 4]); // [0,1,2,3]
		vtmp2 = _mm256_shuffle_pd(vtmp1, vtmp1, 0x00); // [0,0,2,2]
		_mm256_store_pd(&buf[i + 4], _mm256_mul_pd(vtmp2, vec_pan));
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static void effect_panning_mono_stereo(DATA_T *buf, int32 count, double panl, double panr)
{
	int32 i;
	__m128d vec_pan = _mm_set_pd(panr, panl);
	for(i = 0; i < count; i += 8){
		_mm_store_pd(&buf[i], _mm_mul_pd(MM_LOAD1_PD(&buf[i]), vec_pan));
		_mm_store_pd(&buf[i + 2], _mm_mul_pd(MM_LOAD1_PD(&buf[i + 2]), vec_pan));
		_mm_store_pd(&buf[i + 4], _mm_mul_pd(MM_LOAD1_PD(&buf[i + 4]), vec_pan));
		_mm_store_pd(&buf[i + 6], _mm_mul_pd(MM_LOAD1_PD(&buf[i + 6]), vec_pan));
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void effect_panning_mono_stereo(DATA_T *buf, int32 count, double panl, double panr)
{
	int32 i;
	__m128 vec_pan = _mm_set_ps(panr, panl, panr, panl);
	for(i = 0; i < count; i += 8){
		__m128 vtmp1, vtmp2;
		vtmp1 = _mm_load_ps(&buf[i]); // [0,1,2,3]
		vtmp2 = _mm_shuffle_ps(vtmp1, vtmp1, 0xa0); // [0,0,2,2]
		_mm_store_ps(&buf[i], _mm_mul_ps(vtmp2, vec_pan));
		vtmp1 = _mm_load_ps(&buf[i + 4]); // [0,1,2,3]
		vtmp2 = _mm_shuffle_ps(vtmp1, vtmp1, 0xa0); // [0,0,2,2]
		_mm_store_ps(&buf[i + 4], _mm_mul_ps(vtmp2, vec_pan));
	}
}
#else /* floating-point implementation */
// mono to stereo, left to stereo
static void effect_panning_mono_stereo(DATA_T *buf, int32 count, double panl, double panr)
{
	int32 i;

	for(i = 0; i < count; i++) {
		DATA_T tmp = buf[i];
		buf[i] = tmp * panl;
		i++;
		buf[i] = tmp * panr;
	}
}
#endif /* OPT_MODE == 1 */


#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
// change level only left
static void CALLINGCONV effect_level_left(int32 *buf, int32 count, int32 level)
{
	int32 i;

	if (level == TIM_FSCALE(1.0, 24))
		return;
	for (i = 0; i < count; i++) {
		buf[i] = imuldiv24(buf[i], level);
		i++;
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void effect_level_left(DATA_T *buf, int32 count, double level)
{
	int32 i;

	if(level == 1.0)
		return;
	{
	__m128 vlevels = _mm_set_ps(1.0, level, 1.0, level);
	__m256 vlevel = MM256_SET2X_PS(vlevels, vlevels);
	for(i = 0; i < count; i += 8) {			
		MM256_LS_MUL_PS(&buf[i], vlevel);
	}
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void effect_level_left(DATA_T *buf, int32 count, double level)
{
	int32 i;

	if(level == 1.0)
		return;
	{
	__m128d vlevels = _mm_set_pd(1.0, level);
	__m256d vlevel = MM256_SET2X_PD(vlevels, vlevels);
	for(i = 0; i < count; i += 8) {			
		MM256_LS_MUL_PD(&buf[i], vlevel);
		MM256_LS_MUL_PD(&buf[i + 4], vlevel);
	}
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static void effect_level_left(DATA_T *buf, int32 count, double level)
{
	int32 i;

	if(level == 1.0)
		return;
	{
	__m128d vlevels = _mm_set_pd(1.0, level);
	for(i = 0; i < count; i += 8) {			
		MM_LS_MUL_PD(&buf[i], vlevels);
		MM_LS_MUL_PD(&buf[i + 2], vlevels);
		MM_LS_MUL_PD(&buf[i + 4], vlevels);
		MM_LS_MUL_PD(&buf[i + 6], vlevels);
	}
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void effect_level_left(DATA_T *buf, int32 count, double level)
{
	int32 i;

	if(level == 1.0)
		return;
	{
	__m128 vlevels = _mm_set_ps(1.0, level, 1.0, level);
	for(i = 0; i < count; i += 8) {			
		MM_LS_MUL_PS(&buf[i], vlevels);	
		MM_LS_MUL_PS(&buf[i + 4], vlevels);
	}
	}
}
#else /* floating-point implementation */
// change level only left 
static void effect_level_left(DATA_T *buf, int32 count, double level)
{
	int32 i;

	if(level == 1.0)
		return;
	for(i = 0; i < count; i++) {
		buf[i] *= level;
		i++;
	}
}
#endif /* OPT_MODE == 1 */



#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
// change level only right
static void CALLINGCONV effect_level_right(int32 *buf, int32 count, int32 level)
{
	int32 i;

	if (level == TIM_FSCALE(1.0, 24))
		return;
	for (i = 0; i < count; i++) {
		i++;
		buf[i] = imuldiv24(buf[i], level);
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void effect_level_right(DATA_T *buf, int32 count, double level)
{
	int32 i;
	
	if(level == 1.0)
		return;
	{
	__m128 vlevels = _mm_set_ps(level, 1.0, level, 1.0);
	__m256 vlevel = MM256_SET2X_PS(vlevels, vlevels);
	for(i = 0; i < count; i += 8) {			
		MM256_LS_MUL_PS(&buf[i], vlevel);
	}
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void effect_level_right(DATA_T *buf, int32 count, double level)
{
	int32 i;

	if(level == 1.0)
		return;
	{
	__m128d vlevels = _mm_set_pd(level, 1.0);
	__m256d vlevel = MM256_SET2X_PD(vlevels, vlevels);
	for(i = 0; i < count; i += 8) {			
		MM256_LS_MUL_PD(&buf[i], vlevel);
		MM256_LS_MUL_PD(&buf[i + 4], vlevel);
	}
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static void effect_level_right(DATA_T *buf, int32 count, double level)
{
	int32 i;

	if(level == 1.0)
		return;
	{
	__m128d vlevels = _mm_set_pd(level, 1.0);
	for(i = 0; i < count; i += 8) {			
		MM_LS_MUL_PD(&buf[i], vlevels);
		MM_LS_MUL_PD(&buf[i + 2], vlevels);
		MM_LS_MUL_PD(&buf[i + 4], vlevels);
		MM_LS_MUL_PD(&buf[i + 6], vlevels);
	}
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void effect_level_right(DATA_T *buf, int32 count, double level)
{
	int32 i;

	if(level == 1.0)
		return;
	{
	__m128 vlevels = _mm_set_ps(level, 1.0, level, 1.0);
	for(i = 0; i < count; i += 8) {			
		MM_LS_MUL_PS(&buf[i], vlevels);	
		MM_LS_MUL_PS(&buf[i + 4], vlevels);
	}
	}
}
#else /* floating-point implementation */
// change level only right
static void effect_level_right(DATA_T *buf, int32 count, double level)
{
	int32 i;
	
	if(level == 1.0)
		return;
	for(i = 0; i < count; i++) {
		i++;
		buf[i] *= level;
	}
}
#endif /* OPT_MODE == 1 */


#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
// change level stereo
static void CALLINGCONV effect_level_stereo(int32 *buf, int32 count, int32 level)
{
	int32 i;

	if (level == TIM_FSCALE(1.0, 24))
		return;
	for (i = 0; i < count; i++) {
		buf[i] = imuldiv24(buf[i], level);
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void effect_level_stereo(DATA_T *buf, int32 count, double level)
{
	int32 i;
	if(level == 1.0)
		return;
	{
		__m256d vec_level = _mm256_set1_pd(level);
		for(i = 0; i < count; i += 8){
			MM256_LS_MUL_PD(&buf[i], vec_level);
			MM256_LS_MUL_PD(&buf[i + 4], vec_level);
		}
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void effect_level_stereo(DATA_T *buf, int32 count, double level)
{
	int32 i;
	if(level == 1.0)
		return;
	{
		__m256 vec_level = _mm256_set1_ps((float)level);
		for(i = 0; i < count; i += 8)
			MM256_LS_MUL_PS(&buf[i], vec_level);
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static void effect_level_stereo(DATA_T *buf, int32 count, double level)
{
	int32 i;
	if(level == 1.0)
		return;
	{
		__m128d vec_level = _mm_set1_pd(level);
		for(i = 0; i < count; i += 8){
			MM_LS_MUL_PD(&buf[i], vec_level);
			MM_LS_MUL_PD(&buf[i + 2], vec_level);
			MM_LS_MUL_PD(&buf[i + 4], vec_level);
			MM_LS_MUL_PD(&buf[i + 6], vec_level);
		}
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void effect_level_stereo(DATA_T *buf, int32 count, double level)
{
	int32 i;
	if(level == 1.0)
		return;
	{
		__m128 vec_level = _mm_set1_ps((float)level);
		for(i = 0; i < count; i += 8){
			MM_LS_MUL_PS(&buf[i], vec_level);
			MM_LS_MUL_PS(&buf[i + 4], vec_level);
		}
	}
}
#else /* floating-point implementation */
// change level stereo
static void effect_level_stereo(DATA_T *buf, int32 count, double level)
{
	int32 i;
	
	if(level == 1.0)
		return;
	for(i = 0; i < count; i++)
		buf[i] *= level;
}
#endif /* OPT_MODE == 1 */


#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
// source1(left)/source2(right) panning stereo
static void CALLINGCONV mix_parallel_effect(int32 *buf, int32 count, Info_P_Mix *ef)
{
	int32 i;
	int32 inputl, inputr;
	const int32 levell = TIM_FSCALE(ef->levell * ef->level, 24), levelr = TIM_FSCALE(ef->levelr * ef->level, 24);
	const int32 panll = TIM_FSCALE(ef->panll, 24), panlr = TIM_FSCALE(ef->panlr, 24);
	const int32 panrl = TIM_FSCALE(ef->panrl, 24), panrr = TIM_FSCALE(ef->panrr, 24);

	for (i = 0; i < count; i++) {
		inputl = imuldiv24(buf[i], levell);
		inputr = imuldiv24(buf[i + 1], levelr);
		/* panning */
		buf[i] = imuldiv24(inputl, panll) + imuldiv24(inputr, panrl);
		i++;
		buf[i] = imuldiv24(inputl, panlr) + imuldiv24(inputr, panrr);
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
// source1(left)/source2(right) panning stereo 
static void CALLINGCONV mix_parallel_effect(DATA_T *buf, int32 count, Info_P_Mix *ef)
{
	int32 i;	
	__m128 vec_levell = _mm_set1_ps(ef->level * ef->levell);
	__m128 vec_levelr = _mm_set1_ps(ef->level * ef->levelr);
	__m128 vec_panls = _mm_mul_ps(_mm_set_ps(ef->panlr, ef->panll, ef->panlr, ef->panll), vec_levell);
	__m128 vec_panrs = _mm_mul_ps(_mm_set_ps(ef->panrr, ef->panrl, ef->panrr, ef->panrl), vec_levelr);
	__m256 vec_panl = MM256_SET2X_PS(vec_panls, vec_panls);
	__m256 vec_panr = MM256_SET2X_PS(vec_panrs, vec_panrs);
		for(i = 0; i < count; i += 8){
		__m256 input, vtmp1, vtmp2;
		input = _mm256_load_ps(&buf[i]); // [0,1,2,3]
		vtmp1 = _mm256_shuffle_ps(input, input, 0x0); // [0,0,2,2]
		vtmp2 = _mm256_shuffle_ps(input, input, 0xf); // [1,1,3,3]
		_mm256_store_ps(&buf[i], MM256_FMA2_PS(vtmp1, vec_panl, vtmp2, vec_panr));
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
// source1(left)/source2(right) panning stereo 
static void CALLINGCONV mix_parallel_effect(DATA_T *buf, int32 count, Info_P_Mix *ef)
{
	int32 i;	
	__m128d vec_levell = _mm_set1_pd(ef->level * ef->levell);
	__m128d vec_levelr = _mm_set1_pd(ef->level * ef->levelr);
	__m128d vec_panls = _mm_mul_pd(_mm_set_pd(ef->panlr, ef->panll), vec_levell);
	__m128d vec_panrs = _mm_mul_pd(_mm_set_pd(ef->panrr, ef->panrl), vec_levelr);
	__m256d vec_panl = MM256_SET2X_PD(vec_panls, vec_panls);
	__m256d vec_panr = MM256_SET2X_PD(vec_panrs, vec_panrs);
		for(i = 0; i < count; i += 8){
		__m256d input, vtmp1, vtmp2;
		input = _mm256_load_pd(&buf[i]); // [0,1,2,3]
		vtmp1 = _mm256_shuffle_pd(input, input, 0x0); // [0,0,2,2]
		vtmp2 = _mm256_shuffle_pd(input, input, 0xf); // [1,1,3,3]
		_mm256_store_pd(&buf[i], MM256_FMA2_PD(vtmp1, vec_panl, vtmp2, vec_panr));
		input = _mm256_load_pd(&buf[i + 4]);
		vtmp1 = _mm256_shuffle_pd(input, input, 0x0); // [0,0,2,2]
		vtmp2 = _mm256_shuffle_pd(input, input, 0xf); // [1,1,3,3]
		_mm256_store_pd(&buf[i + 4], MM256_FMA2_PD(vtmp1, vec_panl, vtmp2, vec_panr));
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
// source1(left)/source2(right) panning stereo 
static void CALLINGCONV mix_parallel_effect(DATA_T *buf, int32 count, Info_P_Mix *ef)
{
	int32 i;
	__m128d vec_levell = _mm_set1_pd(ef->level * ef->levell);
	__m128d vec_levelr = _mm_set1_pd(ef->level * ef->levelr);
	__m128d vec_panl = _mm_mul_pd(_mm_set_pd(ef->panlr, ef->panll), vec_levell);
	__m128d vec_panr = _mm_mul_pd(_mm_set_pd(ef->panrr, ef->panrl), vec_levelr);
	for(i = 0; i < count; i += 4){
		__m128d input, vtmp1, vtmp2;
		input = _mm_load_pd(&buf[i]); // [0,1]
		vtmp1 = _mm_shuffle_pd(input, input, 0x0); // [0,0]
		vtmp2 = _mm_shuffle_pd(input, input, 0x3); // [1,1]
		_mm_store_pd(&buf[i], MM_FMA2_PD(vtmp1, vec_panl, vtmp2, vec_panr));
		input = _mm_load_pd(&buf[i + 2]); // [0,1]
		vtmp1 = _mm_shuffle_pd(input, input, 0x0); // [0,0]
		vtmp2 = _mm_shuffle_pd(input, input, 0x3); // [1,1]
		_mm_store_pd(&buf[i + 2], MM_FMA2_PD(vtmp1, vec_panl, vtmp2, vec_panr));
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
// source1(left)/source2(right) panning stereo 
static void CALLINGCONV mix_parallel_effect(DATA_T *buf, int32 count, Info_P_Mix *ef)
{
	int32 i;	
	__m128 vec_levell = _mm_set1_ps(ef->level * ef->levell);
	__m128 vec_levelr = _mm_set1_ps(ef->level * ef->levelr);
	__m128 vec_panl = _mm_mul_ps(_mm_set_ps(ef->panlr, ef->panll, ef->panlr, ef->panll), vec_levell);
	__m128 vec_panr = _mm_mul_ps(_mm_set_ps(ef->panrr, ef->panrl, ef->panrr, ef->panrl), vec_levelr);
	for(i = 0; i < count; i += 8){
		__m128 input, vtmp1, vtmp2;
		input = _mm_load_ps(&buf[i]); // [0,1,2,3]
		vtmp1 = _mm_shuffle_ps(input, input, 0xa0); // [0,0,2,2]
		vtmp2 = _mm_shuffle_ps(input, input, 0xf5); // [1,1,3,3]
		_mm_store_ps(&buf[i], MM_FMA2_PS(vtmp1, vec_panl, vtmp2, vec_panr));
		input = _mm_load_ps(&buf[i + 4]); // [0,1,2,3]
		vtmp1 = _mm_shuffle_ps(input, input, 0xa0); // [0,0,2,2]
		vtmp2 = _mm_shuffle_ps(input, input, 0xf5); // [1,1,3,3]
		_mm_store_ps(&buf[i + 4], MM_FMA2_PS(vtmp1, vec_panl, vtmp2, vec_panr));
	}
}
#else /* floating-point implementation */
// source1(left)/source2(right) panning stereo 
static void mix_parallel_effect(DATA_T *buf, int32 count, Info_P_Mix *ef)
{
	int32 i;
	DATA_T inputl, inputr;
	FLOAT_T levelL = ef->levell * ef->level;
	FLOAT_T levelR = ef->levelr * ef->level;

	for(i = 0; i < count; i++) {
		inputl = buf[i] * levelL;
		inputr = buf[i + 1] * levelR;
		/* panning */
		buf[i] = inputl * ef->panll + inputr * ef->panrl;
		i++;
		buf[i] = inputl * ef->panlr + inputr * ef->panrr;
	}
}
#endif /* OPT_MODE == 1 */

static double calc_tempo_gs(int val)
{


}

static double calc_tempo_xg(int val)
{
	// current_play_tempo = 500000 = 120bpm = 500ms
	// output ms
	return (double)500000.0 / (double)get_current_play_tempo() * 500 * tempo_table_xg[val & 0x7F]; 
}

static double calc_note1_sd(int val)
{
	// current_play_tempo = 500000 = 120bpm = 500ms
	// output ms
	return (double)500000.0 / (double)get_current_play_tempo() * 500 * note1_table_sd[clip_int(val, 0, 9)]; 
}

static double calc_note2_sd(int val)
{
	// current_play_tempo = 500000 = 120bpm = 500ms
	// output ms
	return (double)500000.0 / (double)get_current_play_tempo() * 500 * note1_table_sd[clip_int(val, 0, 21)]; 
}


#ifdef __BORLANDC__
static int isprime(int val)
#else
static inline int isprime(int val)
#endif
{
	int i;
	if (val == 2) {return 1;}
	if (val & 1) {
		for (i = 3; i < (int)sqrt((double)val) + 1; i += 2) {
			if ((val % i) == 0) {return 0;}
		}
		return 1; /* prime */
	} else {return 0;} /* even */
}







/*! delay */
static void free_delay(simple_delay *delay)
{
	if(delay->buf != NULL) {
		free(delay->buf);
		delay->buf = NULL;
	}
}

static void set_delay(simple_delay *delay, int32 size)
{
	if(size < 1) {size = 1;} 
	free_delay(delay);
	delay->buf = (DATA_T *)safe_malloc(sizeof(DATA_T) * size);
	if(delay->buf == NULL) {return;}
	delay->index = 0;
	delay->size = size;
	memset(delay->buf, 0, sizeof(DATA_T) * delay->size);
}

static inline void do_delay(DATA_T *stream, DATA_T *buf, int32 size, int32 *index)
{
	DATA_T output = buf[*index];
	buf[*index] = *stream;
	if (++*index >= size) {*index = 0;}
	*stream = output;
}

static inline void do_delay_add(DATA_T *in, DATA_T *out, simple_delay *delay)
{	
	DATA_T output = delay->buf[delay->index];
	delay->buf[delay->index] = *in;
	if (++delay->index >= delay->size) {delay->index = 0;}
	*out += output;
}


///r
/*! LFO (low frequency oscillator) */
static void init_lfo(lfo *lfo, double freq, int type, double phase)
{
	int32 i, cycle, diff;

	lfo->count = 0;
	lfo->freq = freq;
	if (lfo->freq < 0.05) {lfo->freq = 0.05;}
	cycle = (double)play_mode->rate / lfo->freq;
	if (cycle < 1) {cycle = 1;}
	lfo->cycle = cycle;
	lfo->icycle = TIM_FSCALE((SINE_CYCLE_LENGTH - 1) / (double)cycle, 24) - 0.5;
	diff = (double)SINE_CYCLE_LENGTH * phase * DIV_360;

	if(lfo->type != type) {	/* generate LFO waveform */
		switch(type) {
		case LFO_SINE:
			for(i = 0; i < SINE_CYCLE_LENGTH; i++)
				lfo->buf[i] = TIM_FSCALE((lookup_sine(i + diff) + 1.0) * DIV_2, 16);
			break;
		case LFO_TRIANGULAR:
			for(i = 0; i < SINE_CYCLE_LENGTH; i++)
				lfo->buf[i] = TIM_FSCALE((lookup_triangular(i + diff) + 1.0) * DIV_2, 16);
			break;
		case LFO_SAW1:
			for(i = 0; i < SINE_CYCLE_LENGTH; i++)
				lfo->buf[i] = TIM_FSCALE((lookup_saw1(i + diff) + 1.0) * DIV_2, 16);
			break;
		case LFO_SAW2:
			for(i = 0; i < SINE_CYCLE_LENGTH; i++)
				lfo->buf[i] = TIM_FSCALE((lookup_saw2(i + diff) + 1.0) * DIV_2, 16);
			break;
		case LFO_SQUARE:
			for(i = 0; i < SINE_CYCLE_LENGTH; i++)
				lfo->buf[i] = TIM_FSCALE((lookup_square(i + diff) + 1.0) * DIV_2, 16);
			break;
		default:
			for(i = 0; i < SINE_CYCLE_LENGTH; i++) {lfo->buf[i] = TIM_FSCALE(0.5, 16);}
			break;
		}
	}
	lfo->type = type;
}

/* returned value is between 0 and (1 << 16) */
static inline int32 do_lfo(lfo *lfo)
{
	int32 val;
	val = lfo->buf[imuldiv24(lfo->count, lfo->icycle)];
	if(++lfo->count >= lfo->cycle) {lfo->count = 0;}
	return val;
}


/*! modulated delay with allpass interpolation (for Chorus Effect,...) */
static void free_mod_delay(mod_delay *delay)
{
	if(delay->buf != NULL) {
		free(delay->buf);
		delay->buf = NULL;
	}
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void set_mod_delay(mod_delay *delay, int32 ndelay, int32 depth)
{
	int32 size = ndelay + depth + 1;
	free_mod_delay(delay);
	delay->buf = (int32 *)safe_malloc(sizeof(int32) * size);
	if(delay->buf == NULL) {return;}
	delay->rindex = 0;
	delay->windex = 0;
	delay->hist = 0;
	delay->ndelay = ndelay;
	delay->depth = depth;
	delay->size = size;
	memset(delay->buf, 0, sizeof(int32) * delay->size);
}

static inline void do_mod_delay(int32 *stream, mod_delay *delay, int32 lfoval)
{
	int32 t1, t2;
	if (++delay->windex >= delay->size) {delay->windex = 0;}
	t1 = delay->buf[delay->rindex];
	t2 = imuldiv24(lfoval, delay->depth);
	delay->rindex = delay->windex - delay->ndelay - (t2 >> 8);
	if (delay->rindex < 0) {delay->rindex += delay->size;}
	t2 = 0xFF - (t2 & 0xFF);
	delay->hist = t1 + imuldiv8(delay->buf[delay->rindex] - delay->hist, t2);
	delay->buf[delay->windex] = *stream;
	*stream = delay->hist;
}

#else /* floating-point implementation */
static void set_mod_delay(mod_delay *delay, int32 ndelay, int32 depth)
{
	int32 size = ndelay + depth + 1;
	free_mod_delay(delay);
	delay->buf = (DATA_T *)safe_large_malloc(sizeof(DATA_T) * size);
	if(delay->buf == NULL) {return;}
	delay->rindex = 0;
	delay->windex = 0;
	delay->hist2 = delay->hist = 0;
	delay->ndelay = ndelay;
	delay->depth = depth;
	delay->size = size;
	memset(delay->buf, 0, sizeof(DATA_T) * delay->size);
}

static inline void do_mod_delay(DATA_T *stream, mod_delay *delay, int32 lfoval)
{
	DATA_T t1;
	int32 t2;
	if (++(delay->windex) >= delay->size) {delay->windex = 0;}
	delay->rindex2 = delay->rindex; // for read_mod_delay()
	t1 = delay->buf[delay->rindex];
	t2 = imuldiv24(lfoval, delay->depth);
	delay->rindex = delay->windex - delay->ndelay - (t2 >> 8);
	if (delay->rindex < 0) {delay->rindex += delay->size;}
	delay->hist2 = delay->hist; // for read_mod_delay()
	delay->hist = t1 + (delay->buf[delay->rindex] - delay->hist) * (0xFF - (t2 & 0xFF)) * DIV_8BIT; // imuldiv8
	delay->buf[delay->windex] = *stream;
	*stream = delay->hist;
}
// read only after do_mod_delay() diff lfoval
static inline void read_mod_delay(DATA_T *stream, mod_delay *delay, int32 lfoval)
{
	DATA_T t1;
	int32 t2, index = delay->rindex2, out;
	
	t1 = delay->buf[index];
	t2 = imuldiv24(lfoval, delay->depth);
	index = delay->windex - delay->ndelay - (t2 >> 8);
	if (index < 0) {index += delay->size;}
	*stream = t1 + (delay->buf[index] - delay->hist2) * (0xFF - (t2 & 0xFF)) * DIV_8BIT; // imuldiv8
}
#endif /* OPT_MODE != 0 */


/*! modulated allpass filter with allpass interpolation (for Plate Reverberator,...) */
static void free_mod_allpass(mod_allpass *delay)
{
	if(delay->buf != NULL) {
		free(delay->buf);
		delay->buf = NULL;
	}
}

static void set_mod_allpass(mod_allpass *delay, int32 ndelay, int32 depth, double feedback)
{
	int32 size = ndelay + depth + 1;
	free_mod_allpass(delay);
	delay->buf = (DATA_T *)safe_malloc(sizeof(DATA_T) * size);
	if(delay->buf == NULL) {return;}
	delay->rindex = 0;
	delay->windex = 0;
	delay->hist = 0;
	delay->ndelay = ndelay;
	delay->depth = depth;
	delay->size = size;
	delay->feedback = feedback;
	delay->feedbacki = TIM_FSCALE(feedback, 24);
	memset(delay->buf, 0, sizeof(DATA_T) * delay->size);
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static inline void do_mod_allpass(int32 *stream, int32 *buf, int32 size, int32 *rindex, int32 *windex,
								  int32 ndelay, int32 depth, int32 lfoval, int32 *hist, int32 feedback)
{
	int t1, t2, t3;
	if (++*windex >= size) {*windex = 0;}
	t3 = *stream + imuldiv24(*hist, feedback);
	t1 = buf[*rindex];
	t2 = imuldiv24(lfoval, depth);
	*rindex = *windex - ndelay - (t2 >> 8);
	if (*rindex < 0) {*rindex += size;}
	t2 = 0xFF - (t2 & 0xFF);
	*hist = t1 + imuldiv8(buf[*rindex] - *hist, t2);
	buf[*windex] = t3;
	*stream = *hist - imuldiv24(t3, feedback);
}
#else /* floating-point implementation */
static inline void do_mod_allpass(DATA_T *stream, DATA_T *buf, int32 size, int32 *rindex, int32 *windex,
								  int32 ndelay, int32 depth, int32 lfoval, DATA_T *hist, FLOAT_T feedback)
{
	int t1, t2, t3;
	if (++*windex >= size) {*windex = 0;}
	t3 = *stream + *hist * feedback;
	t1 = buf[*rindex];
	t2 = imuldiv24(lfoval, depth);
	*rindex = *windex - ndelay - (t2 >> 8);
	if (*rindex < 0) {*rindex += size;}
	t2 = 0xFF - (t2 & 0xFF);
	*hist = t1 + (buf[*rindex] - *hist) * (FLOAT_T)t2 * DIV_8BIT;
	buf[*windex] = t3;
	*stream = *hist - t3 * feedback;
}
#endif /* OPT_MODE != 0 */

/* allpass filter */
static void free_allpass(allpass *allpass)
{
	if(allpass->buf != NULL) {
		free(allpass->buf);
		allpass->buf = NULL;
	}
}

static void set_allpass(allpass *allpass, int32 size, FLOAT_T feedback)
{
	if(allpass->buf != NULL) {
		free(allpass->buf);
		allpass->buf = NULL;
	}
	allpass->buf = (DATA_T *)safe_malloc(sizeof(DATA_T) * size);
	if(allpass->buf == NULL) {return;}
	allpass->index = 0;
	allpass->size = size;
	allpass->feedback = feedback;
	allpass->feedbacki = TIM_FSCALE(feedback, 24);
	memset(allpass->buf, 0, sizeof(DATA_T) * allpass->size);
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static inline void do_allpass(int32 *stream, int32 *buf, int32 size, int32 *index, int32 feedback)
{
	int32 bufout, output;
	bufout = buf[*index];
	output = *stream - imuldiv24(bufout, feedback);
	buf[*index] = output;
	if (++*index >= size) {*index = 0;}
	*stream = bufout + imuldiv24(output, feedback);
}
#else /* floating-point implementation */
static inline void do_allpass(DATA_T *stream, DATA_T *buf, int32 size, int32 *index, FLOAT_T feedback)
{
	DATA_T bufout, output;
	bufout = buf[*index];
	output = *stream - bufout * feedback;
	buf[*index] = output;
	if (++*index >= size) {*index = 0;}
	*stream = bufout + output * feedback;
}
#endif /* OPT_MODE != 0 */



///r
#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
#define WS_AMP_VALUE (double)((1 << (SAMPLE_BITS + AMP_BITS - 4)) - 1)
static const int32 ws_amp_max1 =  WS_AMP_VALUE * 0.80;
static const int32 ws_amp_min1 = -WS_AMP_VALUE * 0.80;
static const int32 ws_amp_max2 =  WS_AMP_VALUE * 0.90;
static const int32 ws_amp_min2 = -WS_AMP_VALUE * 0.90;
static const int32 ws_amp_maxl =  WS_AMP_VALUE * 1.00;
static const int32 ws_amp_minl = -WS_AMP_VALUE * 1.00;
static const double div_amp_value = (0.15 / WS_AMP_VALUE);
static const double mlt_amp_value = (WS_AMP_VALUE / 0.15);

static void do_clipping_dummy(int32 *stream, int32 d) {}

static void do_clipping0(int32 *stream, int32 d)
{
	int32 x = imuldiv24(*stream, d);
	x = (x > ws_amp_max1) ? ws_amp_max1 : (x < ws_amp_min1) ? ws_amp_min1 : x;
	*stream = x;
}

static void do_clipping1(int32 *stream, int32 d)
{
	int32 x = imuldiv24(*stream, d);
	x = (x > ws_amp_max1) ? (ws_amp_max1 + (sqrt(x - ws_amp_max1))) : (x < ws_amp_min1) ? (ws_amp_min1 - sqrt(-(x - ws_amp_min1))) : x;
	*stream = x;
}

static void do_clipping2(int32 *stream, int32 d)
{
	int32 x = imuldiv24(*stream, d);
//	x = (x > ws_amp_max2) ? ws_amp_max2 : (x < ws_amp_min2) ? ws_amp_min2 : x;
	x = (x > ws_amp_max2) ? (ws_amp_max2 - (sqrt(x - ws_amp_max2))) : (x < ws_amp_min2) ? (ws_amp_min2 + sqrt(-(x - ws_amp_min2))) : x;
	*stream = x;
}

static void do_clipping3(int32 *stream, int32 d)
{
	int32 x = imuldiv24(*stream, d);
	x = (x > ws_amp_max1) ? (ws_amp_max1 + (sqrt(x - ws_amp_max1))) : (x < ws_amp_min1) ? (ws_amp_min1 - sqrt(-(x - ws_amp_min1))) : x;
	x = x * (1.1f - (double)abs(x) * div_amp_value);
	*stream = x;
}

static void do_clipping4(int32 *stream, int32 d)
{
	int32 x = imuldiv24(*stream, d);
//	x = (x > ws_amp_max2) ? ws_amp_max2 : (x < ws_amp_min2) ? ws_amp_min2 : x;
	x = (x > ws_amp_max2) ? (ws_amp_max2 - (sqrt(x - ws_amp_max2))) : (x < ws_amp_min2) ? (ws_amp_min2 + sqrt(-(x - ws_amp_min2))) : x;
	x = x * (1.1f - (double)abs(x) * div_amp_value);
	*stream = x;
}

static void do_clipping5(DATA_T *stream, double d)
{
	FLOAT_T x = *stream * div_amp_value;
	x = (x < 0.0) ? -pow(-x, d) : pow(x, d); // d=1/gain
	*stream = x * mlt_amp_value;
}

#else /* floating-point implementation */


#ifdef EFFECT_LEVEL_FLOAT // level float
#define WS_AMP_VALUE (double)(1.0) // ??
#else // level int
#define WS_AMP_VALUE (double)((1<<(SAMPLE_BITS + AMP_BITS - 4))-1)
#endif
const double ws_amp_max1 =  WS_AMP_VALUE * 0.80;
const double ws_amp_min1 = -WS_AMP_VALUE * 0.80;
const double ws_amp_max2 =  WS_AMP_VALUE * 0.90;
const double ws_amp_min2 = -WS_AMP_VALUE * 0.90;
const double ws_amp_maxl =  WS_AMP_VALUE * 1.00;
const double ws_amp_minl = -WS_AMP_VALUE * 1.00;
const double div_amp_value = (0.15 / WS_AMP_VALUE);
const double mlt_amp_value = (WS_AMP_VALUE / 0.15);

static void do_clipping_dummy(DATA_T *stream, double d) {}

static void do_clipping0(DATA_T *stream, double d)
{
	FLOAT_T	x = *stream * d;
	x = (x > ws_amp_max1) ? ws_amp_max1 : (x < ws_amp_min1) ? ws_amp_min1 : x;
	*stream = x;
}

static void do_clipping1(DATA_T *stream, double d)
{
	FLOAT_T	x = *stream * d;
	x = (x > ws_amp_max1) ? (ws_amp_max1 + (sqrt(x - ws_amp_max1))) : (x < ws_amp_min1) ? (ws_amp_min1 - sqrt(-(x - ws_amp_min1))) : x;
	*stream = x;
}

static void do_clipping2(DATA_T *stream, double d)
{
	FLOAT_T	x = *stream * d;
//	x = (x > ws_amp_max2) ? ws_amp_max2 : (x < ws_amp_min2) ? ws_amp_min2 : x;
	x = (x > ws_amp_max2) ? (ws_amp_max2 - (sqrt(x - ws_amp_max2))) : (x < ws_amp_min2) ? (ws_amp_min2 + sqrt(-(x - ws_amp_min2))) : x;
	*stream = x;
}

static void do_clipping3(DATA_T *stream, double d)
{
	FLOAT_T	x = *stream * d;
	x = (x > ws_amp_max1) ? (ws_amp_max1 + (sqrt(x - ws_amp_max1))) : (x < ws_amp_min1) ? (ws_amp_min1 - sqrt(-(x - ws_amp_min1))) : x;
	x = x * (1.1 - fabs(x) * div_amp_value);
	*stream = x;
}

static void do_clipping4(DATA_T *stream, double d)
{
	FLOAT_T x = *stream * d;
//	x = (x > ws_amp_max2) ? ws_amp_max2 : (x < ws_amp_min2) ? ws_amp_min2 : x;
	x = (x > ws_amp_max2) ? (ws_amp_max2 - (sqrt(x - ws_amp_max2))) : (x < ws_amp_min2) ? (ws_amp_min2 + sqrt(-(x - ws_amp_min2))) : x;
	x = x * (1.1 - fabs(x) * div_amp_value);
	*stream = x;
}

static void do_clipping5(DATA_T *stream, double d)
{
	FLOAT_T x = *stream * div_amp_value;
	x = (x < 0.0) ? -pow(-x, d) : pow(x, d); // d=1/gain
	*stream = x * mlt_amp_value;
}

#endif /* OPT_MODE != 0 */


/*! drive */
/*
type
0: linear <-> clipping
1: linear <-> sq/sqrt
2: linear <-> tanh
3: linear <-> power (0.0:linear 
4: sq/sqrt <-> clipping <-> tanh (0.5:clipping
6: clipping <-> triangle
7: clipping <-> sine
8: tanh <-> triangle
9: tanh <-> sine
*/

static void init_drive(Drive *drv, int type, double curve, double clip, double drive)
{
	int i;
	FLOAT_T clip_level, div_amp_level;
	FLOAT_T v1, v2, out;
	const FLOAT_T div_size = DRIVE_SCALE_MAX / (FLOAT_T)DRIVE_TABLE_LENGTH;

	if(clip < 0.01) clip = 0.01;
	clip_level = ((FLOAT_T)WS_AMP_VALUE * 0.33) * clip;
	div_amp_level = 3.0 / ((FLOAT_T)WS_AMP_VALUE * 0.33) * drive;
	drv->cnv = (FLOAT_T)DRIVE_BASE_LENGTH * div_amp_level;
	drv->cnvi = TIM_FSCALE((FLOAT_T)(1 << DRIVE_INPUT_BIT) * div_amp_level, 24);

	switch(type){
	default:
	case 0: // linear <-> clipping
		for(i = 0; i < (DRIVE_TABLE_LENGTH + 1); i++){
			v1 = div_size * i;
			v2 = v1;
			if(v2 > 1.0) v2 = 1.0;
			out = v1 + (v2 - v1) * curve;
			out *= clip_level;
			drv->dc[i] = out;
		}
		break;
	case 1: // linear <-> sq/sqrt
		for(i = 0; i < (DRIVE_TABLE_LENGTH + 1); i++){
			v1 = div_size * i;
			v2 = v1;
			v2 = (v2 > 1.0) ? sqrt(v2) : sq(v2);
			out = v1 + (v2 - v1) * curve;
			out *= clip_level;
			drv->dc[i] = out;
		}
		break;
	case 2: // linear <-> tanh
		for(i = 0; i < (DRIVE_TABLE_LENGTH + 1); i++){
			v1 = div_size * i;
			v2 = v1;
			v2 = tanh(v2 * M_PI);
			out = v1 + (v2 - v1) * curve;
			out *= clip_level;
			drv->dc[i] = out;
		}
		break;
	case 3: // linear <-> power (0.0:linear 
		curve = 1.0 - curve;
		if(curve >= 1.0) curve = 1.0;
		if(curve <= 0.0) curve = 0.001;
		for(i = 0; i < (DRIVE_TABLE_LENGTH + 1); i++){
			v1 = div_size * i;
			out = pow(v1, curve);
			out *= clip_level;
			drv->dc[i] = out;
		}
		break;
	case 4: // sq/sqrt <-> clipping <-> tanh
		for(i = 0; i < (DRIVE_TABLE_LENGTH + 1); i++){
			v1 = div_size * i;
			v2 = v1;
			if(curve < 0.5){	
				v1 = (v1 > 1.0) ? sqrt(v1) : sq(v1);			
				if(v2 > 1.0) v2 = 1.0;
				curve *= 2.0;
			}else{
				if(v1 > 1.0) v1 = 1.0;
				v2 = tanh(v2 * M_PI);
				curve *= 2.0;
				curve -= 1.0;
			}
			out = v1 + (v2 - v1) * curve;
			out *= clip_level;
			drv->dc[i] = out;
		}
		break;
	case 6: // clipping <-> triangle
		for(i = 0; i < (DRIVE_TABLE_LENGTH + 1); i++){
			v1 = div_size * i;
			v2 = v1;
			if(v1 > 1.0) v1 = 1.0;
			v2 *= 4;
			v2 -= floor(v2);
			v2 *= DIV_4;
			if(v2 > 1.0) v2 = 2.0 - v2;
			if(v2 < 1.0) v2 = v2;
			else if(v1 < 3.0) v2 = 2.0 - v2;
			else if(v1 < 5.0) v2 = -2.0 + v2;
			out = v1 + (v2 - v1) * curve;
			out *= clip_level;
			drv->dc[i] = out;
		}
		break;
	case 7: // clipping <-> sine
		for(i = 0; i < (DRIVE_TABLE_LENGTH + 1); i++){
			v1 = div_size * i;
			v2 = v1;
			if(v1 > 1.0) v1 = 1.0;
			v2 = sin(v2 * M_PI * 0.5);			
			out = v1 + (v2 - v1) * curve;
			out *= clip_level;
			drv->dc[i] = out;
		}
		break;
	case 8: // tanh <-> triangle
		for(i = 0; i < (DRIVE_TABLE_LENGTH + 1); i++){
			v1 = div_size * i;
			v2 = v1;
			v1 = tanh(v1 * M_PI);
			v2 *= 4;
			v2 -= floor(v2);
			v2 *= DIV_4;
			if(v2 > 1.0) v2 = 2.0 - v2;
			if(v2 < 1.0) v2 = v2;
			else if(v1 < 3.0) v2 = 2.0 - v2;
			else if(v1 < 5.0) v2 = -2.0 + v2;
			out = v1 + (v2 - v1) * curve;
			out *= clip_level;
			drv->dc[i] = out;
		}
		break;
	case 9: // tanh <-> sine
		for(i = 0; i < (DRIVE_TABLE_LENGTH + 1); i++){
			v1 = div_size * i;
			v2 = v1;
			v1 = tanh(v1 * M_PI);
			v2 = sin(v2 * M_PI * 0.5);
			out = v1 + (v2 - v1) * curve;
			out *= clip_level;
			drv->dc[i] = out;
		}
		break;
	}
	drv->dc[0] = 0;
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */


static inline int32 imuldiv_drive(int32 a, int32 b) {
#if (OPT_MODE == 1) && defined(SUPPORT_ASM_INTEL) /* fixed-point implementation */
#if defined(SUPPORT_ASM_INTEL)
	_asm {
		mov eax, a
		mov edx, b
		imul edx
		shr eax, DRIVE_FRAC_BIT
		shl edx, (32 - DRIVE_FRAC_BIT)
		or  eax, edx
	}
#else	
	return (int32)(((int64)a * b) >> DRIVE_FRAC_BIT);
#endif	
#else	
	return (int32)(((int64)a * b) >> DRIVE_FRAC_BIT));
#endif
}

static void do_drive_mono(Drive *drv, int32 *inout)
{	
	int32 index;
	int32 in, sign, v1, v2, fp;
	
	in = *inout;
	sign = (in < 0) ? (-1) : (1);
	in = abs(in);
	in = imuldiv24(in, drv->cnvi);
	index = in >> DRIVE_FRAC_BIT;
	fp = in & DRIVE_FRAC_MASK;
	if(index >= DRIVE_TABLE_LENGTH){
		index = DRIVE_TABLE_LENGTH - 1;
		fp = DRIVE_FRAC_MASK;
	}
	v1 = drv->dc[index];
	v2 = drv->dc[++index];
	*inout = (v1 + imuldiv_drive(v2 - v1, fp)) * sign;
}

static void do_drive_stereo(Drive *drv, int32 *inout)
{
	int32 indexL, indexR;
	int32 inL, signL, v1L, v2L, fpL;
	int32 inR, signR, v1R, v2R, fpR;
	
	inL = inout[0];
	inR = inout[1];
	signL = (inL < 0) ? (-1) : (1);
	signR = (inR < 0) ? (-1) : (1);	
	inL = abs(inL);
	inR = abs(inR);
	inL = imuldiv24(inL, drv->cnvi);
	inR = imuldiv24(inR, drv->cnvi);
	indexL = inL >> DRIVE_FRAC_BIT;
	indexR = inR >> DRIVE_FRAC_BIT;
	fpL = inL & DRIVE_FRAC_MASK;
	fpR = inR & DRIVE_FRAC_MASK;
	if(indexL >= DRIVE_TABLE_LENGTH){
		indexL = DRIVE_TABLE_LENGTH - 1;
		fpL = DRIVE_FRAC_MASK;
	}
	if(indexR >= DRIVE_TABLE_LENGTH){
		indexR = DRIVE_TABLE_LENGTH - 1;
		fpR = DRIVE_FRAC_MASK;
	}
	v1L = drv->dc[indexL];
	v1R = drv->dc[indexR];
	v2L = drv->dc[++indexL];
	v2R = drv->dc[++indexR];
	inout[0] = (v1L + imuldiv_drive(v2L - v1L, fpL)) * signL;
	inout[1] = (v1R + imuldiv_drive(v2R - v1R, fpR)) * signR;
}

#else /* floating-point implementation */


static void do_drive_mono(Drive *drv, DATA_T *inout)
{
	int32 index;
	FLOAT_T in, sign, v1, v2, fp;
	
	in = *inout;
	sign = (in < 0) ? (-1.0) : (1.0);
	in *= drv->cnv * sign;
	fp = floor(in);
	index = fp;
	fp = in - fp;
	if(index >= DRIVE_TABLE_LENGTH){
		index = DRIVE_TABLE_LENGTH - 1;
		fp = 1.0;
	}
	v1 = drv->dc[index];
	v2 = drv->dc[index + 1];
	*inout = (v1 + (v2 - v1) * fp) * sign;
}

static void do_drive_stereo(Drive *drv, DATA_T *inout)
{
	int32 indexL, indexR;
	FLOAT_T inL, signL, v1L, v2L, fpL;
	FLOAT_T inR, signR, v1R, v2R, fpR;

	inL = inout[0];
	inR = inout[1];
	signL = (inL < 0) ? (-1.0) : (1.0);
	signR = (inR < 0) ? (-1.0) : (1.0);
	inL *= drv->cnv * signL;
	inR *= drv->cnv * signR;
	fpL = floor(inL);
	fpR = floor(inR);
	indexL = fpL;
	indexR = fpR;
	fpL = inL - fpL;
	fpR = inR - fpR;
	if(indexL >= DRIVE_TABLE_LENGTH){
		indexL = DRIVE_TABLE_LENGTH - 1;
		fpL = 1.0;
	}
	if(indexR >= DRIVE_TABLE_LENGTH){
		indexR = DRIVE_TABLE_LENGTH - 1;
		fpR = 1.0;
	}
	v1L = drv->dc[indexL];
	v1R = drv->dc[indexR];
	v2L = drv->dc[++indexL];
	v2R = drv->dc[++indexR];
	inout[0] = (v1L + (v2L - v1L) * fpL) * signL;
	inout[1] = (v1R + (v2R - v1R) * fpR) * signR;
}
#endif


// white noise (rand
// -1.0 ~ 1.0
static inline FLOAT_T get_white_noise(void)
{
	return (FLOAT_T)((int32)(rand() & 0x7FFFUL) - M_14BIT) * DIV_14BIT;
}

// 0.0 ~ 1.0
static inline FLOAT_T get_white_noise_p(void)
{
	return (FLOAT_T)(rand() & 0x7FFFUL) * DIV_15BIT;
}



// pink noise
static void init_pink_noise(pink_noise *p)
{
	p->b0 = p->b1 = p->b2 = p->b3 = p->b4 = p->b5 = p->b6 = 0;
}

static float get_pink_noise(pink_noise *p)
{
	float b0 = p->b0, b1 = p->b1, b2 = p->b2, b3 = p->b3,
	   b4 = p->b4, b5 = p->b5, b6 = p->b6, pink, white;

	white = genrand_real1() * 2.0 - 1.0;
	b0 = 0.99886 * b0 + white * 0.0555179;
	b1 = 0.99332 * b1 + white * 0.0750759;
	b2 = 0.96900 * b2 + white * 0.1538520;
	b3 = 0.86650 * b3 + white * 0.3104856;
	b4 = 0.55000 * b4 + white * 0.5329522;
	b5 = -0.7616 * b5 - white * 0.0168980;
	pink = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;
	b6 = white * 0.115926;
	pink *= 0.22;
	pink = (pink > 1.0) ? 1.0 : (pink < -1.0) ? -1.0 : pink;

	p->b0 = b0, p->b1 = b1, p->b2 = b2, p->b3 = b3,
		p->b4 = b4, p->b5 = b5, p->b6 = b6;

	return pink;
}

float get_pink_noise_light(pink_noise *p)
{
	float b0 = p->b0, b1 = p->b1, b2 = p->b2, pink, white;

	white = genrand_real1() * 2.0 - 1.0;
	b0 = 0.99765 * b0 + white * 0.0990460;
	b1 = 0.96300 * b1 + white * 0.2965164;
	b2 = 0.57000 * b2 + white * 1.0526913;
	pink = b0 + b1 + b2 + white * 0.1848;
	pink *= 0.22;
	pink = (pink > 1.0) ? 1.0 : (pink < -1.0) ? -1.0 : pink;

	p->b0 = b0, p->b1 = b1, p->b2 = b2;

	return pink;
}





static void init_3d_locate(Info3DLocate *info)
{
	const double delay_time[2] = {3.030, 0.7575,};
	if(!info->init){
		info->init = 1;
		info->prev_out = -1;
		init_sample_filter(&info->side, 4000.0, 0, FILTER_LPF6);
		init_sample_filter(&info->back, 3000.0, 0, FILTER_LPF_BW);
	}
	if(info->out != info->prev_out){
		info->prev_out = info->out;
		free_delay(&(info->delay));		
		set_delay(&(info->delay), (int32)(delay_time[info->out] * playmode_rate_ms));
	}
}

static void uninit_3d_locate(Info3DLocate *info)
{
	if(!info->init)
		return;
	info->init = 0;
	free_delay(&(info->delay));
}

static void do_3d_locate(Info3DLocate *info, DATA_T *inout, FLOAT_T azimuth)
{
	FLOAT_T dirL, subL, dirR, subR, dirB, subB;
	DATA_T tmp, flt_back, flt_side;
	DATA_T input = inout[0];
	
	dirB = fabs(azimuth);
	dirB *= dirB;
	subB = 1.0 - dirB;
	if(azimuth < 0){
		dirL = 0.0;
		dirR = 1.0 - fabs(azimuth * 2.0 + 1.0);
	}else{
		dirR = 0.0;
		dirL = 1.0 - fabs(azimuth * 2.0 - 1.0);
	}
	subL = 1.0 - dirL;
	subR = 1.0 - dirR;
	flt_back = input;
	sample_filter_left(&info->back, &flt_back);
	flt_side = tmp = flt_back * dirB + input * subB;
	sample_filter_left(&info->side, &flt_side);	
	do_delay(&flt_side, info->delay.buf, info->delay.size, &info->delay.index);	
	inout[0] = flt_side * dirL + tmp * subL;
	inout[1] = flt_side * dirR + tmp * subR;
}



void init_pre_lpf(InfoPreFilter *info)
{
#ifdef SYS_EFFECT_PRE_LPF
	set_sample_filter_type(&info->fcL, FILTER_LPF6);
	set_sample_filter_freq(&info->fcL, info->freqL);
	set_sample_filter_reso(&info->fcL, 0);
#endif
}

static void do_pre_lpf(DATA_T *buf, int32 count, InfoPreFilter *info)
{
#ifdef SYS_EFFECT_PRE_LPF
	buffer_filter_stereo(&info->fcL, buf, count);
#endif
}

static void init_pre_bpf(InfoPreFilter *info)
{
#ifdef SYS_EFFECT_PRE_LPF
	set_sample_filter_type(&info->fcL, FILTER_LPF6);
	set_sample_filter_freq(&info->fcL, info->freqL);
	set_sample_filter_reso(&info->fcL, 0);
	set_sample_filter_type(&info->fcH, FILTER_HPF6);
	set_sample_filter_freq(&info->fcH, info->freqH);
	set_sample_filter_reso(&info->fcH, 0);
#endif
}

static void do_pre_bpf(DATA_T *buf, int32 count, InfoPreFilter *info)
{
#ifdef SYS_EFFECT_PRE_LPF
	int i;

	buffer_filter_stereo(&info->fcL, buf, count);
	buffer_filter_stereo(&info->fcH, buf, count);	
#endif
}




/********************************** EFFECT core **********************************/

/*                          */
/*  Standard Reverb Effect  */
/*                          */
#define REV_VAL0         5.3
#define REV_VAL1        10.5
#define REV_VAL2        44.12
#define REV_VAL3        21.0

static double gs_revchar_to_roomsize(int character)
{
	double rs;
	switch(character) {
	case 0: rs = 1.0;	break;	/* Room 1 */
	case 1: rs = 0.94;	break;	/* Room 2 */
	case 2: rs = 0.97;	break;	/* Room 3 */
	case 3: rs = 0.90;	break;	/* Hall 1 */
	case 4: rs = 0.85;	break;	/* Hall 2 */
	default: rs = 1.0;	break;	/* Plate, Delay, Panning Delay */
	}
	return rs;
}

static double gs_revchar_to_level(int character)
{
	double level;
	switch(character) {
	case 0: level = 0.744025605;	break;	/* Room 1 */
	case 1: level = 1.224309745;	break;	/* Room 2 */
	case 2: level = 0.858592403;	break;	/* Room 3 */
	case 3: level = 1.0471802;	break;	/* Hall 1 */
	case 4: level = 1.0;	break;	/* Hall 2 */
	case 5: level = 0.865335496;	break;	/* Plate */
	default: level = 1.0;	break;	/* Delay, Panning Delay */
	}
	return level;
}

static double gs_revchar_to_rt(int character)
{
	double rt;
	switch(character) {
	case 0: rt = 0.516850262;	break;	/* Room 1 */
	case 1: rt = 1.004226004;	break;	/* Room 2 */
	case 2: rt = 0.691046825;	break;	/* Room 3 */
	case 3: rt = 0.893006004;	break;	/* Hall 1 */
	case 4: rt = 1.0;	break;	/* Hall 2 */
	case 5: rt = 0.538476488;	break;	/* Plate */
	default: rt = 1.0;	break;	/* Delay, Panning Delay */
	}
	return rt;
}

static void init_standard_reverb(InfoStandardReverb *info)
{
	double time;
	info->ta = info->tb = 0;
	info->HPFL = info->HPFR = info->LPFL = info->LPFR = info->EPFL = info->EPFR = 0;
	info->spt0 = info->spt1 = info->spt2 = info->spt3 = 0;
	time = info->rev_time_sec * info->rev_rt / reverb_time_table[64] * 0.8;
	info->rpt0 = REV_VAL0 * playmode_rate_ms * time;
	info->rpt1 = REV_VAL1 * playmode_rate_ms * time;
	info->rpt2 = REV_VAL2 * playmode_rate_ms * time;
	info->rpt3 = REV_VAL3 * playmode_rate_ms * time;
	while (!isprime(info->rpt0)) {info->rpt0++;}
	while (!isprime(info->rpt1)) {info->rpt1++;}
	while (!isprime(info->rpt2)) {info->rpt2++;}
	while (!isprime(info->rpt3)) {info->rpt3++;}
	set_delay(&(info->buf0_L), info->rpt0 + 1);
	set_delay(&(info->buf0_R), info->rpt0 + 1);
	set_delay(&(info->buf1_L), info->rpt1 + 1);
	set_delay(&(info->buf1_R), info->rpt1 + 1);
	set_delay(&(info->buf2_L), info->rpt2 + 1);
	set_delay(&(info->buf2_R), info->rpt2 + 1);
	set_delay(&(info->buf3_L), info->rpt3 + 1);
	set_delay(&(info->buf3_R), info->rpt3 + 1);
	info->fbklev = 0.12;
	info->nmixlev = 0.7;
	info->cmixlev = 0.9;
	info->monolev = 0.7;
	info->hpflev = 0.5;
	info->lpflev = 0.45;
	info->lpfinp = 0.55;
	info->epflev = 0.4;
	info->epfinp = 0.48;
	info->width = info->rev_width;
	info->wet = 2.0 * info->rev_wet;
	info->fbklevi = TIM_FSCALE(info->fbklev, 24);
	info->nmixlevi = TIM_FSCALE(info->nmixlev, 24);
	info->cmixlevi = TIM_FSCALE(info->cmixlev, 24);
	info->monolevi = TIM_FSCALE(info->monolev, 24);
	info->hpflevi = TIM_FSCALE(info->hpflev, 24);
	info->lpflevi = TIM_FSCALE(info->lpflev, 24);
	info->lpfinpi = TIM_FSCALE(info->lpfinp, 24);
	info->epflevi = TIM_FSCALE(info->epflev, 24);
	info->epfinpi = TIM_FSCALE(info->epfinp, 24);
	info->widthi = TIM_FSCALE(info->width, 24);
	info->weti = TIM_FSCALE(info->wet, 24);
}

static void free_standard_reverb(InfoStandardReverb *info)
{
	free_delay(&(info->buf0_L));
	free_delay(&(info->buf0_R));
	free_delay(&(info->buf1_L));
	free_delay(&(info->buf1_R));
	free_delay(&(info->buf2_L));
	free_delay(&(info->buf2_R));
	free_delay(&(info->buf3_L));
	free_delay(&(info->buf3_R));
}

/*! Standard Reverberator; this implementation is specialized for system effect. */
#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void CALLINGCONV do_standard_reverb(int32 *buf, int32 count, InfoStandardReverb *info)
{
	int32 i, fixp, s, t;
	int32 spt0 = info->spt0, spt1 = info->spt1, spt2 = info->spt2, spt3 = info->spt3,
		ta = info->ta, tb = info->tb, HPFL = info->HPFL, HPFR = info->HPFR,
		LPFL = info->LPFL, LPFR = info->LPFR, EPFL = info->EPFL, EPFR = info->EPFR;
	int32 *buf0_L = info->buf0_L.buf, *buf0_R = info->buf0_R.buf,
		*buf1_L = info->buf1_L.buf, *buf1_R = info->buf1_R.buf,
		*buf2_L = info->buf2_L.buf, *buf2_R = info->buf2_R.buf,
		*buf3_L = info->buf3_L.buf, *buf3_R = info->buf3_R.buf;
	const int32 fbklevi = info->fbklevi, cmixlevi = info->cmixlevi,
		hpflevi = info->hpflevi, lpflevi = info->lpflevi, lpfinpi = info->lpfinpi,
		epflevi = info->epflevi, epfinpi = info->epfinpi, widthi = info->widthi,
		rpt0 = info->rpt0, rpt1 = info->rpt1, rpt2 = info->rpt2, rpt3 = info->rpt3, weti = info->weti;

	if (count == MAGIC_INIT_EFFECT_INFO) {
		init_standard_reverb(info);
		return;
	} else if (count == MAGIC_FREE_EFFECT_INFO) {
		free_standard_reverb(info);
		return;
	}
	for (i = 0; i < count; i++)
	{
		/* L */
		fixp = buf[i];

		LPFL = imuldiv24(LPFL, lpflevi) + imuldiv24(buf2_L[spt2] + tb, lpfinpi) + imuldiv24(ta, widthi);
		ta = buf3_L[spt3];
		s  = buf3_L[spt3] = buf0_L[spt0];
		buf0_L[spt0] = -LPFL;

		t = imuldiv24(HPFL + fixp, hpflevi);
		HPFL = t - fixp;

		buf2_L[spt2] = imuldiv24(s - imuldiv24(fixp, fbklevi), cmixlevi);
		tb = buf1_L[spt1];
		buf1_L[spt1] = t;

		EPFL = imuldiv24(EPFL, epflevi) + imuldiv24(ta, epfinpi);
		buf[i] = imuldiv24(ta + EPFL, weti);

		/* R */
		fixp = buf[++i];

		LPFR = imuldiv24(LPFR, lpflevi) + imuldiv24(buf2_R[spt2] + tb, lpfinpi) + imuldiv24(ta, widthi);
		ta = buf3_R[spt3];
		s  = buf3_R[spt3] = buf0_R[spt0];
		buf0_R[spt0] = LPFR;

		t = imuldiv24(HPFR + fixp, hpflevi);
		HPFR = t - fixp;

		buf2_R[spt2] = imuldiv24(s - imuldiv24(fixp, fbklevi), cmixlevi);
		tb = buf1_R[spt1];
		buf1_R[spt1] = t;

		EPFR = imuldiv24(EPFR, epflevi) + imuldiv24(ta, epfinpi);
		buf[i] = imuldiv24(ta + EPFR, weti);

		if (++spt0 >= rpt0) { spt0 = 0; }
		if (++spt1 >= rpt1) { spt1 = 0; }
		if (++spt2 >= rpt2) { spt2 = 0; }
		if (++spt3 >= rpt3) { spt3 = 0; }
	}
	info->spt0 = spt0, info->spt1 = spt1, info->spt2 = spt2, info->spt3 = spt3,
	info->ta = ta, info->tb = tb, info->HPFL = HPFL, info->HPFR = HPFR,
	info->LPFL = LPFL, info->LPFR = LPFR, info->EPFL = EPFL, info->EPFR = EPFR;
}

/*! Standard Monoral Reverberator; this implementation is specialized for system effect. */
static void CALLINGCONV do_standard_reverb_mono(DATA_T *buf, int32 count, InfoStandardReverb *info)
{
	int32 i, fixp, s, t;
	int32 spt0 = info->spt0, spt1 = info->spt1, spt2 = info->spt2, spt3 = info->spt3,
		ta = info->ta, tb = info->tb, HPFL = info->HPFL, HPFR = info->HPFR,
		LPFL = info->LPFL, LPFR = info->LPFR, EPFL = info->EPFL, EPFR = info->EPFR;
	int32 *buf0_L = info->buf0_L.buf, *buf0_R = info->buf0_R.buf,
		*buf1_L = info->buf1_L.buf, *buf1_R = info->buf1_R.buf,
		*buf2_L = info->buf2_L.buf, *buf2_R = info->buf2_R.buf,
		*buf3_L = info->buf3_L.buf, *buf3_R = info->buf3_R.buf;
	const int32 fbklevi = info->fbklevi, nmixlevi = info->nmixlevi, monolevi = info->monolevi,
		hpflevi = info->hpflevi, lpflevi = info->lpflevi, lpfinpi = info->lpfinpi,
		epflevi = info->epflevi, epfinpi = info->epfinpi, widthi = info->widthi,
		rpt0 = info->rpt0, rpt1 = info->rpt1, rpt2 = info->rpt2, rpt3 = info->rpt3, weti = info->weti;

	if (count == MAGIC_INIT_EFFECT_INFO) {
		init_standard_reverb(info);
		return;
	} else if (count == MAGIC_FREE_EFFECT_INFO) {
		free_standard_reverb(info);
		return;
	}
	for (i = 0; i < count; i++)
	{
		/* L */
		fixp = imuldiv24(buf[i], monolevi);

		LPFL = imuldiv24(LPFL, lpflevi) + imuldiv24(buf2_L[spt2] + tb, lpfinpi) + imuldiv24(ta, widthi);
		ta = buf3_L[spt3];
		s  = buf3_L[spt3] = buf0_L[spt0];
		buf0_L[spt0] = -LPFL;

		t = imuldiv24(HPFL + fixp, hpflevi);
		HPFL = t - fixp;

		buf2_L[spt2] = imuldiv24(s - imuldiv24(fixp, fbklevi), nmixlevi);
		tb = buf1_L[spt1];
		buf1_L[spt1] = t;

		/* R */
		LPFR = imuldiv24(LPFR, lpflevi) + imuldiv24(buf2_R[spt2] + tb, lpfinpi) + imuldiv24(ta, widthi);
		ta = buf3_R[spt3];
		s  = buf3_R[spt3] = buf0_R[spt0];
		buf0_R[spt0] = LPFR;

		t = imuldiv24(HPFR + fixp, hpflevi);
		HPFR = t - fixp;

		buf2_R[spt2] = imuldiv24(s - imuldiv24(fixp, fbklevi), nmixlevi);
		tb = buf1_R[spt1];
		buf1_R[spt1] = t;

		EPFR = imuldiv24(EPFR, epflevi) + imuldiv24(ta, epfinpi);
		buf[i] = imuldiv24(ta + EPFR, weti);

		if (++spt0 >= rpt0) { spt0 = 0; }
		if (++spt1 >= rpt1) { spt1 = 0; }
		if (++spt2 >= rpt2) { spt2 = 0; }
		if (++spt3 >= rpt3) { spt3 = 0; }
	}
	info->spt0 = spt0, info->spt1 = spt1, info->spt2 = spt2, info->spt3 = spt3,
	info->ta = ta, info->tb = tb, info->HPFL = HPFL, info->HPFR = HPFR,
	info->LPFL = LPFL, info->LPFR = LPFR, info->EPFL = EPFL, info->EPFR = EPFR;
}
#else /* floating-point implementation */
static void do_standard_reverb(DATA_T *buf, int32 count, InfoStandardReverb *info)
{
	int32 i;
	DATA_T	fixp, s, t;
	int32 spt0 = info->spt0, spt1 = info->spt1, spt2 = info->spt2, spt3 = info->spt3;
	FLOAT_T tad = info->tad, tbd = info->tbd, HPFLd = info->HPFLd, HPFRd = info->HPFRd,
		LPFLd = info->LPFLd, LPFRd = info->LPFRd, EPFLd = info->EPFLd, EPFRd = info->EPFRd;
	DATA_T *buf0_L = info->buf0_L.buf, *buf0_R = info->buf0_R.buf,
		*buf1_L = info->buf1_L.buf, *buf1_R = info->buf1_R.buf,
		*buf2_L = info->buf2_L.buf, *buf2_R = info->buf2_R.buf,
		*buf3_L = info->buf3_L.buf, *buf3_R = info->buf3_R.buf;
	FLOAT_T fbklev = info->fbklev, cmixlev = info->cmixlev,
		hpflev = info->hpflev, lpflev = info->lpflev, lpfinp = info->lpfinp,
		epflev = info->epflev, epfinp = info->epfinp, width = info->width,
		rpt0 = info->rpt0, rpt1 = info->rpt1, rpt2 = info->rpt2, rpt3 = info->rpt3, wet = info->wet;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		init_standard_reverb(info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_standard_reverb(info);
		return;
	}

	for (i = 0; i < count; i++)
	{
        /* L */
        fixp = buf[i];

        LPFLd = LPFLd * lpflev + (buf2_L[spt2] + tbd) * lpfinp + tad * width;
        tad = buf3_L[spt3];
        s  = buf3_L[spt3] = buf0_L[spt0];
        buf0_L[spt0] = -LPFLd;

        t = (HPFLd + fixp) * hpflev;
        HPFLd = t - fixp;

        buf2_L[spt2] = (s - fixp * fbklev) * cmixlev;
        tbd = buf1_L[spt1];
        buf1_L[spt1] = t;

        EPFLd = EPFLd * epflev + tad * epfinp;
        buf[i] = (tad + EPFLd) * wet;

        /* R */
        fixp = buf[++i];

        LPFRd = LPFRd * lpflev + (buf2_R[spt2] + tbd) * lpfinp + tad * width;
        tad = buf3_R[spt3];
        s  = buf3_R[spt3] = buf0_R[spt0];
        buf0_R[spt0] = LPFRd;

        t = (HPFRd + fixp) * hpflev;
        HPFRd = t - fixp;

        buf2_R[spt2] = (s - fixp * fbklev) * cmixlev;
        tbd = buf1_R[spt1];
        buf1_R[spt1] = t;

        EPFRd = EPFRd * epflev + tad * epfinp;
        buf[i] = (tad + EPFRd) * wet;

		if (++spt0 >= rpt0) {spt0 = 0;}
		if (++spt1 >= rpt1) {spt1 = 0;}
		if (++spt2 >= rpt2) {spt2 = 0;}
		if (++spt3 >= rpt3) {spt3 = 0;}
	}
	info->spt0 = spt0, info->spt1 = spt1, info->spt2 = spt2, info->spt3 = spt3,
	info->tad = tad, info->tbd = tbd, info->HPFLd = HPFLd, info->HPFRd = HPFRd,
	info->LPFLd = LPFLd, info->LPFRd = LPFRd, info->EPFLd = EPFLd, info->EPFRd = EPFRd;
}

/*! Standard Monoral Reverberator; this implementation is specialized for system effect. */
static void do_standard_reverb_mono(DATA_T *buf, int32 count, InfoStandardReverb *info)
{
	int32 i;
	DATA_T fixp, s, t;
	int32 spt0 = info->spt0, spt1 = info->spt1, spt2 = info->spt2, spt3 = info->spt3;
	FLOAT_T  tad = info->tad, tbd = info->tbd, HPFLd = info->HPFLd, HPFRd = info->HPFRd,
		LPFLd = info->LPFLd, LPFRd = info->LPFRd, EPFLd = info->EPFLd, EPFRd = info->EPFRd;
	DATA_T *buf0_L = info->buf0_L.buf, *buf0_R = info->buf0_R.buf,
		*buf1_L = info->buf1_L.buf, *buf1_R = info->buf1_R.buf,
		*buf2_L = info->buf2_L.buf, *buf2_R = info->buf2_R.buf,
		*buf3_L = info->buf3_L.buf, *buf3_R = info->buf3_R.buf;
	FLOAT_T fbklev = info->fbklev, nmixlev = info->nmixlev, monolev = info->monolev,
		hpflev = info->hpflev, lpflev = info->lpflev, lpfinp = info->lpfinp,
		epflev = info->epflev, epfinp = info->epfinp, width = info->width,
		rpt0 = info->rpt0, rpt1 = info->rpt1, rpt2 = info->rpt2, rpt3 = info->rpt3, wet = info->wet;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		init_standard_reverb(info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_standard_reverb(info);
		return;
	}

	for (i = 0; i < count; i++)
	{
        /* L */
        fixp = buf[i] * monolev;

        LPFLd = LPFLd * lpflev + (buf2_L[spt2] + tbd) * lpfinp + tad * width;
        tad = buf3_L[spt3];
        s  = buf3_L[spt3] = buf0_L[spt0];
        buf0_L[spt0] = -LPFLd;

        t = (HPFLd + fixp) * hpflev;
        HPFLd = t - fixp;

        buf2_L[spt2] = (s - fixp * fbklev) * nmixlev;
        tbd = buf1_L[spt1];
        buf1_L[spt1] = t;

        /* R */
        LPFRd = LPFRd * lpflev + (buf2_R[spt2] + tbd) * lpfinp + tad * width;
        tad = buf3_R[spt3];
        s  = buf3_R[spt3] = buf0_R[spt0];
        buf0_R[spt0] = LPFRd;

        t = (HPFRd + fixp) * hpflev;
        HPFRd = t - fixp;

        buf2_R[spt2] = (s - fixp * fbklev) * nmixlev;
        tbd = buf1_R[spt1];
        buf1_R[spt1] = t;

        EPFRd = EPFRd * epflev + tad * epfinp;
        buf[i] = (tad + EPFRd) * wet;

		if (++spt0 >= rpt0) {spt0 = 0;}
		if (++spt1 >= rpt1) {spt1 = 0;}
		if (++spt2 >= rpt2) {spt2 = 0;}
		if (++spt3 >= rpt3) {spt3 = 0;}
	}
	info->spt0 = spt0, info->spt1 = spt1, info->spt2 = spt2, info->spt3 = spt3,
	info->tad = tad, info->tbd = tbd, info->HPFLd = HPFLd, info->HPFRd = HPFRd,
	info->LPFLd = LPFLd, info->LPFRd = LPFRd, info->EPFLd = EPFLd, info->EPFRd = EPFRd;
}
#endif /* OPT_MODE != 0 */




/*                     */
/*  early reflection   */
/*                     */

#define ER_LEVEL (2.00)
#define ER_FEEDBACK (0.0)

const double er_var1[4] = {14.24, 10.77, 37.92, 27.76,};

static void set_er_allpass(allpass *allpass, int32 size)
{
	if(allpass->buf != NULL) {
		free(allpass->buf);
		allpass->buf = NULL;
	}
	allpass->buf = (DATA_T *)safe_malloc(sizeof(DATA_T) * size);
	if(allpass->buf == NULL) {return;}
	allpass->index = 0;
	allpass->size = size;
}

static void init_er_allpass(allpass *allpass)
{
	memset(allpass->buf, 0, sizeof(DATA_T) * allpass->size);
}

static inline void do_er_allpass(DATA_T *stream, DATA_T *buf, int32 size, int32 *index, FLOAT_T feedback)
{
	DATA_T bufout, output;
	bufout = buf[*index];
	output = -*stream + bufout;
	buf[*index] = *stream + bufout * feedback;
	if (++*index >= size) {*index = 0;}
	*stream = output;
}

static void do_early_reflection(DATA_T *buf, int32 count, InfoEarlyReflection *info)
{
	int32 i, k = 0;
	DATA_T outl, outr, input, erL, erR;
	simple_delay *pdelayL = &(info->pdelayL), *pdelayR = &(info->pdelayR);
	DATA_T histL = info->histL, histR = info->histR;		
	allpass *apL = info->apL, *apR = info->apR;
	FilterCoefficients *lpf1 = &(info->lpf1);
	FLOAT_T *ddif = info->ddif, feedbackd = info->feedbackd;
	FLOAT_T t, dif;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		set_delay(&(info->pdelayL), (int32)(info->er_time_ms * playmode_rate_ms));
		set_delay(&(info->pdelayR), (int32)(info->er_time_ms * playmode_rate_ms));	
		init_sample_filter(lpf1, info->damp_freq, 0, FILTER_LPF6);
		//lpf1L->freq = lpf1R->freq = info->damp_freq;
		//calc_filter_lowpass1(lpf1L);
		//calc_filter_lowpass1(lpf1R);
		//init_filter_lowpass1(lpf1L);
		//init_filter_lowpass1(lpf1R);	
	//	info->feedback = 1.0; // test
		info->feedbackd = info->feedback * ER_FEEDBACK;
		t = playmode_rate_ms * (0.01431 + info->roomsize); // / 36926037;
		dif = 1.0;
		for (i = 0; i < ER_APF_NUM; i++) {
			int32 tmp = er_var1[i] * t;
			set_er_allpass(&info->apL[i], tmp);
			set_er_allpass(&info->apR[i], tmp);
			init_er_allpass(&info->apL[i]);
			init_er_allpass(&info->apR[i]);
			dif *= 0.75;
			info->ddif[i] = dif * 0.93333333333333;	
		}
		info->histL = info->histR = 0;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_delay(&(info->pdelayL));
		free_delay(&(info->pdelayR));	
		for(i = 0; i < ER_APF_NUM; i++)
		{
			if(info->apL[i].buf != NULL) {
				free(info->apL[i].buf);
				info->apL[i].buf = NULL;
			}
			if(info->apR[i].buf != NULL) {
				free(info->apR[i].buf);
				info->apR[i].buf = NULL;
			}
		}		
		return;
	}
	switch(info->mode){
	case CH_STEREO:
		for (k = 0; k < count; k++)
		{
			outl = outr = 0;
			erL = buf[k] + histL * feedbackd;
			erR = buf[k + 1] + histR * feedbackd;
			do_delay(&erL, pdelayL->buf, pdelayL->size, &pdelayL->index);
			do_delay(&erR, pdelayR->buf, pdelayR->size, &pdelayR->index);				
			sample_filter_stereo(lpf1, &erL, &erR);	
			for (i = 0; i < ER_APF_NUM; i++) {
				do_er_allpass(&erL, apL[i].buf, apL[i].size, &apL[i].index, ddif[i]);
				do_er_allpass(&erR, apR[i].buf, apR[i].size, &apR[i].index, ddif[i]);
			}
			buf[k] = histL = erL * ER_LEVEL;
			buf[++k] = histR = erR * ER_LEVEL;
		}
		info->histL = histL, info->histR = histR;
		break;
	case CH_MIX_STEREO:
		for (k = 0; k < count; k++)
		{
			outl = outr = 0;
			erL = erR = buf[k] + (histL + histR) * DIV_MIX_LEVEL * feedbackd;
			do_delay(&erL, pdelayL->buf, pdelayL->size, &pdelayL->index);
			do_delay(&erR, pdelayR->buf, pdelayR->size, &pdelayR->index);					
			sample_filter_stereo(lpf1, &erL, &erR);
			for (i = 0; i < ER_APF_NUM; i++) {
				do_er_allpass(&erL, apL[i].buf, apL[i].size, &apL[i].index, ddif[i]);
				do_er_allpass(&erR, apR[i].buf, apR[i].size, &apR[i].index, ddif[i]);
			}
			buf[k] = histL = erL * ER_LEVEL;
			buf[++k] = histR = erR * ER_LEVEL;
		}
		info->histL = histL, info->histR = histR;
		break;
	case CH_MIX_MONO:
		for (k = 0; k < count; k++)
		{
			outl = outr = 0;
			erL = (buf[k] + buf[k + 1]) * DIV_MIX_LEVEL + histL * feedbackd;
			do_delay(&erL, pdelayL->buf, pdelayL->size, &pdelayL->index);		
			sample_filter_left(lpf1, &erL);
			for (i = 0; i < ER_APF_NUM; i++) {
				do_er_allpass(&erL, apL[i].buf, apL[i].size, &apL[i].index, ddif[i]);
			}
			buf[k] = histL = erL * ER_LEVEL;
			buf[++k] = histL;
		}
		info->histL = histL;
		break;
	}
}


/*             */
/*  Freeverb   */
/*             */
/*
static int combtunings[numcombs] = {1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617};
static int allpasstunings[numallpasses] = {225, 341, 441, 556};
#define fixedgain 0.025
#define combfbk 3.0
*/
double scalewet = 0.06;
double freeverb_scaleroom = 0.28;
double freeverb_offsetroom = 0.7;
#define scaledamp 0.4
#define scaleroom freeverb_scaleroom
#define offsetroom freeverb_offsetroom
#define initialroom 0.5
#define initialdamp 0.5
#define initialwet 1 / scalewet
#define initialdry 0
#define initialwidth 0.5
#define initialallpassfbk 0.65
#define stereospread 23 // def 23

#define FREEVERB_LEVEL  (1.0)
#define FREEVERB_ER_LEVEL (1.0 * FREEVERB_LEVEL)
#define FREEVERB_RV_LEVEL (3.0 * FREEVERB_LEVEL)
#define FREEVERB_FEEDBACK (0.06125)
#define FREEVERB_STEREO_CROSS (0.3333333)

const int combtunings[64] = {
	1116,1193,1270,1347,1419,1491,1561,1631,
	1701,1773,1844,1914,1980,2047,2108,2171,
	2231,2291,2349,2410,2469,2529,2584,2638,
	2690,2742,2794,2847,2899,2948,2999,3046,
	3092,3137,3178,3218,3261,3301,3343,3381,
	3421,3459,3492,3527,3564,3594,3626,3659,
	3688,3720,3746,3772,3798,3825,3852,3873,
	3896,3920,3941,3958,3974,3989,4008,4024,
};
const int allpasstunings[16] = {
	113, 171, 221, 278, 343, 407, 481, 549,
	613, 677, 735, 801, 865, 832, 899, 967
};

int numcombs = 8;
double extgain = 1.0;
double fixedgain = 0.025;
double combfbk = 3.0;
double time_rt_diff = 1.0;
FLOAT_T reverb_predelay_factor = 1.0;

static void do_freeverb_none(DATA_T *buf, int32 count, InfoFreeverb *info);
static void do_freeverb_chST(DATA_T *buf, int32 count, InfoFreeverb *info);
static void do_freeverb_chMS(DATA_T *buf, int32 count, InfoFreeverb *info);

static void freeverb_free_delay_rv(InfoFreeverb *info, int type, int num)
{
	if(!info->alloc_rv[num][type])
		return;
	if(info->buf_rv[num][type] != NULL) {
#ifdef ALIGN_SIZE
		aligned_free(info->buf_rv[num][type]);
#else
		free(info->buf_rv[num][type]);
#endif
		info->buf_rv[num][type] = NULL;
		info->alloc_rv[num][type] = 0;
	}
}

static int freeverb_init_delay_rv(InfoFreeverb *info, int type, int num, int32 size)
{
	int32 bytes;
	freeverb_free_delay_rv(info, type, num);
	if(size < 10) {size = 10;} 
	bytes = sizeof(DATA_T) * (size + 4); // sse
#ifdef ALIGN_SIZE
	info->buf_rv[num][type] = (DATA_T *)aligned_malloc(bytes, ALIGN_SIZE);
#else
	info->buf_rv[num][type] = (DATA_T *)safe_malloc(bytes);
#endif
	if(info->buf_rv[num][type] == NULL) {return 1;} // error
	memset(info->buf_rv[num][type], 0, bytes);
	info->size_rv[num][type] = size;
	info->index_rv[num][type] = 0;
	info->alloc_rv[num][type] = 1;
	return 0;
}

static void freeverb_free_delay_ap(InfoFreeverb *info, int type, int num)
{
	if(!info->alloc_ap[num][type])
		return;
	if(info->buf_ap[num][type] != NULL) {
#ifdef ALIGN_SIZE
		aligned_free(info->buf_ap[num][type]);
#else
		free(info->buf_ap[num][type]);
#endif
		info->buf_ap[num][type] = NULL;
		info->alloc_ap[num][type] = 0;
	}
}

static int freeverb_init_delay_ap(InfoFreeverb *info, int type, int num, int32 size)
{
	int32 bytes;
	freeverb_free_delay_ap(info, type, num);
	if(size < 10) {size = 10;} 
	bytes = sizeof(DATA_T) * (size + 4); // sse
#ifdef ALIGN_SIZE
	info->buf_ap[num][type] = (DATA_T *)aligned_malloc(bytes, ALIGN_SIZE);
#else
	info->buf_ap[num][type] = (DATA_T *)safe_malloc(bytes);
#endif
	if(info->buf_ap[num][type] == NULL) {return 1;} // error
	memset(info->buf_ap[num][type], 0, bytes);
	info->size_ap[num][type] = size;
	info->index_ap[num][type] = 0;
	info->alloc_ap[num][type] = 1;
	return 0;
}

static void freeverb_free_delay1(InfoFreeverb *info, int type)
{
	if(info->alloc1[type]){
		if(info->buf1[type] != NULL) {
#ifdef ALIGN_SIZE
			aligned_free(info->buf1[type]);
#else
			free(info->buf1[type]);
#endif
			info->buf1[type] = NULL;
			info->alloc1[type] = 0;
		}
	}
}

static int freeverb_init_delay1(InfoFreeverb *info, int type, int32 size)
{
	int32 bytes;
	freeverb_free_delay1(info, type);
	if(size < 1) {size = 1;} 
	bytes = sizeof(DATA_T) * (size + 4) * 2; // ch // sse
#ifdef ALIGN_SIZE
	info->buf1[type] = (DATA_T *)aligned_malloc(bytes, ALIGN_SIZE);
#else
	info->buf1[type] = (DATA_T *)safe_malloc(bytes);
#endif
	if(info->buf1[type] == NULL) {return 1;} // error
	memset(info->buf1[type], 0, bytes);
	info->alloc1[type] = 1;
	info->size1[type] = size * 2;
	info->index1[type] = 0;
	return 0;
}

static void free_freeverb(InfoFreeverb *info)
{
	int i;
	
	if(!info->init)
		return;
	freeverb_free_delay1(info, FREEVERV_PD);
	freeverb_free_delay1(info, FREEVERV_RD);
	for(i = 0; i < FREEVERV_RV; i++)
	{
		freeverb_free_delay_rv(info, FREEVERV_L, i);
		freeverb_free_delay_rv(info, FREEVERV_R, i);
	}
	for(i = 0; i < FREEVERV_AP; i++)
	{
		freeverb_free_delay_ap(info, FREEVERV_L, i);
		freeverb_free_delay_ap(info, FREEVERV_R, i);
	}
	info->init = 0;
}

static void init_freeverb(InfoFreeverb *info)
{
	int i, error = 0;
	int32 tmpL, tmpR;
	double time, samplerate = play_mode->rate, t;
	double allpassfbk = 0.55, rtbase, rt, dif, roomsize, width, fbmax = 0;
///r
		
	// test
	//rev->wet = initialwet * scalewet;
	//rev->damp = initialdamp * scaledamp;
	//rev->width = initialwidth;
	//rev->roomsize = initialroom * scaleroom + offsetroom;
	//info->mode = 5;
	//info->er_time_ms = 50 * pow(1.2, get_white_noise_p());
	//info->rev_time_sec = 4.0 * pow(1.2, get_white_noise_p());
	//info->rev_dly_ms = 10 * pow(1.2, get_white_noise_p());
	//info->rev_dif = 0.8 * pow(1.2, get_white_noise_p());
	//info->rev_damp = 0.7 * pow(1.2, get_white_noise_p());
	//info->er_damp_freq = 12000 * pow(1.2, get_white_noise_p());
	//info->rev_feedback = 0.01 * pow(1.2, get_white_noise_p());
	//info->rev_rt = 0.7 * pow(1.2, get_white_noise_p());
	//info->rev_roomsize = 1.4 * pow(1.2, get_white_noise_p());
	//info->rev_width = initialwidth * pow(1.2, get_white_noise_p());
	//info->rev_level = 0.5;	
	//info->er_level = 0.5;	
	//info->feedback = 0;
	
	if(numcombs & 0x1) // need 2*n
		numcombs++;
	if(numcombs >= 64)
		numcombs = 64;
	else if(numcombs < 2)
		numcombs = 2;
	info->unit_num = numcombs;
	width = info->rev_width;
	roomsize = info->rev_roomsize * scaleroom + offsetroom; 	
	info->wet1 = width * DIV_2 + 0.5;
	info->wet2 = (1.0 - width) * DIV_2;
	info->damp1 = info->rev_damp * scaledamp;
	info->damp2 = 1.0 - info->damp1;		
	extgain = 1.5 / log(sqrt((double)numcombs) * 2.0);
	time = (info->rev_time_sec * info->rev_rt * combfbk
		/ (60 * combtunings[numcombs - 1] / (-20 * log10(roomsize) * 44100.0))) * time_rt_diff;		
	t = playmode_rate_ms * (0.01431 + info->er_roomsize);	
	rtbase = 1.0 / (44100 * pow(info->rev_time_sec, DIV_3_2) * pow(info->rev_rt, DIV_2));
	for(i = 0; i <info->unit_num; i++)
	{
		tmpL = combtunings[i] * samplerate * time / 44100.0;
		tmpR = (combtunings[i] + stereospread) * samplerate * time / 44100.0;
		if(tmpL < 10) tmpL = 10;
		if(tmpR < 10) tmpR = 10;
		while(!isprime(tmpL)) tmpL++;
		while(!isprime(tmpR)) tmpR++;
		error += freeverb_init_delay_rv(info, FREEVERV_L, i, tmpL);
		error += freeverb_init_delay_rv(info, FREEVERV_R, i, tmpR);
		info->feedback_rv[i] = pow(10.0, -combfbk * (double)combtunings[i] * rtbase);
		if(fbmax < info->feedback_rv[i])
			fbmax = info->feedback_rv[i];
	}
	info->feedback_ap = allpassfbk;
	for(i = 0; i < FREEVERV_AP; i++)
	{
		tmpL = allpasstunings[i] * samplerate * time / 44100.0;
		tmpR = (allpasstunings[i] + stereospread) * samplerate * time / 44100.0;
		if(tmpL < 10) tmpL = 10;
		if(tmpR < 10) tmpR = 10;
		while(!isprime(tmpL)) tmpL++;
		while(!isprime(tmpR)) tmpR++;
		error += freeverb_init_delay_ap(info, FREEVERV_L, i, tmpL);
		error += freeverb_init_delay_ap(info, FREEVERV_R, i, tmpR);
	}
	error += freeverb_init_delay1(info, FREEVERV_PD, (int32)(info->er_time_ms * reverb_predelay_factor * playmode_rate_ms));
	error += freeverb_init_delay1(info, FREEVERV_RD, (int32)(info->rev_dly_ms * playmode_rate_ms));
	init_sample_filter(&info->lpf1, info->er_damp_freq, 0, FILTER_LPF6);	
	info->feedback = info->rev_feedback * FREEVERB_FEEDBACK;
	if(fbmax < 0.01)
		fbmax = 0.01;
	else if(fbmax > 0.99)
		fbmax = 0.99;
	fbmax = sqrt(3.0 / pow(1.0 / (1.0 - fbmax), DIV_3_2));
	info->levelrv = info->rev_level * FREEVERB_RV_LEVEL * fbmax;
	info->leveler = info->er_level * FREEVERB_ER_LEVEL;	
	info->in_level = info->rev_wet * fixedgain * extgain;	
	info->hist[0] = info->hist[1] = 0;	
#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
	for(i = 0; i <info->unit_num; i++)
	{
		info->feedback_rvi[i] = TIM_FSCALE(info->feedback_rv[i], 24);
	}
	info->damp1i = TIM_FSCALE(info->damp1, 24);
	info->damp2i = TIM_FSCALE(info->damp2, 24);
	info->feedback_api = TIM_FSCALE(info->feedback_ap, 24);
	info->wet1i = TIM_FSCALE(info->wet1, 24);
	info->wet2i = TIM_FSCALE(info->wet2, 24);
	info->in_leveli = TIM_FSCALE(info->in_level, 24);
	info->levelrvi = TIM_FSCALE(info->levelrv, 24);
	info->leveleri = TIM_FSCALE(info->leveler, 24);
#else /* floating-point implementation */
#endif	
	// func
	switch(info->mode){
	case CH_STEREO:
		info->do_reverb_mode = do_freeverb_chST;
		break;
	case CH_MIX_STEREO:
		info->do_reverb_mode = do_freeverb_chMS;
		break;
	default:
		info->do_reverb_mode = do_freeverb_none;
		break;
	}
	if(error) info->do_reverb_mode = do_freeverb_none; // safe
	info->init = 1;
}

static void do_freeverb_none(DATA_T *buf, int32 count, InfoFreeverb *info)
{
	//int32 k = 0;
	//for (k = 0; k < count; k++)	{buf[k] = 0;} // wet 0
	memset(buf, 0, sizeof(DATA_T) * count); // count > 0 // wet 0 
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void do_freeverb_chST(int32 *buf, int32 count, InfoFreeverb *info)
{
	int32 i, k = 0, 
		*indexpd = &info->index1[FREEVERV_PD], sizepd = info->size1[FREEVERV_PD],
		*indexrd = &info->index1[FREEVERV_RD], sizerd = info->size1[FREEVERV_RD];
	FILTER_T *dcL = info->lpf1.dc;
	FILTER_T *dbL = info->lpf1.db;
	int32 damp1 = info->damp1i, damp2 = info->damp2i, in_level = info->in_leveli, 
		*feedback_rv = info->feedback_rvi, feedback_ap = info->feedback_api,
		leveler = info->leveleri, levelrv = info->levelrvi, feedback = info->feedbacki, 
		wet1 = info->wet1i, wet2 = info->wet2i;
	DATA_T input[2], mixer[2], mixrv[2], *hist = info->hist,
		*bufpd = info->buf1[FREEVERV_PD], *bufrd = info->buf1[FREEVERV_RD];
	const int32 cross = TIM_FSCALE(FREEVERB_STEREO_CROSS, 24);
	for (k = 0; k < count; k++)
	{
		input[0] = buf[k] + imuldiv24(buf[k + 1], cross) + imuldiv24(hist[0], feedback);
		input[1] = imuldiv24(buf[k], cross) + buf[k + 1] + imuldiv24(hist[1], feedback);
		// pre delay out in 
		if ((*indexpd += 2) >= sizepd) {*indexpd = 0;}
		mixer[0] = bufpd[*indexpd]; 
		mixer[1] = bufpd[*indexpd + 1];
		bufpd[*indexpd] = input[0]; 
		bufpd[*indexpd + 1] = input[1];
		//sample_filter_stereo(&info->lpf1, &erL, &erR);
		dbL[0] = mixer[0] = imuldiv28(mixer[0], dcL[0]) + imuldiv28(dbL[0], dcL[1]);
		dbL[1] = mixer[1] = imuldiv28(mixer[1], dcL[0]) + imuldiv28(dbL[1], dcL[1]);
		// rv delay out in
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input[0] = imuldiv24(bufrd[*indexrd], in_level);
		input[1] = imuldiv24(bufrd[*indexrd + 1], in_level);
		bufrd[*indexrd] = mixer[0]; 
		bufrd[*indexrd + 1] = mixer[1];
		// unit
		mixrv[0] = mixrv[1] = 0;
		for (i = 0; i < info->unit_num; i++) {
			DATA_T *bufL, *bufR, *fbL = &info->fb_rv[i][FREEVERV_L], *fbR = &info->fb_rv[i][FREEVERV_R];
			int32 *indexL = &info->index_rv[i][FREEVERV_L], *indexR = &info->index_rv[i][FREEVERV_R];
			if (++*indexL >= info->size_rv[i][0]) {*indexL = 0;}
			if (++*indexR >= info->size_rv[i][1]) {*indexR = 0;}			
			bufL = &info->buf_rv[i][FREEVERV_L][*indexL]; bufR = &info->buf_rv[i][FREEVERV_R][*indexR];
			*fbL = imuldiv24(*bufL, damp2) + imuldiv24(*fbL, damp1); 
			*fbR = imuldiv24(*bufR, damp2) + imuldiv24(*fbR, damp1); 
			*bufL = input[0] + imuldiv24(*fbL, feedback_rv[i]); 
			*bufR = input[1] + imuldiv24(*fbR, feedback_rv[i]); 
			mixrv[0] += *fbL; mixrv[1] += *fbR;
		}
		for (i = 0; i < FREEVERV_AP; i++) {			
			DATA_T *bufL, *bufR, outputL, outputR;
			int32 *indexL = &info->index_ap[i][FREEVERV_L], *indexR = &info->index_ap[i][FREEVERV_R];
			if (++*indexL >= info->size_ap[i][0]) {*indexL = 0;}
			if (++*indexR >= info->size_ap[i][1]) {*indexR = 0;}
			bufL = &info->buf_ap[i][FREEVERV_L][*indexL]; bufR = &info->buf_ap[i][FREEVERV_R][*indexR];
			outputL = *bufL - mixrv[0]; outputR = *bufR - mixrv[1];
			*bufL = mixrv[0] + imuldiv24(*bufL, feedback_ap); 
			*bufR = mixrv[1] + imuldiv24(*bufR, feedback_ap);
			mixrv[0] = outputL; mixrv[1] = outputR;
		}	
		// out
		hist[0] = imuldiv24(mixer[0], leveler) + imuldiv24(imuldiv24(mixrv[0], wet1) + imuldiv24(mixrv[1], wet2), levelrv);
		hist[1] = imuldiv24(mixer[1], leveler) + imuldiv24(imuldiv24(mixrv[1], wet1) + imuldiv24(mixrv[0], wet2), levelrv);
		buf[k] = hist[0];
		buf[++k] = hist[1];
	}
}

static void do_freeverb_chMS(DATA_T *buf, int32 count, InfoFreeverb *info)
{
	int32 i, k = 0, 
		*indexpd = &info->index1[FREEVERV_PD], sizepd = info->size1[FREEVERV_PD],
		*indexrd = &info->index1[FREEVERV_RD], sizerd = info->size1[FREEVERV_RD];
	FILTER_T *dcL = info->lpf1.dc;
	FILTER_T *dbL = info->lpf1.db;
	int32 damp1 = info->damp1i, damp2 = info->damp2i, in_level = info->in_leveli, 
		*feedback_rv = info->feedback_rvi, feedback_ap = info->feedback_api,
		leveler = info->leveleri, levelrv = info->levelrvi, feedback = info->feedbacki, 
		wet1 = info->wet1i, wet2 = info->wet2i;
	DATA_T input[2], mixer[2], mixrv[2], *hist = info->hist,
		*bufpd = info->buf1[FREEVERV_PD], *bufrd = info->buf1[FREEVERV_RD];
	for (k = 0; k < count; k++)
	{
		DATA_T mix = imuldiv24((buf[k] + buf[k + 1]), DIV_MIX_LEVELi);
		input[0] = mix + imuldiv24(hist[0], feedback);
		input[1] = mix + imuldiv24(hist[1], feedback);
		// pre delay out in 
		if ((*indexpd += 2) >= sizepd) {*indexpd = 0;}
		mixer[0] = bufpd[*indexpd]; 
		mixer[1] = bufpd[*indexpd + 1];
		bufpd[*indexpd] = input[0]; 
		bufpd[*indexpd + 1] = input[1];
		//sample_filter_stereo(&info->lpf1, &erL, &erR);
		dbL[0] = mixer[0] = imuldiv28(mixer[0], dcL[0]) + imuldiv28(dbL[0], dcL[1]);
		dbL[1] = mixer[1] = imuldiv28(mixer[1], dcL[0]) + imuldiv28(dbL[1], dcL[1]);
		// rv delay out in
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input[0] = imuldiv24(bufrd[*indexrd], in_level);
		input[1] = imuldiv24(bufrd[*indexrd + 1], in_level);
		bufrd[*indexrd] = mixer[0]; 
		bufrd[*indexrd + 1] = mixer[1];
		// unit
		mixrv[0] = mixrv[1] = 0;
		for (i = 0; i < info->unit_num; i++) {
			DATA_T *bufL, *bufR, *fbL = &info->fb_rv[i][FREEVERV_L], *fbR = &info->fb_rv[i][FREEVERV_R];
			int32 *indexL = &info->index_rv[i][FREEVERV_L], *indexR = &info->index_rv[i][FREEVERV_R];
			if (++*indexL >= info->size_rv[i][0]) {*indexL = 0;}
			if (++*indexR >= info->size_rv[i][1]) {*indexR = 0;}			
			bufL = &info->buf_rv[i][FREEVERV_L][*indexL]; bufR = &info->buf_rv[i][FREEVERV_R][*indexR];
			*fbL = imuldiv24(*bufL, damp2) + imuldiv24(*fbL, damp1); 
			*fbR = imuldiv24(*bufR, damp2) + imuldiv24(*fbR, damp1); 
			*bufL = input[0] + imuldiv24(*fbL, feedback_rv[i]); 
			*bufR = input[1] + imuldiv24(*fbR, feedback_rv[i]); 
			mixrv[0] += *fbL; mixrv[1] += *fbR;
		}
		for (i = 0; i < FREEVERV_AP; i++) {			
			DATA_T *bufL, *bufR, outputL, outputR;
			int32 *indexL = &info->index_ap[i][FREEVERV_L], *indexR = &info->index_ap[i][FREEVERV_R];
			if (++*indexL >= info->size_ap[i][0]) {*indexL = 0;}
			if (++*indexR >= info->size_ap[i][1]) {*indexR = 0;}
			bufL = &info->buf_ap[i][FREEVERV_L][*indexL]; bufR = &info->buf_ap[i][FREEVERV_R][*indexR];
			outputL = *bufL - mixrv[0]; outputR = *bufR - mixrv[1];
			*bufL = mixrv[0] + imuldiv24(*bufL, feedback_ap); 
			*bufR = mixrv[1] + imuldiv24(*bufR, feedback_ap);
			mixrv[0] = outputL; mixrv[1] = outputR;
		}	
		// out
		hist[0] = imuldiv24(mixer[0], leveler) + imuldiv24(imuldiv24(mixrv[0], wet1) + imuldiv24(mixrv[1], wet2), levelrv);
		hist[1] = imuldiv24(mixer[1], leveler) + imuldiv24(imuldiv24(mixrv[1], wet1) + imuldiv24(mixrv[0], wet2), levelrv);
		buf[k] = hist[0];
		buf[++k] = hist[1];
	}
}

#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE) && defined(FLOAT_T_DOUBLE)
// 設定によってノイズ発生するのでundef
#if 1 // rv,ap 2unit 
static void do_freeverb_chST(DATA_T *buf, int32 count, InfoFreeverb *info)
{
	int32 i, k = 0, 
		*indexpd = &info->index1[FREEVERV_PD], sizepd = info->size1[FREEVERV_PD],
		*indexrd = &info->index1[FREEVERV_RD], sizerd = info->size1[FREEVERV_RD];
	FILTER_T *dcL = info->lpf1.dc;
	FILTER_T *dbL = info->lpf1.db;
	DATA_T *bufpd = info->buf1[FREEVERV_PD], *bufrd = info->buf1[FREEVERV_RD];	
	__m128d vec_lpf_dc0 = MM_LOAD1_PD(&dcL[0]), vec_lpf_dc1 = MM_LOAD1_PD(&dcL[1]), vec_lpf_db1 = _mm_loadu_pd(dbL);
	__m128d vec_feedback = MM_LOAD1_PD(&info->feedback), vec_inlevel = MM_LOAD1_PD(&info->in_level),
		vec_damp1 = MM_LOAD1_PD(&info->damp1), vec_damp2 = MM_LOAD1_PD(&info->damp2), 
		vec_fb_ap = MM_LOAD1_PD(&info->feedback_ap),
		vec_leveler = MM_LOAD1_PD(&info->leveler), vec_levelrv = MM_LOAD1_PD(&info->levelrv),
		vec_wet1 = MM_LOAD1_PD(&info->wet1), vec_wet2 = MM_LOAD1_PD(&info->wet2);
	__m128d vec_input, vec_tmp1, vec_tmp2, vec_mixer, vec_mixrv, vec_hist = _mm_loadu_pd(info->hist);
	__m128d vec_st_cross = _mm_set1_pd(FREEVERB_STEREO_CROSS);
	for (k = 0; k < count; k += 2)
	{
		vec_input = _mm_load_pd(&buf[k]);
		vec_tmp1 = _mm_shuffle_pd(vec_input, vec_input, 0x1); // swap L64bit,H64bit 
		vec_input = MM_FMA_PD(vec_tmp1, vec_st_cross, vec_input);
		vec_input = MM_FMA_PD(vec_hist, vec_feedback, vec_input);
		// pre delay out in 
		if ((*indexpd += 2) >= sizepd) {*indexpd = 0;}	
		vec_tmp1 = _mm_load_pd(&bufpd[*indexpd]);
		_mm_store_pd(&bufpd[*indexpd], vec_input);		
		vec_mixer = vec_lpf_db1 = MM_FMA2_PD(vec_tmp1, vec_lpf_dc0, vec_lpf_db1, vec_lpf_dc1); // filter
		// rv delay out in
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		vec_tmp1 = _mm_load_pd(&bufrd[*indexrd]);
		vec_input = _mm_mul_pd(vec_tmp1, vec_inlevel);
		_mm_store_pd(&bufrd[*indexrd], vec_mixer);
		// unit
		vec_mixrv = _mm_setzero_pd();
		for (i = 0; i < info->unit_num; i += 2) {	
			DATA_T *bufL1, *bufR1, *bufL2, *bufR2;		
			__m128d vfbrv1 = _mm_loadu_pd(info->fb_rv[i]), vfbrv2 = _mm_loadu_pd(info->fb_rv[i+1]);
			__m128d vfeedback_rv1 = MM_LOAD1_PD(&info->feedback_rv[i]);
			__m128d vfeedback_rv2 = MM_LOAD1_PD(&info->feedback_rv[i+1]);
			__m128d vin1, vfb1, vout1, vin2, vfb2, vout2;	
			int32 *indexL1 = &info->index_rv[i][FREEVERV_L], *indexR1 = &info->index_rv[i][FREEVERV_R];
			int32 *indexL2 = &info->index_rv[i+1][FREEVERV_L], *indexR2 = &info->index_rv[i+1][FREEVERV_R];
			if (++*indexL1 >= info->size_rv[i][FREEVERV_L]) {*indexL1 = 0;}
			if (++*indexR1 >= info->size_rv[i][FREEVERV_R]) {*indexR1 = 0;}
			if (++*indexL2 >= info->size_rv[i+1][FREEVERV_L]) {*indexL2 = 0;}
			if (++*indexR2 >= info->size_rv[i+1][FREEVERV_R]) {*indexR2 = 0;}
			bufL1 = &info->buf_rv[i][FREEVERV_L][*indexL1]; 
			bufR1 = &info->buf_rv[i][FREEVERV_R][*indexR1];
			bufL2 = &info->buf_rv[i+1][FREEVERV_L][*indexL2]; 
			bufR2 = &info->buf_rv[i+1][FREEVERV_R][*indexR2];
			vin1 = _mm_shuffle_pd(_mm_load_sd(bufL1), _mm_load_sd(bufR1), 0x0);
			vin2 = _mm_shuffle_pd(_mm_load_sd(bufL2), _mm_load_sd(bufR2), 0x0);
			vfb1 = MM_FMA2_PD(vin1, vec_damp2, vfbrv1, vec_damp1);
			vfb2 = MM_FMA2_PD(vin2, vec_damp2, vfbrv2, vec_damp1);
			_mm_storeu_pd(info->fb_rv[i], vfb1);		
			_mm_storeu_pd(info->fb_rv[i+1], vfb2);				
			vec_mixrv = _mm_add_pd(vec_mixrv, vfb1);		
			vec_mixrv = _mm_add_pd(vec_mixrv, vfb2);
			vout1 = MM_FMA_PD(vfb1, vfeedback_rv1, vec_input);
			vout2 = MM_FMA_PD(vfb2, vfeedback_rv2, vec_input);
			_mm_store_sd(bufL1, vout1); _mm_store_sd(bufR1, _mm_shuffle_pd(vout1, vout1, 0x1)); // swap L64bit,H64bit 
			_mm_store_sd(bufL2, vout2); _mm_store_sd(bufR2, _mm_shuffle_pd(vout2, vout2, 0x1)); // swap L64bit,H64bit 
		}
		for (i = 0; i < FREEVERV_AP; i += 2) {		
			DATA_T *bufL1, *bufR1, *bufL2, *bufR2;
			__m128d vin1, vout1, vmrv1 = vec_mixrv, vin2, vout2, vmrv2;			
			int32 *indexL1 = &info->index_ap[i][FREEVERV_L], *indexR1 = &info->index_ap[i][FREEVERV_R];
			int32 *indexL2 = &info->index_ap[i+1][FREEVERV_L], *indexR2 = &info->index_ap[i+1][FREEVERV_R];
			if (++*indexL1 >= info->size_ap[i][FREEVERV_L]) {*indexL1 = 0;}
			if (++*indexR1 >= info->size_ap[i][FREEVERV_R]) {*indexR1 = 0;}
			if (++*indexL2 >= info->size_ap[i+1][FREEVERV_L]) {*indexL2 = 0;}
			if (++*indexR2 >= info->size_ap[i+1][FREEVERV_R]) {*indexR2 = 0;}
			bufL1 = &info->buf_ap[i][FREEVERV_L][*indexL1]; 
			bufR1 = &info->buf_ap[i][FREEVERV_R][*indexR1];
			bufL2 = &info->buf_ap[i+1][FREEVERV_L][*indexL2]; 
			bufR2 = &info->buf_ap[i+1][FREEVERV_R][*indexR2];
			vin1 = _mm_shuffle_pd(_mm_load_sd(bufL1), _mm_load_sd(bufR1), 0x0);	
			vin2 = _mm_shuffle_pd(_mm_load_sd(bufL2), _mm_load_sd(bufR2), 0x0);					
			vmrv2 = _mm_sub_pd(vin1, vmrv1); // unit1 output to unit2 input
			vec_mixrv = _mm_sub_pd(vin2, vmrv2);
			vout1 = MM_FMA_PD(vin1, vec_fb_ap, vmrv1);
			vout2 = MM_FMA_PD(vin2, vec_fb_ap, vmrv2);
			_mm_store_sd(bufL1, vout1); _mm_store_sd(bufR1, _mm_shuffle_pd(vout1, vout1, 0x1)); // swap L64bit,H64bit 
			_mm_store_sd(bufL2, vout2); _mm_store_sd(bufR2, _mm_shuffle_pd(vout2, vout2, 0x1)); // swap L64bit,H64bit 
		}
		// out
		vec_tmp1 = _mm_shuffle_pd(vec_mixrv, vec_mixrv, 0x1); // swap L64bit,H64bit 
		vec_tmp2 = MM_FMA2_PD(vec_mixrv, vec_wet1, vec_tmp1, vec_wet2); // spread
		vec_hist = MM_FMA2_PD(vec_mixer, vec_leveler, vec_tmp2, vec_levelrv); // mix er,rv
		_mm_store_pd(&buf[k], vec_hist);
	}
	_mm_storeu_pd(info->hist, vec_hist); _mm_storeu_pd(dbL, vec_lpf_db1);
}

static void do_freeverb_chMS(DATA_T *buf, int32 count, InfoFreeverb *info)
{
	int32 i, k = 0, 
		*indexpd = &info->index1[FREEVERV_PD], sizepd = info->size1[FREEVERV_PD],
		*indexrd = &info->index1[FREEVERV_RD], sizerd = info->size1[FREEVERV_RD];
	FILTER_T *dcL = info->lpf1.dc;
	FILTER_T *dbL = info->lpf1.db;
	DATA_T *bufpd = info->buf1[FREEVERV_PD], *bufrd = info->buf1[FREEVERV_RD];	
	__m128d vec_lpf_dc0 = MM_LOAD1_PD(&dcL[0]), vec_lpf_dc1 = MM_LOAD1_PD(&dcL[1]), vec_lpf_db1 = _mm_loadu_pd(dbL);
	__m128d vec_feedback = MM_LOAD1_PD(&info->feedback), vec_inlevel = MM_LOAD1_PD(&info->in_level),
		vec_damp1 = MM_LOAD1_PD(&info->damp1), vec_damp2 = MM_LOAD1_PD(&info->damp2), 
		vec_fb_ap = MM_LOAD1_PD(&info->feedback_ap),
		vec_leveler = MM_LOAD1_PD(&info->leveler), vec_levelrv = MM_LOAD1_PD(&info->levelrv),
		vec_wet1 = MM_LOAD1_PD(&info->wet1), vec_wet2 = MM_LOAD1_PD(&info->wet2);
	__m128d vec_input, vec_tmp1, vec_tmp2, vec_mixer, vec_mixrv, vec_hist = _mm_loadu_pd(info->hist);
	__m128d vec_mix_level = _mm_set1_pd(DIV_MIX_LEVEL);
	for (k = 0; k < count; k += 2)
	{
		vec_input = _mm_load_pd(&buf[k]);
		vec_tmp1 = _mm_shuffle_pd(vec_input, vec_input, 0x1); // swap L64bit,H64bit 
		vec_input = _mm_mul_pd(_mm_add_pd(vec_input, vec_tmp1), vec_mix_level);
		vec_input = MM_FMA_PD(vec_hist, vec_feedback, vec_input);
		// pre delay out in 
		if ((*indexpd += 2) >= sizepd) {*indexpd = 0;}
		vec_tmp1 = _mm_load_pd(&bufpd[*indexpd]);
		_mm_store_pd(&bufpd[*indexpd], vec_input);		
		vec_mixer = vec_lpf_db1 = MM_FMA2_PD(vec_tmp1, vec_lpf_dc0, vec_lpf_db1, vec_lpf_dc1); // filter
		// rv delay out in
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		vec_tmp1 = _mm_load_pd(&bufrd[*indexrd]);
		vec_input = _mm_mul_pd(vec_tmp1, vec_inlevel);
		_mm_store_pd(&bufrd[*indexrd], vec_mixer);
		// unit
		vec_mixrv = _mm_setzero_pd();
		for (i = 0; i < info->unit_num; i += 2) {
			DATA_T *bufL1, *bufR1, *bufL2, *bufR2;
			__m128d vfbrv1 = _mm_loadu_pd(info->fb_rv[i]), vfbrv2 = _mm_loadu_pd(info->fb_rv[i+1]);
			__m128d vfeedback_rv1 = MM_LOAD1_PD(&info->feedback_rv[i]);
			__m128d vfeedback_rv2 = MM_LOAD1_PD(&info->feedback_rv[i+1]);
			__m128d vin1, vfb1, vout1, vin2, vfb2, vout2;
			int32 *indexL1 = &info->index_rv[i][FREEVERV_L], *indexR1 = &info->index_rv[i][FREEVERV_R];
			int32 *indexL2 = &info->index_rv[i+1][FREEVERV_L], *indexR2 = &info->index_rv[i+1][FREEVERV_R];
			if (++*indexL1 >= info->size_rv[i][FREEVERV_L]) {*indexL1 = 0;}
			if (++*indexR1 >= info->size_rv[i][FREEVERV_R]) {*indexR1 = 0;}
			if (++*indexL2 >= info->size_rv[i+1][FREEVERV_L]) {*indexL2 = 0;}
			if (++*indexR2 >= info->size_rv[i+1][FREEVERV_R]) {*indexR2 = 0;}
			bufL1 = &info->buf_rv[i][FREEVERV_L][*indexL1]; 
			bufR1 = &info->buf_rv[i][FREEVERV_R][*indexR1];
			bufL2 = &info->buf_rv[i+1][FREEVERV_L][*indexL2]; 
			bufR2 = &info->buf_rv[i+1][FREEVERV_R][*indexR2];
			vin1 = _mm_shuffle_pd(_mm_load_sd(bufL1), _mm_load_sd(bufR1), 0x0);
			vin2 = _mm_shuffle_pd(_mm_load_sd(bufL2), _mm_load_sd(bufR2), 0x0);
			vfb1 = MM_FMA2_PD(vin1, vec_damp2, vfbrv1, vec_damp1);
			vfb2 = MM_FMA2_PD(vin2, vec_damp2, vfbrv2, vec_damp1);
			_mm_storeu_pd(info->fb_rv[i], vfb1);		
			_mm_storeu_pd(info->fb_rv[i+1], vfb2);				
			vec_mixrv = _mm_add_pd(vec_mixrv, vfb1);		
			vec_mixrv = _mm_add_pd(vec_mixrv, vfb2);
			vout1 = MM_FMA_PD(vfb1, vfeedback_rv1, vec_input);
			vout2 = MM_FMA_PD(vfb2, vfeedback_rv2, vec_input);
			_mm_store_sd(bufL1, vout1); _mm_store_sd(bufR1, _mm_shuffle_pd(vout1, vout1, 0x1)); // swap L64bit,H64bit 
			_mm_store_sd(bufL2, vout2); _mm_store_sd(bufR2, _mm_shuffle_pd(vout2, vout2, 0x1)); // swap L64bit,H64bit 
		}
		for (i = 0; i < FREEVERV_AP; i += 2) {			
			DATA_T *bufL1, *bufR1, *bufL2, *bufR2;
			__m128d vin1, vout1, vmrv1 = vec_mixrv, vin2, vout2, vmrv2;
			int32 *indexL1 = &info->index_ap[i][FREEVERV_L], *indexR1 = &info->index_ap[i][FREEVERV_R];
			int32 *indexL2 = &info->index_ap[i+1][FREEVERV_L], *indexR2 = &info->index_ap[i+1][FREEVERV_R];
			if (++*indexL1 >= info->size_ap[i][FREEVERV_L]) {*indexL1 = 0;}
			if (++*indexR1 >= info->size_ap[i][FREEVERV_R]) {*indexR1 = 0;}
			if (++*indexL2 >= info->size_ap[i+1][FREEVERV_L]) {*indexL2 = 0;}
			if (++*indexR2 >= info->size_ap[i+1][FREEVERV_R]) {*indexR2 = 0;}
			bufL1 = &info->buf_ap[i][FREEVERV_L][*indexL1]; 
			bufR1 = &info->buf_ap[i][FREEVERV_R][*indexR1];
			bufL2 = &info->buf_ap[i+1][FREEVERV_L][*indexL2]; 
			bufR2 = &info->buf_ap[i+1][FREEVERV_R][*indexR2];
			vin1 = _mm_shuffle_pd(_mm_load_sd(bufL1), _mm_load_sd(bufR1), 0x0);	
			vin2 = _mm_shuffle_pd(_mm_load_sd(bufL2), _mm_load_sd(bufR2), 0x0);					
			vmrv2 = _mm_sub_pd(vin1, vmrv1); // unit1 output to unit2 input
			vec_mixrv = _mm_sub_pd(vin2, vmrv2);
			vout1 = MM_FMA_PD(vin1, vec_fb_ap, vmrv1);
			vout2 = MM_FMA_PD(vin2, vec_fb_ap, vmrv2);
			_mm_store_sd(bufL1, vout1); _mm_store_sd(bufR1, _mm_shuffle_pd(vout1, vout1, 0x1)); // swap L64bit,H64bit 
			_mm_store_sd(bufL2, vout2); _mm_store_sd(bufR2, _mm_shuffle_pd(vout2, vout2, 0x1)); // swap L64bit,H64bit 
		}	
		// out
		vec_tmp1 = _mm_shuffle_pd(vec_mixrv, vec_mixrv, 0x1); // swap L64bit,H64bit 
		vec_tmp2 = MM_FMA2_PD(vec_mixrv, vec_wet1, vec_tmp1, vec_wet2); // spread
		vec_hist = MM_FMA2_PD(vec_mixer, vec_leveler, vec_tmp2, vec_levelrv); // mix er,rv
		_mm_store_pd(&buf[k], vec_hist);
	}
	_mm_storeu_pd(info->hist, vec_hist); _mm_storeu_pd(dbL, vec_lpf_db1);
}

#else // rv,ap 1unit
static void do_freeverb_chST(DATA_T *buf, int32 count, InfoFreeverb *info)
{
	int32 i, k = 0, 
		*indexpd = &info->index1[FREEVERV_PD], sizepd = info->size1[FREEVERV_PD],
		*indexrd = &info->index1[FREEVERV_RD], sizerd = info->size1[FREEVERV_RD];
	FILTER_T *dcL = info->lpf1.dc;
	FILTER_T *dbL = info->lpf1.db;
	DATA_T *bufpd = info->buf1[FREEVERV_PD], *bufrd = info->buf1[FREEVERV_RD];	
	__m128d vec_lpf_dc0 = MM_LOAD1_PD(&dcL[0]), vec_lpf_dc1 = MM_LOAD1_PD(&dcL[1]), vec_lpf_db1 = _mm_loadu_pd(dbL);
	__m128d vec_feedback = MM_LOAD1_PD(&info->feedback), vec_inlevel = MM_LOAD1_PD(&info->in_level),
		vec_damp1 = MM_LOAD1_PD(&info->damp1), vec_damp2 = MM_LOAD1_PD(&info->damp2), 
		vec_fb_ap = MM_LOAD1_PD(&info->feedback_ap),
		vec_leveler = MM_LOAD1_PD(&info->leveler), vec_levelrv = MM_LOAD1_PD(&info->levelrv),
		vec_wet1 = MM_LOAD1_PD(&info->wet1), vec_wet2 = MM_LOAD1_PD(&info->wet2);
	__m128d vec_input, vec_tmp1, vec_tmp2, vec_mixer, vec_mixrv, vec_hist = _mm_loadu_pd(info->hist);
	__m128d vec_st_cross = _mm_set1_pd(FREEVERB_STEREO_CROSS);
	for (k = 0; k < count; k += 2)
	{
		vec_input = _mm_load_pd(&buf[k]);
		vec_tmp1 = _mm_shuffle_pd(vec_input, vec_input, 0x1); // swap L64bit,H64bit 
		vec_input = MM_FMA_PD(vec_tmp1, vec_st_cross, vec_input);
		vec_input = MM_FMA_PD(vec_hist, vec_feedback, vec_input);
		// pre delay out in 
		if ((*indexpd += 2) >= sizepd) {*indexpd = 0;}	
		vec_tmp1 = _mm_load_pd(&bufpd[*indexpd]);
		_mm_store_pd(&bufpd[*indexpd], vec_input);		
		vec_mixer = vec_lpf_db1 = MM_FMA2_PD(vec_tmp1, vec_lpf_dc0, vec_lpf_db1, vec_lpf_dc1); // filter
		// rv delay out in
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		vec_tmp1 = _mm_load_pd(&bufrd[*indexrd]);
		vec_input = _mm_mul_pd(vec_tmp1, vec_inlevel);
		_mm_store_pd(&bufrd[*indexrd], vec_mixer);
		// unit
		vec_mixrv = _mm_setzero_pd();
		for (i = 0; i < info->unit_num; i++) {
			DATA_T *bufL, *bufR;
			__m128d vfbrv = _mm_loadu_pd(info->fb_rv[i]);
			__m128d vfeedback_rv = MM_LOAD1_PD(&info->feedback_rv[i]);
			__m128d vin, vfb, vout;
			int32 *indexL = &info->index_rv[i][FREEVERV_L], *indexR = &info->index_rv[i][FREEVERV_R];
			if (++*indexL >= info->size_rv[i][0]) {*indexL = 0;}
			if (++*indexR >= info->size_rv[i][1]) {*indexR = 0;}
			bufL = &info->buf_rv[i][FREEVERV_L][*indexL]; 
			bufR = &info->buf_rv[i][FREEVERV_R][*indexR];
			vin = _mm_shuffle_pd(_mm_load_sd(bufL), _mm_load_sd(bufR), 0x0);
			vfb = MM_FMA2_PD(vin, vec_damp2, vfbrv, vec_damp1);
			_mm_storeu_pd(info->fb_rv[i], vfb);			
			vec_mixrv = _mm_add_pd(vec_mixrv, vfb);
			vout = MM_FMA_PD(vfb, vfeedback_rv, vec_input);
			_mm_store_sd(bufL, vout); _mm_store_sd(bufR, _mm_shuffle_pd(vout, vout, 0x1)); // swap L64bit,H64bit 
		}
		for (i = 0; i < FREEVERV_AP; i++) {			
			DATA_T *bufL, *bufR;
			int32 *indexL = &info->index_ap[i][FREEVERV_L], *indexR = &info->index_ap[i][FREEVERV_R];
			__m128d vin, vout, vmrv = vec_mixrv;
			if (++*indexL >= info->size_ap[i][0]) {*indexL = 0;}
			if (++*indexR >= info->size_ap[i][1]) {*indexR = 0;}
			bufL = &info->buf_ap[i][FREEVERV_L][*indexL]; bufR = &info->buf_ap[i][FREEVERV_R][*indexR];
			vin = _mm_shuffle_pd(_mm_load_sd(bufL), _mm_load_sd(bufR), 0x0);			
			vec_mixrv = _mm_sub_pd(vin, vmrv);
			vout = MM_FMA_PD(vin, vec_fb_ap, vmrv);
			_mm_store_sd(bufL, vout); _mm_store_sd(bufR, _mm_shuffle_pd(vout, vout, 0x1)); // swap L64bit,H64bit 
		}	
		// out
		vec_tmp1 = _mm_shuffle_pd(vec_mixrv, vec_mixrv, 0x1); // swap L64bit,H64bit 
		vec_tmp2 = MM_FMA2_PD(vec_mixrv, vec_wet1, vec_tmp1, vec_wet2); // spread
		vec_hist = MM_FMA2_PD(vec_mixer, vec_leveler, vec_tmp2, vec_levelrv); // mix er,rv
		_mm_store_pd(&buf[k], vec_hist);
	}
	_mm_storeu_pd(info->hist, vec_hist); _mm_storeu_pd(dbL, vec_lpf_db1);
}

static void do_freeverb_chMS(DATA_T *buf, int32 count, InfoFreeverb *info)
{
	int32 i, k = 0, 
		*indexpd = &info->index1[FREEVERV_PD], sizepd = info->size1[FREEVERV_PD],
		*indexrd = &info->index1[FREEVERV_RD], sizerd = info->size1[FREEVERV_RD];
	FILTER_T *dcL = info->lpf1.dc;
	FILTER_T *dbL = info->lpf1.db;
	DATA_T *bufpd = info->buf1[FREEVERV_PD], *bufrd = info->buf1[FREEVERV_RD];	
	__m128d vec_lpf_dc0 = MM_LOAD1_PD(&dcL[0]), vec_lpf_dc1 = MM_LOAD1_PD(&dcL[1]), vec_lpf_db1 = _mm_loadu_pd(dbL);
	__m128d vec_feedback = MM_LOAD1_PD(&info->feedback), vec_inlevel = MM_LOAD1_PD(&info->in_level),
		vec_damp1 = MM_LOAD1_PD(&info->damp1), vec_damp2 = MM_LOAD1_PD(&info->damp2), 
		vec_fb_ap = MM_LOAD1_PD(&info->feedback_ap),
		vec_leveler = MM_LOAD1_PD(&info->leveler), vec_levelrv = MM_LOAD1_PD(&info->levelrv),
		vec_wet1 = MM_LOAD1_PD(&info->wet1), vec_wet2 = MM_LOAD1_PD(&info->wet2);
	__m128d vec_input, vec_tmp1, vec_tmp2, vec_mixer, vec_mixrv, vec_hist = _mm_loadu_pd(info->hist);
	__m128d vec_mix_level = _mm_set1_pd(DIV_MIX_LEVEL);
	for (k = 0; k < count; k += 2)
	{
		vec_input = _mm_load_pd(&buf[k]);
		vec_tmp1 = _mm_shuffle_pd(vec_input, vec_input, 0x1); // swap L64bit,H64bit 
		vec_input = _mm_mul_pd(_mm_add_pd(vec_input, vec_tmp1), vec_mix_level);
		vec_input = MM_FMA_PD(vec_hist, vec_feedback, vec_input);
		// pre delay out in 
		if ((*indexpd += 2) >= sizepd) {*indexpd = 0;}
		vec_tmp1 = _mm_load_pd(&bufpd[*indexpd]);
		_mm_store_pd(&bufpd[*indexpd], vec_input);		
		vec_mixer = vec_lpf_db1 = MM_FMA2_PD(vec_tmp1, vec_lpf_dc0, vec_lpf_db1, vec_lpf_dc1); // filter
		// rv delay out in
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		vec_tmp1 = _mm_load_pd(&bufrd[*indexrd]);
		vec_input = _mm_mul_pd(vec_tmp1, vec_inlevel);
		_mm_store_pd(&bufrd[*indexrd], vec_mixer);
		// unit
		vec_mixrv = _mm_setzero_pd();
		for (i = 0; i < info->unit_num; i++) {
			DATA_T *bufL, *bufR;
			__m128d vfbrv = _mm_loadu_pd(info->fb_rv[i]);
			__m128d vfeedback_rv = MM_LOAD1_PD(&info->feedback_rv[i]);
			__m128d vin, vfb, vout;
			int32 *indexL = &info->index_rv[i][FREEVERV_L], *indexR = &info->index_rv[i][FREEVERV_R];
			if (++*indexL >= info->size_rv[i][0]) {*indexL = 0;}
			if (++*indexR >= info->size_rv[i][1]) {*indexR = 0;}
			bufL = &info->buf_rv[i][FREEVERV_L][*indexL]; 
			bufR = &info->buf_rv[i][FREEVERV_R][*indexR];
			vin = _mm_shuffle_pd(_mm_load_sd(bufL), _mm_load_sd(bufR), 0x0);
			vfb = MM_FMA2_PD(vin, vec_damp2, vfbrv, vec_damp1);
			_mm_storeu_pd(info->fb_rv[i], vfb);			
			vec_mixrv = _mm_add_pd(vec_mixrv, vfb);
			vout = MM_FMA_PD(vfb, vfeedback_rv, vec_input);
			_mm_store_sd(bufL, vout); _mm_store_sd(bufR, _mm_shuffle_pd(vout, vout, 0x1)); // swap L64bit,H64bit 
		}
		for (i = 0; i < FREEVERV_AP; i++) {			
			DATA_T *bufL, *bufR;
			int32 *indexL = &info->index_ap[i][FREEVERV_L], *indexR = &info->index_ap[i][FREEVERV_R];
			__m128d vin, vout, vmrv = vec_mixrv;
			if (++*indexL >= info->size_ap[i][0]) {*indexL = 0;}
			if (++*indexR >= info->size_ap[i][1]) {*indexR = 0;}
			bufL = &info->buf_ap[i][FREEVERV_L][*indexL]; bufR = &info->buf_ap[i][FREEVERV_R][*indexR];
			vin = _mm_shuffle_pd(_mm_load_sd(bufL), _mm_load_sd(bufR), 0x0);			
			vec_mixrv = _mm_sub_pd(vin, vmrv);
			vout = MM_FMA_PD(vin, vec_fb_ap, vmrv);
			_mm_store_sd(bufL, vout); _mm_store_sd(bufR, _mm_shuffle_pd(vout, vout, 0x1)); // swap L64bit,H64bit 
		}	
		// out
		vec_tmp1 = _mm_shuffle_pd(vec_mixrv, vec_mixrv, 0x1); // swap L64bit,H64bit 
		vec_tmp2 = MM_FMA2_PD(vec_mixrv, vec_wet1, vec_tmp1, vec_wet2); // spread
		vec_hist = MM_FMA2_PD(vec_mixer, vec_leveler, vec_tmp2, vec_levelrv); // mix er,rv
		_mm_store_pd(&buf[k], vec_hist);
	}
	_mm_storeu_pd(info->hist, vec_hist); _mm_storeu_pd(dbL, vec_lpf_db1);
}
#endif // unit opt

#else /* floating-point implementation */
static void do_freeverb_chST(DATA_T *buf, int32 count, InfoFreeverb *info)
{
	int32 i, k = 0, 
		*indexpd = &info->index1[FREEVERV_PD], sizepd = info->size1[FREEVERV_PD],
		*indexrd = &info->index1[FREEVERV_RD], sizerd = info->size1[FREEVERV_RD];
	FILTER_T *dcL = info->lpf1.dc;
	FILTER_T *dbL = info->lpf1.db;
	FLOAT_T damp1 = info->damp1, damp2 = info->damp2, in_level = info->in_level, feedback_ap = info->feedback_ap,
		leveler = info->leveler, levelrv = info->levelrv, feedback = info->feedback;
	DATA_T inputL, inputR, erL, erR, prcL, prcR, histL = info->hist[0], histR = info->hist[1],
		*bufpd = info->buf1[FREEVERV_PD], *bufrd = info->buf1[FREEVERV_RD];
	for (k = 0; k < count; k++)
	{
		inputL = buf[k] + buf[k + 1] * FREEVERB_STEREO_CROSS + histL * feedback;
		inputR = buf[k] * FREEVERB_STEREO_CROSS + buf[k + 1] + histR * feedback;
		// pre delay out in 
		if ((*indexpd += 2) >= sizepd) {*indexpd = 0;}
		erL = bufpd[*indexpd]; 
		erR = bufpd[*indexpd + 1];
		bufpd[*indexpd] = inputL; 
		bufpd[*indexpd + 1] = inputR;
		dbL[0] = erL = dcL[0] * erL + dcL[1] * dbL[0];
		dbL[1] = erR = dcL[0] * erR + dcL[1] * dbL[1];
		// rv delay out in
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		inputL = bufrd[*indexrd] * in_level;
		inputR = bufrd[*indexrd + 1] * in_level;
		bufrd[*indexrd] = erL; 
		bufrd[*indexrd + 1] = erR;
		// unit
		prcL = prcR = 0;
		for (i = 0; i < info->unit_num; i++) {
			DATA_T *bufL, *bufR, *fbL = &info->fb_rv[i][FREEVERV_L], *fbR = &info->fb_rv[i][FREEVERV_R];
			int32 *indexL = &info->index_rv[i][FREEVERV_L], *indexR = &info->index_rv[i][FREEVERV_R];
			if (++*indexL >= info->size_rv[i][0]) {*indexL = 0;}
			if (++*indexR >= info->size_rv[i][1]) {*indexR = 0;}			
			bufL = &info->buf_rv[i][FREEVERV_L][*indexL]; bufR = &info->buf_rv[i][FREEVERV_R][*indexR];
			*fbL = *bufL * damp2 + *fbL * damp1; *fbR = *bufR * damp2 + *fbR * damp1;
			*bufL = inputL + *fbL * info->feedback_rv[i]; *bufR = inputR + *fbR * info->feedback_rv[i];
			prcL += *fbL; prcR += *fbR;
		}
		for (i = 0; i < FREEVERV_AP; i++) {			
			DATA_T *bufL, *bufR, outputL, outputR;
			int32 *indexL = &info->index_ap[i][FREEVERV_L], *indexR = &info->index_ap[i][FREEVERV_R];
			if (++*indexL >= info->size_ap[i][0]) {*indexL = 0;}
			if (++*indexR >= info->size_ap[i][1]) {*indexR = 0;}
			bufL = &info->buf_ap[i][FREEVERV_L][*indexL]; bufR = &info->buf_ap[i][FREEVERV_R][*indexR];
			outputL = -prcL + *bufL; outputR = -prcR + *bufR;
			*bufL = prcL + *bufL * feedback_ap; *bufR = prcR + *bufR * feedback_ap;
			prcL = outputL; prcR = outputR;
		}	
		// out
		histL = erL * leveler + (prcL * info->wet1 + prcR * info->wet2) * levelrv;
		histR = erR * leveler + (prcR * info->wet1 + prcL * info->wet2) * levelrv;
		buf[k] = histL;
		buf[++k] = histR;
	}
	info->hist[0] = histL, info->hist[1] = histR;
}

static void do_freeverb_chMS(DATA_T *buf, int32 count, InfoFreeverb *info)
{
	int32 i, k = 0, 
		*indexpd = &info->index1[FREEVERV_PD], sizepd = info->size1[FREEVERV_PD],
		*indexrd = &info->index1[FREEVERV_RD], sizerd = info->size1[FREEVERV_RD];
	FILTER_T *dcL = info->lpf1.dc;
	FILTER_T *dbL = info->lpf1.db;
	FLOAT_T damp1 = info->damp1, damp2 = info->damp2, in_level = info->in_level, feedback_ap = info->feedback_ap,
		leveler = info->leveler, levelrv = info->levelrv, feedback = info->feedback;
	DATA_T inputL, inputR, erL, erR, prcL, prcR, histL = info->hist[0], histR = info->hist[1],
		*bufpd = info->buf1[FREEVERV_PD], *bufrd = info->buf1[FREEVERV_RD];
	for (k = 0; k < count; k++)
	{
		DATA_T mix = (buf[k] + buf[k + 1]) * DIV_MIX_LEVEL;
		inputL = mix + histL * feedback;
		inputR = mix + histR * feedback;
		// pre delay out in 
		if ((*indexpd += 2) >= sizepd) {*indexpd = 0;}
		erL = bufpd[*indexpd]; 
		erR = bufpd[*indexpd + 1];
		bufpd[*indexpd] = inputL; 
		bufpd[*indexpd + 1] = inputR;
	//	sample_filter_stereo(lpf1, &erL, &erR);
		dbL[0] = erL = dcL[0] * erL + dcL[1] * dbL[0];
		dbL[1] = erR = dcL[0] * erR + dcL[1] * dbL[1];
		// rv delay out in
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		inputL = bufrd[*indexrd] * in_level;
		inputR = bufrd[*indexrd + 1] * in_level;
		bufrd[*indexrd] = erL; 
		bufrd[*indexrd + 1] = erR;
		// unit
		prcL = prcR = 0;
		for (i = 0; i < info->unit_num; i++) {
			DATA_T *bufL, *bufR, *fbL = &info->fb_rv[i][FREEVERV_L], *fbR = &info->fb_rv[i][FREEVERV_R];
			int32 *indexL = &info->index_rv[i][FREEVERV_L], *indexR = &info->index_rv[i][FREEVERV_R];
			if (++*indexL >= info->size_rv[i][0]) {*indexL = 0;}
			if (++*indexR >= info->size_rv[i][1]) {*indexR = 0;}			
			bufL = &info->buf_rv[i][FREEVERV_L][*indexL]; bufR = &info->buf_rv[i][FREEVERV_R][*indexR];
			*fbL = *bufL * damp2 + *fbL * damp1; *fbR = *bufR * damp2 + *fbR * damp1;
			*bufL = inputL + *fbL * info->feedback_rv[i]; *bufR = inputR + *fbR * info->feedback_rv[i];
			prcL += *fbL; prcR += *fbR;
		}
		for (i = 0; i < FREEVERV_AP; i++) {			
			DATA_T *bufL, *bufR, outputL, outputR;
			int32 *indexL = &info->index_ap[i][FREEVERV_L], *indexR = &info->index_ap[i][FREEVERV_R];
			if (++*indexL >= info->size_ap[i][0]) {*indexL = 0;}
			if (++*indexR >= info->size_ap[i][1]) {*indexR = 0;}
			bufL = &info->buf_ap[i][FREEVERV_L][*indexL]; bufR = &info->buf_ap[i][FREEVERV_R][*indexR];
			outputL = -prcL + *bufL; outputR = -prcR + *bufR;
			*bufL = prcL + *bufL * feedback_ap; *bufR = prcR + *bufR * feedback_ap;
			prcL = outputL; prcR = outputR;
		}			
		// out
		histL = erL * leveler + (prcL * info->wet1 + prcR * info->wet2) * levelrv;
		histR = erR * leveler + (prcR * info->wet1 + prcL * info->wet2) * levelrv;
		buf[k] = histL;
		buf[++k] = histR;
	}
	info->hist[0] = histL, info->hist[1] = histR;
}
#endif

static void CALLINGCONV do_freeverb(DATA_T *buf, int32 count, InfoFreeverb *info)
{
	if(count == MAGIC_INIT_EFFECT_INFO) {	
		init_freeverb(info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_freeverb(info);		
		return;
	} else if(count < 0) {
		return;
	}
	info->do_reverb_mode(buf, count, info);
}



/*                 */
/*  Reverb EX/EX2  */
/*                 */


#define PRIME_LIST_MAX 256
int32 prime_list[PRIME_LIST_MAX];
int32 prime_list_count = 0;

static void init_prime_list(void)
{
	prime_list_count = 0;
	memset(prime_list, 0, sizeof(prime_list));
}

static inline void find_prime(int32 *inout)
{
	int i, flg, val = *inout;
	
	if(val < 11)
		val = 11; 
	for(;;) {
		if (val & 1) {
			flg = 1;
			for (i = 3; i < (int)sqrt((double)val) + 1; i += 2) {
				if ((val % i) == 0){
					flg = 0; /* multi */
					break;
				}
			}		
			if(flg){ /* prime */
				for (i = 0; i < prime_list_count; i++) {
					if(val == prime_list[i]){
						flg = 0; // exist
						break;
					}
				}
			}
		} else	{ /* even */			
			flg = 0;
		}
		if(flg){ /* new prime */
			*inout = prime_list[prime_list_count] = val;
			if(++prime_list_count > PRIME_LIST_MAX)
				prime_list_count = PRIME_LIST_MAX;
			return;
		}		
		val++;
	}
}

static void free_fb_delay(fb_delay *delay)
{
	if(delay->buf != NULL) {
		free(delay->buf);
		delay->buf = NULL;
	}
}

static void init_fb_delay(fb_delay *delay, int32 size, FLOAT_T fb)
{
	if(size < 1) {size = 1;} 
	free_fb_delay(delay);
	delay->buf = (DATA_T *)safe_malloc(sizeof(DATA_T) * size);
	if(delay->buf == NULL) {return;}
	delay->index = 0;
	delay->size = size;
	memset(delay->buf, 0, sizeof(DATA_T) * delay->size);
	delay->feedback = fb;
}

static inline void do_fb_delay(fb_delay *delay, DATA_T *inout)
{
	DATA_T output = delay->buf[delay->index];
	delay->buf[delay->index] = *inout;
	if (++delay->index >= delay->size) {delay->index = 0;}
	*inout = output;
}

static inline void do_fb_delay_fb(fb_delay *delay, DATA_T *inout)
{
	DATA_T output = delay->buf[delay->index];
	delay->buf[delay->index] = *inout + output * delay->feedback;
	if (++delay->index >= delay->size) {delay->index = 0;}
	*inout = output;
}

static inline void do_fb_delay_add(fb_delay *delay, DATA_T *in, DATA_T *out)
{	
	DATA_T output = delay->buf[delay->index];
	delay->buf[delay->index] = *in;
	if (++delay->index >= delay->size) {delay->index = 0;}
	*out += output;
}

static inline void do_fb_delay_fb_add(fb_delay *delay, DATA_T *in, DATA_T *out)
{	
	DATA_T output = delay->buf[delay->index];
	delay->buf[delay->index] = *in + output * delay->feedback;
	if (++delay->index >= delay->size) {delay->index = 0;}
	*out += output;
}


static void free_allpass2(allpass2 *info)
{
	if(!info)
		return;
	if(info->alloc != 1)
		return;
	if(!info->buf)
		return;
	safe_free(info->buf);
	info->buf = NULL;
	info->alloc = 0;
}

static void init_allpass2(allpass2 *info, int32 size, FLOAT_T feedback)
{
	int bytes;
	
	if(size < 10) {size = 10;} 
	free_allpass2(info);
	bytes = sizeof(DATA_T) * size;
	info->buf = (DATA_T *)safe_malloc(bytes);
	if(info->buf == NULL){
		info->alloc = 0;
		return;
	}
	memset(info->buf, 0, bytes);
	info->size = size;
	info->index = 0;	
	info->feedback = feedback;
	info->alloc = 1;
}

static inline void do_allpass2(allpass2 *info, DATA_T *inout)
{
	DATA_T bufout;

	bufout = info->buf[info->index];
	info->buf[info->index] = *inout + bufout * info->feedback;
	if (++info->index >= info->size) {info->index = 0;}
	*inout = bufout - *inout;
}

static void init_mod_allpass2(allpass2 *info, int32 size, FLOAT_T feedback)
{
	int bytes;
	
	if(size < 10) {size = 10;} 
	free_allpass2(info);
	// lfo wave:triangular(lite) out:0.0~1.0 freq:1.25Hz~2.1875Hz depth:3.0~4.5cent, random:freq,phase,depth	
	info->lfo_rate = 1.25 * div_playmode_rate * pow(1.75, get_white_noise_p());
	info->lfo_count = get_white_noise_p() * DIV_2; // 0.0~0.5
	info->lfo_depth = (pow(2.0, 3.0 * DIV_1200) - 1.0) / (info->lfo_rate * 2.0) * pow(1.5, get_white_noise_p());
	info->lfo_phase = get_white_noise_p();
	info->lfo_cycle = 0;
	if(size < info->lfo_depth + 1)
		size = info->lfo_depth + 1; // must depth < size
	info->delay = size;
	bytes = sizeof(DATA_T) * (size + 1); // +1 linear interpolation	
	info->buf = (DATA_T *)safe_malloc(bytes);
	if(info->buf == NULL){
		info->alloc = 0;
		return;
	}
	info->alloc = 1;	
	info->size = size;
	info->index = 0;
	info->feedback = feedback;	
	memset(info->buf, 0, bytes);
}

static inline void pre_compute_mod_allpass2(allpass2 *info, int32 count)
{	
	FLOAT_T cf;	

	if((cf = info->lfo_count * 2.0) > 1.0) {cf = 2.0 - cf;}
	info->offset = info->lfo_depth * cf - info->delay;
	if((info->lfo_count += info->lfo_rate * count) >= 1.0) {info->lfo_count -= 1.0;}	
}

static inline void do_mod_allpass2(allpass2 *info, DATA_T *inout)
{
	DATA_T bufout;
	int32 index;
	DATA_T v1, v2;
	FLOAT_T fp = (FLOAT_T)info->index - info->offset;	

	if(fp < 0)
		fp += info->size;
	else if(fp >= info->size)
		fp -= info->size;					
	index = fp;
	fp -= index;
	v1 = info->buf[index];
	v2 = info->buf[index + 1];
	bufout = v1 + (v2 - v1) * fp; // linear interpolation	
	info->buf[info->index] = *inout + bufout * info->feedback;
	*inout = bufout - *inout;
	if(info->lfo_cycle && info->index == 0)
		info->buf[info->size] = info->buf[0]; // for linear interpolation
	if(++info->index >= info->size){
		info->index = 0;
		info->lfo_cycle++;
	}
}

static void free_comb2(comb2 *info)
{
	if(!info)
		return;
	if(info->alloc != 1)
		return;
	if(!info->buf)
		return;
	safe_free(info->buf);
	info->buf = NULL;
	info->alloc = 0;
}

static void init_comb2(comb2 *info, int32 size, FLOAT_T feedback, FLOAT_T bal, FLOAT_T freq, int type)
{
	int bytes;
	
	if(size < 10) {size = 10;} 
	free_comb2(info);
	bytes = sizeof(DATA_T) * size;
	info->buf = (DATA_T *)safe_malloc(bytes);
	if(info->buf == NULL){
		info->alloc = 0;
		return;
	}
	info->alloc = 1;	
	memset(info->buf, 0, bytes);
	info->size = size;
	info->index = 0;
	info->feedback_wet = bal;	
	info->feedback_dry = 1.0 - bal;
	info->feedback_out = feedback;	
	info->feedback_in = 1.0 - feedback * DIV_2;
	info->return_in = -pow((1.0 - feedback) * DIV_2, 3);
	init_sample_filter(&info->fc, freq, 0, type);
}

static inline void do_comb2(comb2 *info, DATA_T *in, DATA_T *out)
{
	DATA_T bufout, flt;
	
	flt = bufout = info->buf[info->index];
	sample_filter(&info->fc, &flt);
	bufout = bufout * info->feedback_dry + flt * info->feedback_wet;
	info->buf[info->index] = *in * info->feedback_in + bufout * info->feedback_out;
	if (++info->index >= info->size) {info->index = 0;}
	*in -= bufout * info->return_in;
	*out += bufout;
}

static void init_mod_comb2(comb2 *info, int32 size, FLOAT_T feedback, FLOAT_T bal, FLOAT_T freq, int type)
{
	int bytes;
			
	if(size < 10) {size = 10;} 
	free_comb2(info);
	// lfo wave:triangular(lite) out:0.0~1.0 freq:0.95Hz~1.425Hz depth:1~1.5cent, random:freq,phase,depth	
	info->lfo_rate[0] = 0.95 * div_playmode_rate * pow(1.75, get_white_noise_p());
	info->lfo_count[0] = get_white_noise_p() * DIV_2; // 0.0~0.5
	info->lfo_depth = (pow(2.0, 1.0 * DIV_1200) - 1.0) / (info->lfo_rate[0] * 2.0) * pow(1.5, get_white_noise_p());
	info->lfo_phase = get_white_noise_p();
	info->lfo_cycle = 0;
	if(size < info->lfo_depth + 1)
		size = info->lfo_depth + 1; // must depth < size
	info->delay = size;
	bytes = sizeof(DATA_T) * (size + 1); // +1 linear interpolation	
	info->buf = (DATA_T *)safe_malloc(bytes);
	if(info->buf == NULL){
		info->alloc = 0;
		return;
	}
	info->alloc = 1;
	memset(info->buf, 0, bytes);
	info->size = size;
	info->index = 0;
	info->feedback_wet = bal;	
	info->feedback_dry = 1.0 - bal;
	info->feedback_out = feedback;	
	info->feedback_in = 1.0 - feedback * DIV_2;
	info->return_in = -pow((1.0 - feedback) * DIV_2, 3);
	init_sample_filter(&info->fc, freq, 0, type);
}

static inline void do_mod_comb2(comb2 *info, DATA_T *in, DATA_T *out)
{
	DATA_T bufout, flt;
	int32 index;
	DATA_T v1, v2;
	FLOAT_T fp = (FLOAT_T)info->index - info->offset;	

	if(fp < 0)
		fp += info->size;
	else if(fp >= info->size)
		fp -= info->size;					
	index = fp;
	fp -= index;
	v1 = info->buf[index];
	v2 = info->buf[index + 1];
	flt = bufout = v1 + (v2 - v1) * fp; // linear interpolation
	sample_filter(&info->fc, &flt);
	bufout = bufout * info->feedback_dry + flt * info->feedback_wet;
	info->buf[info->index] = *in * info->feedback_in + bufout * info->feedback_out;
	if(info->lfo_cycle && info->index == 0)
		info->buf[info->size] = info->buf[0]; // for linear interpolation
	if(++info->index >= info->size){
		info->index = 0;
		info->lfo_cycle++;
	}
	*in -= bufout * info->return_in;
	*out += bufout;
}

static inline void pre_compute_mod_comb2(comb2 *info, int32 count)
{	
	FLOAT_T cf;	

	if((cf = info->lfo_count[0] * 2.0) > 1.0) {cf = 2.0 - cf;}
	info->offset = info->lfo_depth * cf - info->delay;
	if((info->lfo_count[0] += info->lfo_rate[0] * count) >= 1.0) {info->lfo_count[0] -= 1.0;}	
}

// net_comb // net_comb2
static void init_net_comb(comb2 *info, int32 size, FLOAT_T fb, FLOAT_T bal, FLOAT_T freq, int type, FLOAT_T density)
{
	int bytes, i;
	
	if(size < 10) {size = 10;} 
	free_comb2(info);
	bytes = sizeof(DATA_T) * size;
	info->buf = (DATA_T *)safe_malloc(bytes);
	if(info->buf == NULL){
		info->alloc = 0;
		return;
	}
	info->alloc = 1;	
	memset(info->buf, 0, bytes);
	info->size = size;
	info->index = 0;
	info->feedback_wet = bal;	
	info->feedback_dry = 1.0 - bal;
	info->feedback_out = fb;
	info->net_in = 0;
	info->net_out = 0;
	info->dummy = 0;
	for(i = 0; i < NET_COMB_CON; i++)
		info->net_ptr[i] = &info->dummy;
	init_sample_filter(&info->fc, freq, 0, type);
	info->net_wet = density;
	info->net_dry = 1.0 - info->net_wet;
}

static inline void do_net_comb(comb2 *info, DATA_T *in, DATA_T *out)
{	
	DATA_T output, flt;
	int32 *index = &info->index;
	
	output = flt = info->buf[*index];
	sample_filter(&info->fc, &flt);	
	output = output * info->feedback_dry + flt * info->feedback_wet;
	*out += (info->net_out = output);
	info->buf[*index] = *in + (output * info->net_dry + info->net_in * info->net_wet) * info->feedback_out;
	if (++(*index) >= info->size) {*index = 0;}	
}

static void init_net_comb_fbc(comb2 *base, int info_num, int max_num)
{
	const FLOAT_T var[7] = {7/8, 2/8, 4/8, 1/8, 3/8, 5/8, 6/8,};
	int i, mod = info_num % NET_COMB_CON;
	comb2 *info = base + info_num;

	for(i = 0; i < NET_COMB_CON; i++){
		comb2 *net = NULL;
		int tmp = mod + i;
		if(tmp >= NET_COMB_CON)
			tmp -= NET_COMB_CON;
		tmp = info_num + max_num * var[tmp];
		if(tmp >= max_num)
			tmp -= max_num;
		net = base + tmp;
		if(&net->net_out)
			info->net_ptr[i] = &net->net_out;
	}
	// level total 1.0 : mul[0]=mul[CON-1]*2  mul[x]=((CON-1)*2-x) / (((CON-1)*2-0)+((CON-1)*2-1)...+((CON-1)*2-(CON-1)) 
#if NET_COMB_CON == 5
	info->cf[0] = 0.26666666666666666666666666666666; // 8/30
	info->cf[1] = 0.23333333333333333333333333333333; // 7/30
	info->cf[2] = 0.20000000000000000000000000000000; // 6/30
	info->cf[3] = 0.16666666666666666666666666666666; // 5/30
	info->cf[4] = 0.13333333333333333333333333333333; // 4/30
#elif NET_COMB_CON == 4
	info->cf[0] = 0.33333333333333333333333333333333; // 6/18
	info->cf[1] = 0.27777777777777777777777777777777; // 5/18
	info->cf[2] = 0.22222222222222222222222222222222; // 4/18
	info->cf[3] = 0.16666666666666666666666666666666; // 3/18
#elif NET_COMB_CON == 3
	info->cf[0] = 0.44444444444444444444444444444444; // 4/9
	info->cf[1] = 0.33333333333333333333333333333333; // 3/9
	info->cf[2] = 0.22222222222222222222222222222222; // 2/9
#elif NET_COMB_CON == 2
	info->cf[0] = 0.66666666666666666666666666666666; // 2/3
	info->cf[1] = 0.33333333333333333333333333333333; // 1/3
#else // NET_COMB_CON == 1
	info->cf[0] = 1.0; // 1/1
#endif
	// xnet (net_comb2
	// ある程度分散して ノイズ化しない変化速度で feedback lineを切り替える cfの和=1.0 一番シンプルな方法？
	// feedback 2lineを対にしてlfo triangluarでcrossfade mix, 2mixを対にしてlfoをcrossfade mix, ...
	// lfo wave:triangular(lite) out:0.0~1.0 freq:2.25Hz~4.133Hz, random:freq,phase
	for(i = 0; i < NET_COMB_LFO; i++){
		info->lfo_count[i] = 2.25 * div_playmode_rate * pow(1.75, get_white_noise_p());
		info->lfo_rate[i] = get_white_noise_p() * DIV_2; // 0.0~0.5
	}
}

static inline void do_net_comb_fbc(comb2 *info)
{	
#if NET_COMB_CON == 8
	info->net_in = *info->net_ptr[0] * info->cf[0]
		+ *info->net_ptr[1] * info->cf[1]
		+ *info->net_ptr[2] * info->cf[2]
		+ *info->net_ptr[3] * info->cf[3]
		+ *info->net_ptr[4] * info->cf[4]
		+ *info->net_ptr[5] * info->cf[5]
		+ *info->net_ptr[6] * info->cf[6]
		+ *info->net_ptr[7] * info->cf[7];
#elif NET_COMB_CON == 5
	info->net_in = *info->net_ptr[0] * info->cf[0]
		+ *info->net_ptr[1] * info->cf[1]
		+ *info->net_ptr[2] * info->cf[2]
		+ *info->net_ptr[3] * info->cf[3]
		+ *info->net_ptr[4] * info->cf[4];
#elif NET_COMB_CON == 4
	info->net_in = *info->net_ptr[0] * info->cf[0]
		+ *info->net_ptr[1] * info->cf[1]
		+ *info->net_ptr[2] * info->cf[2]
		+ *info->net_ptr[3] * info->cf[3];
#elif NET_COMB_CON == 3
	info->net_in = *info->net_ptr[0] * info->cf[0]
		+ *info->net_ptr[1] * info->cf[1]
		+ *info->net_ptr[2] * info->cf[2];
#elif NET_COMB_CON == 2
	info->net_in = *info->net_ptr[0] * info->cf[0]
		+ *info->net_ptr[1] * info->cf[1];	
#else
	info->net_in = *info->net_ptr[0]; // 1/1
#endif
}

// use xnet (net_comb2
static inline void pre_compute_net_comb_fbc(comb2 *info, int32 count)
{	
#if NET_COMB_CON == 8
	int i;
	FLOAT_T cf[NET_COMB_LFO][2];	

	for(i = 0; i < NET_COMB_CF; i++){
		if((cf[i][0] = info->lfo_count[i] * 2.0) > 1.0) {cf[i][0] = 2.0 - cf[i][0];}
		cf[i][1] = (1.0 - cf[i][0]);
		if((info->lfo_count[i] += info->freq[i] * count) >= 1.0) {info->lfo_count[i] -= 1.0;}	
	}
	for(i = 0; i < NET_COMB_CON; i++)
		info->cf[i] = cf[0][i & 0x1] * cf[1][(i >> 1) & 0x1] * cf[2][(i >> 2) & 0x1];
#elif NET_COMB_CON == 4
	FLOAT_T cf[NET_COMB_LFO][2];	

	if((cf[0][0] = info->lfo_count[0] * 2.0) > 1.0) {cf[0][0] = 2.0 - cf[0][0];}
	if((cf[1][0] = info->lfo_count[1] * 2.0) > 1.0) {cf[1][0] = 2.0 - cf[1][0];}
	cf[0][1] = (1.0 - cf[0][0]);
	cf[1][1] = (1.0 - cf[1][0]);
	info->cf[0] = cf[0][0] * cf[1][0];
	info->cf[1] = cf[0][1] * cf[1][0];
	info->cf[2] = cf[0][0] * cf[1][1];
	info->cf[3] = cf[0][1] * cf[1][1];
	if((info->lfo_count[0] += info->lfo_rate[0] * count) >= 1.0) {info->lfo_count[0] -= 1.0;}	
	if((info->lfo_count[1] += info->lfo_rate[1] * count) >= 1.0) {info->lfo_count[1] -= 1.0;}	
#elif NET_COMB_CON == 2
	FLOAT_T cf;	
	if((cf = info->lfo_count[0] * 2.0) > 1.0) {cf = 2.0 - cf;}
	info->cf[0] = cf;
	info->cf[1] = (1.0 - cf);
	if((info->lfo_count[0] += info->freq[0] * count) >= 1.0) {info->lfo_count[0] -= 1.0;}	
#else
#endif
}


// Reverb EX
#define REV_EX_ROOMSIZE_FCT (0.0029411764705882352941176470588235)
#define REV_EX_TIME     (1.6) 
#define REV_EX_LEVEL    (3.0) // total
#define REV_EX_ER_LEVEL (0.613 * REV_EX_LEVEL)
#define REV_EX_RV_LEVEL (1.022 * REV_EX_LEVEL)
#define REV_EX_FEEDBACK (0.25)
#define REV_EX_HPF_FREQ (107.73) // Hz
#define REV_EX_AP_LEVEL (0.33333)
#define REV_EX_AP_FB    (0.06125)
#define REV_EX_AP_BALANCE (0.55)
#define REV_EX_DAMP     (0.5)

double ext_reverb_ex_time = 1.0;
double ext_reverb_ex_level = 1.0;
double ext_reverb_ex_er_level = 1.0;
double ext_reverb_ex_rv_level = 1.0;
int ext_reverb_ex_rv_num = 16;
int ext_reverb_ex_ap_num = 8; // flag : 0 or 8 
//int ext_reverb_ex_lite = 0;
//int ext_reverb_ex_mode = 0;
//int ext_reverb_ex_er_num = 16;
//int ext_reverb_ex_rv_type = 1;
//int ext_reverb_ex_ap_type = 1;
// MOD
int ext_reverb_ex_mod = 0;
double ext_reverb_ex_rv_rate = 0.2; // 0.2Hz
double ext_reverb_ex_rv_depth = 3.0; // 3.0ms
double ext_reverb_ex_ap_rate = 0.1; // 0.15Hz
double ext_reverb_ex_ap_depth = 0.5; // 1.5ms

static void do_reverb_ex_none(DATA_T *buf, int32 count, InfoReverbEX *info);
static void do_reverb_ex_chST(DATA_T *buf, int32 count, InfoReverbEX *info);
static void do_reverb_ex_chMS(DATA_T *buf, int32 count, InfoReverbEX *info);
static void do_reverb_ex_chST_ap8(DATA_T *buf, int32 count, InfoReverbEX *info);
static void do_reverb_ex_chMS_ap8(DATA_T *buf, int32 count, InfoReverbEX *info);

static void rev_ex_mod_free_ap_delay(InfoReverbEX *info);
static void init_reverb_ex_mod(InfoReverbEX *info);

static void rev_ex_free_delay(InfoReverbEX *info, int type, int num)
{
	if(!info->alloc[num][type])
		return;
	if(info->buf[num][type] != NULL) {
#ifdef ALIGN_SIZE
		aligned_free(info->buf[num][type]);
#else
		free(info->buf[num][type]);
#endif
		info->buf[num][type] = NULL;
		info->alloc[num][type] = 0;
	}
}

static int rev_ex_init_delay(InfoReverbEX *info, int type, int num, int32 size)
{
	int32 bytes;
	rev_ex_free_delay(info, type, num);
	if(size < 10) {size = 10;} 
	bytes = sizeof(DATA_T) * (size + 1);
#ifdef ALIGN_SIZE
	info->buf[num][type] = (DATA_T *)aligned_malloc(bytes, ALIGN_SIZE);
#else
	info->buf[num][type] = (DATA_T *)safe_malloc(bytes);
#endif
	if(info->buf[num][type] == NULL) {return 1;} // error
	memset(info->buf[num][type], 0, bytes);
	info->size[num][type] = size;
	info->index[num][type] = 0;
	info->alloc[num][type] = 1;
	return 0;
}

static void rev_ex_init_rv_fbc(InfoReverbEX *info, int num, int unit_num)
{
	int tmp = num + unit_num * 3 / 4; // + :offset
	if(tmp >= unit_num) tmp -= unit_num;
	if(num & 0x2){ // swap
		info->rv_in[num][0] = &info->rv_out[tmp][1];
		info->rv_in[num][1] = &info->rv_out[tmp][0];
	}else{
		info->rv_in[num][0] = &info->rv_out[tmp][0];
		info->rv_in[num][1] = &info->rv_out[tmp][1];
	}
	info->rv_out[num][0] = info->rv_out[num][1] = 0;
}

static void rev_ex_free_rv_delay(InfoReverbEX *info)
{
	if(info->alloc2[REV_EX_RD]){
		if(info->buf2[REV_EX_RD] != NULL) {
#ifdef ALIGN_SIZE
			aligned_free(info->buf2[REV_EX_RD]);
#else
			free(info->buf2[REV_EX_RD]);
#endif
			info->buf2[REV_EX_RD] = NULL;
			info->alloc2[REV_EX_RD] = 0;
		}
	}
}

static int rev_ex_init_rv_delay(InfoReverbEX *info, int32 size)
{
	int32 bytes;
	rev_ex_free_rv_delay(info);
	if(size < 1) {size = 1;} 
	bytes = sizeof(DATA_T) * (size + 1) * 2; // ch
#ifdef ALIGN_SIZE
	info->buf2[REV_EX_RD] = (DATA_T *)aligned_malloc(bytes, ALIGN_SIZE);
#else
	info->buf2[REV_EX_RD] = (DATA_T *)safe_malloc(bytes);
#endif
	if(info->buf2[REV_EX_RD] == NULL) {return 1;} // error
	memset(info->buf2[REV_EX_RD], 0, bytes);
	info->alloc2[REV_EX_RD] = 1;
	info->size2[REV_EX_RD] = size * 2;
	info->index2[REV_EX_RD] = 0;
	return 0;
}

static void rev_ex_free_ap_delay(InfoReverbEX *info)
{
	int i;	
	for (i = 0; i < REV_EX_DELAY; i++) {
		if(info->aalloc[i]){
			if(info->abuf[i] != NULL) {
#ifdef ALIGN_SIZE
				aligned_free(info->abuf[i]);
#else
				free(info->abuf[i]);
#endif
				info->abuf[i] = NULL;
				info->aalloc[i] = 0;
			}
		}
	}
}

static int rev_ex_init_ap_delay(InfoReverbEX *info, int32 size)
{
	int32 i, bytes;
	rev_ex_free_ap_delay(info);	
	bytes = sizeof(DATA_T) * (size + 1); // +1 interporation	
	for (i = 0; i < REV_EX_DELAY; i++) {
#ifdef ALIGN_SIZE
		info->abuf[i] = (DATA_T *)aligned_malloc(bytes, ALIGN_SIZE);
#else
		info->abuf[i] = (DATA_T *)safe_malloc(bytes);
#endif
		if(info->abuf[i] == NULL) {return 1;} // error
		info->aalloc[i] = 1;
		memset(info->abuf[i], 0, bytes);
	}
	return 0;
}

static void free_reverb_ex(InfoReverbEX *info)
{
	int i;	
	if(!info)
		return;
	if(!info->init)
		return;
	for (i = 0; i < REV_EX_UNITS; i++) {	
		rev_ex_free_delay(info, REV_EX_ER_L1, i);
		rev_ex_free_delay(info, REV_EX_ER_R1, i);
		rev_ex_free_delay(info, REV_EX_RV_L1, i);
		rev_ex_free_delay(info, REV_EX_RV_R1, i);
	}
	rev_ex_free_rv_delay(info);
	rev_ex_free_ap_delay(info);
	info->init = 0;
}

static void init_reverb_ex(InfoReverbEX *info)
{
	int32 i, error = 0;
	FLOAT_T pdelay_cnt, room_cnt, dtS1, dtL1, dtS2, dtL2, lenS1, lenL1, lenS2, lenL2, lenA,
		qrt, ww, fbS, fbL, div_time;
	int num, num_div2;
	FLOAT_T div_num, norm, fbmax = 0;

	// test
	// ext_reverb_ex_er_num
	//info->mode = CH_MIX_STEREO;
	//info->depth = 3.0;
	//info->width = 3.0;
	//info->height = 3.0;
	//info->flt_type = 6;
	//info->er_time_ms = 200;
	//info->depth = 150.0;
	//info->width = 120.0;
	//info->height = 80.0;
	//info->rev_time_sec = 40.0;
	//info->rev_level = 1.0;	
	//info->er_level = 0;
	//info->er_level = 1.0;
	//info->rev_level = 0;
	////info->rev_damp_bal = 1.0;
	//info->feedback = 0;
	//info->rev_dly_ms = 0;

	// mod
	if(ext_reverb_ex_mod){
		init_reverb_ex_mod(info);
		return;
	}

	//units	
	ext_reverb_ex_rv_num = clip_int(ext_reverb_ex_rv_num, 8, REV_EX_UNITS); // min 8
	num = ext_reverb_ex_rv_num;
	num_div2 = num / 2;
	div_num = 1.0 / (FLOAT_T)num;
	norm = pow(div_num, DIV_3_2);
	ext_reverb_ex_ap_num = ext_reverb_ex_ap_num ? REV_EX_AP_MAX : 0;
	// init
	init_prime_list();
	pdelay_cnt = info->er_time_ms * playmode_rate_ms;	
	room_cnt = REV_EX_ROOMSIZE_FCT * (FLOAT_T)play_mode->rate;	// leng[m] * div_s[s/m] * rate[cnt/s]
	qrt = pow(info->width * info->height * info->depth, DIV_3);
	lenS1 = info->depth;
	lenL1 = sqrt(sq(info->width) + sq(info->height) + sq(info->depth)) * 2.0;
	lenL2 = qrt * SQRT_2 * 2.0;
	lenS2 = lenL2 * DIV_PI;
	lenA = lenS2 * DIV_PI;
	if((pdelay_cnt -= room_cnt * lenS1) < 0)
		pdelay_cnt = 0;
	dtS1 = pdelay_cnt + room_cnt * lenS1;
	dtL1 = pdelay_cnt + room_cnt * lenL1;
	dtS2 = room_cnt * lenS2;
	dtL2 = room_cnt * lenL2;
	ww = sqrt(sqrt(info->width * info->height) / qrt);
	div_time = 1.0 / (info->rev_time_sec * ext_reverb_ex_time);
	fbL = pow(10.0, -3.0 * lenL2 * REV_EX_ROOMSIZE_FCT * div_time); // rev time to fb level
	fbS = pow(10.0, -3.0 * lenS2 * REV_EX_ROOMSIZE_FCT * div_time); // rev time to fb level
	for (i = 0; i < num; i++) {
		FLOAT_T rt, dt;
		int32 dtiL1, dtiR1;
		// er	
		rt = div_num * i;
		dt = dtS1 * (1.0 - rt) + dtL1 * rt; // dtS1->dtL1
		dtiL1 = dt * pow(1.05, sqrt(rt) * get_white_noise_p());
		dtiR1 = dt * pow(1.05, sqrt(rt) * get_white_noise_p());
		error += rev_ex_init_delay(info, REV_EX_ER_L1, i, dtiL1);
		error += rev_ex_init_delay(info, REV_EX_ER_R1, i, dtiR1);
		// fb
		rt = sqrt(div_num * i);
		info->rv_feedback[i] = fbS * (1.0 - rt) + fbL * rt;		
		if(fbmax < info->rv_feedback[i])
			fbmax = info->rv_feedback[i];
		// rv
		rt = i < num_div2 ? sq(div_num * i * 2.0) : sq(1.0 - div_num * i * 2.0);
		dt = dtS2 * (1.0 - rt) + dtL2 * rt; // dtS2->dtL2->dtS2
		dtiL1 = dt * pow(ww, get_white_noise_p());
		dtiR1 = dt * pow(ww, get_white_noise_p());
		find_prime(&dtiL1);	find_prime(&dtiR1);
		error += rev_ex_init_delay(info, REV_EX_RV_L1, i, dtiL1);
		error += rev_ex_init_delay(info, REV_EX_RV_R1, i, dtiR1);
		rev_ex_init_rv_fbc(info, i, num);			
		set_sample_filter_type(&info->rv_fc1[i], FILTER_NONE);
		init_sample_filter(&info->rv_fc1[i], info->rev_damp_freq * pow(0.9, get_white_noise_p()) * REV_EX_DAMP, 0, FILTER_LPF6); //info->rev_damp_type);
	}	
	rev_ex_init_rv_delay(info, info->rev_dly_ms * playmode_rate_ms);
	if(ext_reverb_ex_ap_num){
		int32 size = 0, apnum_div2 = ext_reverb_ex_ap_num / 2;
		FLOAT_T div_apnum = 1.0 / (FLOAT_T)ext_reverb_ex_ap_num;
		for (i = 0; i < ext_reverb_ex_ap_num; i++) {
			FLOAT_T rt, dt;
			int32 dti;
			// ap1
			rt = div_apnum * i;
			dt = dtS1 * (1.0 - rt) + dtL1 * rt; // dtS1->dtL1
			dti = (dt - pdelay_cnt) * DIV_SQRT2;
			dti += 1;
			find_prime(&dti);
			info->delaya[i][REV_EX_ER_L1] = dti;
			if(dti > size)
				size = dti;
			dti = (dt - pdelay_cnt) * DIV_SQRT2;
			dti += 5; // st spread
			find_prime(&dti);
			info->delaya[i][REV_EX_ER_R1] = dti;
			if(dti > size)
				size = dti;
			// ap2
			rt = i < apnum_div2 ? sqrt(div_apnum * i * 2.0) : sqrt(1.0 - div_apnum * i * 2.0);
			dt = dtS2 * (1.0 - rt) + dtL2 * rt; // dtS2->dtL2->dtS2
			dti = dt * DIV_SQRT2;
			dti += 3;
			find_prime(&dti);
			info->delaya[i][REV_EX_RV_L1] = dti;
			if(dti > size)
				size = dti;
			dti = dt * DIV_SQRT2;
			dti += 7; // st spread
			find_prime(&dti);
			info->delaya[i][REV_EX_RV_R1] = dti;
			if(dti > size)
				size = dti;
		}
		info->index2[REV_EX_AP1] = 0;
		info->index2[REV_EX_AP2] = 0;
		++size;
		if(size < 2) size = 2;
		info->size2[REV_EX_AP1] = size;
		info->size2[REV_EX_AP2] = size;
		error += rev_ex_init_ap_delay(info, size);
	}
	set_sample_filter_type(&info->er_fc, FILTER_NONE);
	init_sample_filter(&info->er_fc, info->er_damp_freq * REV_EX_DAMP, 0, FILTER_LPF6); //info->rev_damp_type);
	set_sample_filter_type(&info->hpf, FILTER_NONE);
	init_sample_filter(&info->hpf, REV_EX_HPF_FREQ, 0, FILTER_HPF_BW);	
	info->unit_num = num;
	info->st_sprd = div_num; // L+,R-
	info->flt_wet = (info->rev_damp_bal + 1.0) * DIV_2;
	info->flt_dry = 1.0 - info->flt_wet;
	info->feedback = info->rev_feedback * REV_EX_FEEDBACK;
	info->leveler = norm * REV_EX_ER_LEVEL
		* info->er_level * ext_reverb_ex_er_level * ext_reverb_ex_level;
	if(fbmax < 0.01)
		fbmax = 0.01;
	else if(fbmax > 0.99)
		fbmax = 0.99;
	fbmax = sqrt(3.0 / pow(1.0 / (1.0 - fbmax), DIV_3_2));
	info->levelrv = sq(norm) / (sqrt(1.0 + (fbL + fbS) * DIV_2)) * REV_EX_RV_LEVEL
		* info->rev_level * ext_reverb_ex_rv_level * ext_reverb_ex_level * fbmax; // rv_fb
	info->levelap = (info->density + 1.0) * DIV_2 * REV_EX_AP_LEVEL;
	if(ext_reverb_ex_ap_num){
		info->leveler *= REV_EX_AP_BALANCE;
		info->levelrv *= REV_EX_AP_BALANCE;
	}
// int32の場合 er/rvのミックス部分がint32超える気がするので 入力下げて出力上げ 8bit分
#if !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT)
#if (OPT_MODE == 1)/* fixed-point implementation */
	info->in_leveli = TIM_FSCALE(DIV_MIX_LEVEL, 24 - 8); // input // imuldiv24 //  * DIV_MIX_LEVEL部分
	info->st_sprdi = TIM_FSCALE(info->st_sprd, 24 - 8); // input // imuldiv24 // * st_sprd部分
	info->flt_weti = TIM_FSCALE(info->flt_wet, 24);
	info->flt_dryi = TIM_FSCALE(info->flt_dry, 24);
	info->feedbacki = TIM_FSCALE(info->feedback, 24 - 8); // input // imuldiv24 // * feedback部分
	info->leveleri = TIM_FSCALE(info->leveler , 24); // output // imuldiv16
	info->levelrvi = TIM_FSCALE(info->levelrv , 24); // output // imuldiv16	
	info->levelapi = TIM_FSCALE(info->levelap , 24);;
	for (i = 0; i < num; i++)
		info->rv_feedbacki[i] = TIM_FSCALE(info->rv_feedback[i], 24);
#else // OPT_MODE 0 /* floating-point implementation */
	info->in_level = DIV_8BIT;
	info->leveler *= M_8BIT;
	info->levelrv *= M_8BIT;
#endif /* OPT_MODE == 1 */
#endif /* !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) */
	info->hist[0] = info->hist[1] = 0;	
	info->fb_ap1[0] = info->fb_ap1[1] = 0;	
	info->fb_ap2[0] = info->fb_ap2[1] = 0;	
	// func
	switch(info->mode){
	case CH_STEREO:
		info->do_reverb_mode = ext_reverb_ex_ap_num ? do_reverb_ex_chST_ap8 : do_reverb_ex_chST;
		break;
	case CH_MIX_STEREO:
		info->do_reverb_mode = ext_reverb_ex_ap_num ? do_reverb_ex_chMS_ap8 : do_reverb_ex_chMS;
		break;
	default:
		info->do_reverb_mode = do_reverb_ex_none;
		break;
	}
	if(error) info->do_reverb_mode = do_reverb_ex_none; // safe
	info->init = 1;
}

static void do_reverb_ex_none(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	//int32 k = 0;
	//for (k = 0; k < count; k++)	{buf[k] = 0;} // wet 0
	memset(buf, 0, sizeof(DATA_T) * count); // count > 0 // wet 0 
}


#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void do_reverb_ex_chST(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	int32 leveler = info->leveleri, levelrv = info->levelrvi, feedback = info->feedbacki,
		*rv_feedback = info->rv_feedbacki, flt_dry = info->flt_dryi, flt_wet = info->flt_weti,
		*dcH = hpf->dc, *dcL = er_fc->dc, in_level = info->in_leveli, st_sprd = info->st_sprdi;
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[8], *dbL = er_fc->db; 
	DATA_T *hist = info->hist, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2], sprd;
	// CH_STEREO:
	for (k = 0; k < count; k++)
	{		
		input[0] = buf[k]; input[1] = buf[k + 1];
		sprd = imuldiv24((input[0] - input[1]), st_sprd);
		input[0] = input[1] = imuldiv24((input[0] + input[1]), in_level);
		input[0] += imuldiv24(hist[0], feedback); input[1] += imuldiv24(hist[1], feedback);
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		// unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		for (i = 0; i < info->unit_num; i++) {
			// index inc
			DATA_T *buf[4];
			int32 *index[4] = {&info->index[i][0], &info->index[i][1], &info->index[i][2], &info->index[i][3],};
			if (++(*index[0]) >= info->size[i][0]) {*index[0] = 0;}
			if (++(*index[1]) >= info->size[i][1]) {*index[1] = 0;}
			if (++(*index[2]) >= info->size[i][2]) {*index[2] = 0;}
			if (++(*index[3]) >= info->size[i][3]) {*index[3] = 0;}
			buf[0] = &info->buf[i][0][*index[0]];
			buf[1] = &info->buf[i][1][*index[1]];
			buf[2] = &info->buf[i][2][*index[2]];
			buf[3] = &info->buf[i][3][*index[3]];
			// er out
			dat_er[0] += *buf[0]; dat_er[1] += *buf[1];
			// er in
			*buf[0] = input[0]; *buf[1] = input[1];
			input[0] += sprd; input[1] -= sprd; // spread
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = *buf[2];
			tmp1[1] = *buf[3];
			lpf = &rv_fc[i];
			lpf->db[0] = imuldiv28(tmp1[0], lpf->dc[0]) + imuldiv28(lpf->db[0], lpf->dc[1]);
			lpf->db[1] = imuldiv28(tmp1[1], lpf->dc[0]) + imuldiv28(lpf->db[1], lpf->dc[1]);
			dat_rv[0] += (info->rv_out[i][0] = imuldiv24(tmp1[0], flt_dry) + imuldiv24(lpf->db[0], flt_wet));
			dat_rv[1] += (info->rv_out[i][1] = imuldiv24(tmp1[1], flt_dry) + imuldiv24(lpf->db[1], flt_wet));
			// rv in
			*buf[2] = input_rv[0] + imuldiv24(tmp_rv[0], rv_feedback[i]);
			*buf[3] = input_rv[1] + imuldiv24(tmp_rv[1], rv_feedback[i]);
		}
		// er flt
		dbL[0] = imuldiv28(dat_er[0], dcL[0]) + imuldiv28(dbL[0], dcL[1]);
		dbL[1] = imuldiv28(dat_er[1], dcL[0]) + imuldiv28(dbL[1], dcL[1]);
		dat_er[0] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[0], flt_wet);
		dat_er[1] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[1], flt_wet);
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// out
		hist[0] = imuldiv16(dat_rv[0], levelrv) - imuldiv16(dat_er[0], leveler);
		hist[1] = imuldiv16(dat_rv[1], levelrv) - imuldiv16(dat_er[1], leveler);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = imuldiv28(dbHL[0], dcH[0]) + imuldiv28(dbHL[1], dcH[1]) + imuldiv28(dbHL[2], dcH[2])
			- imuldiv28(dbHL[3], dcH[3]) - imuldiv28(dbHL[4], dcH[4]);
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = imuldiv28(dbHR[0], dcH[0]) + imuldiv28(dbHR[1], dcH[1]) + imuldiv28(dbHR[2], dcH[2])
			- imuldiv28(dbHR[3], dcH[3]) - imuldiv28(dbHR[4], dcH[4]);
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];		
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
}

static void do_reverb_ex_chMS(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	int32 leveler = info->leveleri, levelrv = info->levelrvi, feedback = info->feedbacki,
		*rv_feedback = info->rv_feedbacki, flt_dry = info->flt_dryi, flt_wet = info->flt_weti,
		*dcH = hpf->dc, *dcL = er_fc->dc, in_level = info->in_leveli;
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T	*hist = info->hist, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2];
	// CH_MIX_STEREO:
	for (k = 0; k < count; k++)
	{		
		input[0] = input[1] = imuldiv24((buf[k] + buf[k + 1]), info->in_level);
		input[0] += imuldiv24(hist[0], feedback); input[1] += imuldiv24(hist[1], feedback);
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		// unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		for (i = 0; i < info->unit_num; i++) {
			// index inc
			DATA_T *buf[4];
			int32 *index[4] = {&info->index[i][0], &info->index[i][1], &info->index[i][2], &info->index[i][3],};
			if (++(*index[0]) >= info->size[i][0]) {*index[0] = 0;}
			if (++(*index[1]) >= info->size[i][1]) {*index[1] = 0;}
			if (++(*index[2]) >= info->size[i][2]) {*index[2] = 0;}
			if (++(*index[3]) >= info->size[i][3]) {*index[3] = 0;}
			buf[0] = &info->buf[i][0][*index[0]];
			buf[1] = &info->buf[i][1][*index[1]];
			buf[2] = &info->buf[i][2][*index[2]];
			buf[3] = &info->buf[i][3][*index[3]];
			// er out
			dat_er[0] += *buf[0]; dat_er[1] += *buf[1];
			// er in
			*buf[0] = input[0]; *buf[1] = input[1];
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = *buf[2];
			tmp1[1] = *buf[3];
			lpf = &rv_fc[i];
			lpf->db[0] = imuldiv28(tmp1[0], lpf->dc[0]) + imuldiv28(lpf->db[0], lpf->dc[1]);
			lpf->db[1] = imuldiv28(tmp1[1], lpf->dc[0]) + imuldiv28(lpf->db[1], lpf->dc[1]);
			dat_rv[0] += (info->rv_out[i][0] = imuldiv24(tmp1[0], flt_dry) + imuldiv24(lpf->db[0], flt_wet));
			dat_rv[1] += (info->rv_out[i][1] = imuldiv24(tmp1[1], flt_dry) + imuldiv24(lpf->db[1], flt_wet));
			// rv in
			*buf[2] = input_rv[0] + imuldiv24(tmp_rv[0], rv_feedback[i]);
			*buf[3] = input_rv[1] + imuldiv24(tmp_rv[1], rv_feedback[i]);
		}
		// er flt
		dbL[0] = imuldiv28(dat_er[0], dcL[0]) + imuldiv28(dbL[0], dcL[1]);
		dbL[1] = imuldiv28(dat_er[1], dcL[0]) + imuldiv28(dbL[1], dcL[1]);
		dat_er[0] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[0], flt_wet);
		dat_er[1] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[1], flt_wet);
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// out
		hist[0] = imuldiv16(dat_rv[0], levelrv) - imuldiv16(dat_er[0], leveler);
		hist[1] = imuldiv16(dat_rv[1], levelrv) - imuldiv16(dat_er[1], leveler);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = imuldiv28(dbHL[0], dcH[0]) + imuldiv28(dbHL[1], dcH[1]) + imuldiv28(dbHL[2], dcH[2])
			- imuldiv28(dbHL[3], dcH[3]) - imuldiv28(dbHL[4], dcH[4]);
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = imuldiv28(dbHR[0], dcH[0]) + imuldiv28(dbHR[1], dcH[1]) + imuldiv28(dbHR[2], dcH[2])
			- imuldiv28(dbHR[3], dcH[3]) - imuldiv28(dbHR[4], dcH[4]);
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];		
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
}

static void do_reverb_ex_chST_ap8(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	int32 leveler = info->leveleri, levelrv = info->levelrvi, feedback = info->feedbacki,
		*rv_feedback = info->rv_feedbacki, flt_dry = info->flt_dryi, flt_wet = info->flt_weti,
		*dcH = hpf->dc, *dcL = er_fc->dc, in_level = info->in_leveli, st_sprd = info->st_sprdi;
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T	*hist = info->hist, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2], sprd;
	int32 *indexap = &info->index2[REV_EX_AP1], sizeap = info->size2[REV_EX_AP1];
	DATA_T *fb_ap1 = info->fb_ap1, *fb_ap2 = info->fb_ap2;
	int32 levelap = info->levelapi;
	const int32 apfbi = TIM_FSCALE(REV_EX_AP_FB, 24);
	// CH_STEREO:
	for (k = 0; k < count; k++)
	{		
		input[0] = buf[k]; input[1] = buf[k + 1];
		sprd = imuldiv24((input[0] - input[1]), st_sprd);
		input[0] = input[1] = imuldiv24((input[0] + input[1]), in_level);
		input[0] += imuldiv24(hist[0], feedback); input[1] += imuldiv24(hist[1], feedback);
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		// unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		for (i = 0; i < info->unit_num; i++) {
			// index inc
			DATA_T *buf[4];
			int32 *index[4] = {&info->index[i][0], &info->index[i][1], &info->index[i][2], &info->index[i][3],};
			if (++(*index[0]) >= info->size[i][0]) {*index[0] = 0;}
			if (++(*index[1]) >= info->size[i][1]) {*index[1] = 0;}
			if (++(*index[2]) >= info->size[i][2]) {*index[2] = 0;}
			if (++(*index[3]) >= info->size[i][3]) {*index[3] = 0;}
			buf[0] = &info->buf[i][0][*index[0]];
			buf[1] = &info->buf[i][1][*index[1]];
			buf[2] = &info->buf[i][2][*index[2]];
			buf[3] = &info->buf[i][3][*index[3]];
			// er out
			dat_er[0] += *buf[0]; dat_er[1] += *buf[1];
			// er in
			*buf[0] = input[0]; *buf[1] = input[1];
			input[0] += sprd; input[1] -= sprd; // spread
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = *buf[2];
			tmp1[1] = *buf[3];
			lpf = &rv_fc[i];
			lpf->db[0] = imuldiv28(tmp1[0], lpf->dc[0]) + imuldiv28(lpf->db[0], lpf->dc[1]);
			lpf->db[1] = imuldiv28(tmp1[1], lpf->dc[0]) + imuldiv28(lpf->db[1], lpf->dc[1]);
			dat_rv[0] += (info->rv_out[i][0] = imuldiv24(tmp1[0], flt_dry) + imuldiv24(lpf->db[0], flt_wet));
			dat_rv[1] += (info->rv_out[i][1] = imuldiv24(tmp1[1], flt_dry) + imuldiv24(lpf->db[1], flt_wet));
			// rv in
			*buf[2] = input_rv[0] + imuldiv24(tmp_rv[0], rv_feedback[i]);
			*buf[3] = input_rv[1] + imuldiv24(tmp_rv[1], rv_feedback[i]);
		}
		// er flt
		dbL[0] = imuldiv28(dat_er[0], dcL[0]) + imuldiv28(dbL[0], dcL[1]);
		dbL[1] = imuldiv28(dat_er[1], dcL[0]) + imuldiv28(dbL[1], dcL[1]);
		dat_er[0] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[0], flt_wet);
		dat_er[1] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[1], flt_wet);
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// ap
		if ((++(*indexap)) >= sizeap) {*indexap -= sizeap;}
		info->abuf[0][*indexap] = imuldiv24(dat_er[0], levelap) + imuldiv24(fb_ap1[0], apfbi); 
		info->abuf[1][*indexap] = imuldiv24(dat_er[1], levelap) + imuldiv24(fb_ap1[1], apfbi); 
		info->abuf[2][*indexap] = imuldiv24(dat_rv[0], levelap) + imuldiv24(fb_ap2[0], apfbi); 
		info->abuf[3][*indexap] = imuldiv24(dat_rv[1], levelap) + imuldiv24(fb_ap2[1], apfbi);  
		for (i = 0; i < REV_EX_AP_MAX; i++) {
			int32 index;
			// ap1 er
			if((index = *indexap - info->delaya[i][0]) < 0) {index += sizeap;} 
			dat_er[0] += info->abuf[0][index]; 
			if((index = *indexap - info->delaya[i][1]) < 0) {index += sizeap;}
			dat_er[1] += info->abuf[1][index]; 	
			// ap2 rv
			if((index = *indexap - info->delaya[i][2]) < 0) {index += sizeap;}
			dat_rv[0] += info->abuf[2][index]; 
			if((index = *indexap - info->delaya[i][3]) < 0) {index += sizeap;}
			dat_rv[1] += info->abuf[3][index]; 
		}
		fb_ap1[0] = dat_er[0]; fb_ap1[1] = dat_er[1];
		fb_ap2[0] = dat_rv[0]; fb_ap2[1] = dat_rv[1];
		// out
		hist[0] = imuldiv16(dat_rv[0], levelrv) - imuldiv16(dat_er[0], leveler);
		hist[1] = imuldiv16(dat_rv[1], levelrv) - imuldiv16(dat_er[1], leveler);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = imuldiv28(dbHL[0], dcH[0]) + imuldiv28(dbHL[1], dcH[1]) + imuldiv28(dbHL[2], dcH[2])
			- imuldiv28(dbHL[3], dcH[3]) - imuldiv28(dbHL[4], dcH[4]);
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = imuldiv28(dbHR[0], dcH[0]) + imuldiv28(dbHR[1], dcH[1]) + imuldiv28(dbHR[2], dcH[2])
			- imuldiv28(dbHR[3], dcH[3]) - imuldiv28(dbHR[4], dcH[4]);
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];		
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
}

static void do_reverb_ex_chMS_ap8(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	int32 leveler = info->leveleri, levelrv = info->levelrvi, feedback = info->feedbacki,
		*rv_feedback = info->rv_feedbacki, flt_dry = info->flt_dryi, flt_wet = info->flt_weti,
		*dcH = hpf->dc, *dcL = er_fc->dc, in_level = info->in_leveli;
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T	*hist = info->hist, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2];
	int32 *indexap = &info->index2[REV_EX_AP1], sizeap = info->size2[REV_EX_AP1];
	DATA_T *fb_ap1 = info->fb_ap1, *fb_ap2 = info->fb_ap2;
	int32 levelap = info->levelapi;
	const int32 apfbi = TIM_FSCALE(REV_EX_AP_FB, 24);
	// CH_MIX_STEREO:
	for (k = 0; k < count; k++)
	{		
		input[0] = input[1] = imuldiv24((buf[k] + buf[k + 1]), info->in_level);
		input[0] += imuldiv24(hist[0], feedback); input[1] += imuldiv24(hist[1], feedback);
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		// unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		for (i = 0; i < info->unit_num; i++) {
			// index inc
			DATA_T *buf[4];
			int32 *index[4] = {&info->index[i][0], &info->index[i][1], &info->index[i][2], &info->index[i][3],};
			if (++(*index[0]) >= info->size[i][0]) {*index[0] = 0;}
			if (++(*index[1]) >= info->size[i][1]) {*index[1] = 0;}
			if (++(*index[2]) >= info->size[i][2]) {*index[2] = 0;}
			if (++(*index[3]) >= info->size[i][3]) {*index[3] = 0;}
			buf[0] = &info->buf[i][0][*index[0]];
			buf[1] = &info->buf[i][1][*index[1]];
			buf[2] = &info->buf[i][2][*index[2]];
			buf[3] = &info->buf[i][3][*index[3]];
			// er out
			dat_er[0] += *buf[0]; dat_er[1] += *buf[1];
			// er in
			*buf[0] = input[0]; *buf[1] = input[1];
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = *buf[2];
			tmp1[1] = *buf[3];
			lpf = &rv_fc[i];
			lpf->db[0] = imuldiv28(tmp1[0], lpf->dc[0]) + imuldiv28(lpf->db[0], lpf->dc[1]);
			lpf->db[1] = imuldiv28(tmp1[1], lpf->dc[0]) + imuldiv28(lpf->db[1], lpf->dc[1]);
			dat_rv[0] += (info->rv_out[i][0] = imuldiv24(tmp1[0], flt_dry) + imuldiv24(lpf->db[0], flt_wet));
			dat_rv[1] += (info->rv_out[i][1] = imuldiv24(tmp1[1], flt_dry) + imuldiv24(lpf->db[1], flt_wet));
			// rv in
			*buf[2] = input_rv[0] + imuldiv24(tmp_rv[0], rv_feedback[i]);
			*buf[3] = input_rv[1] + imuldiv24(tmp_rv[1], rv_feedback[i]);
		}
		// er flt
		dbL[0] = imuldiv28(dat_er[0], dcL[0]) + imuldiv28(dbL[0], dcL[1]);
		dbL[1] = imuldiv28(dat_er[1], dcL[0]) + imuldiv28(dbL[1], dcL[1]);
		dat_er[0] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[0], flt_wet);
		dat_er[1] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[1], flt_wet);
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// ap
		if ((++(*indexap)) >= sizeap) {*indexap -= sizeap;}
		info->abuf[0][*indexap] = imuldiv24(dat_er[0], levelap) + imuldiv24(fb_ap1[0], apfbi); 
		info->abuf[1][*indexap] = imuldiv24(dat_er[1], levelap) + imuldiv24(fb_ap1[1], apfbi); 
		info->abuf[2][*indexap] = imuldiv24(dat_rv[0], levelap) + imuldiv24(fb_ap2[0], apfbi); 
		info->abuf[3][*indexap] = imuldiv24(dat_rv[1], levelap) + imuldiv24(fb_ap2[1], apfbi);  
		for (i = 0; i < REV_EX_AP_MAX; i++) {
			int32 index;
			// ap1 er
			if((index = *indexap - info->delaya[i][0]) < 0) {index += sizeap;} 
			dat_er[0] += info->abuf[0][index]; 
			if((index = *indexap - info->delaya[i][1]) < 0) {index += sizeap;}
			dat_er[1] += info->abuf[1][index]; 	
			// ap2 rv
			if((index = *indexap - info->delaya[i][2]) < 0) {index += sizeap;}
			dat_rv[0] += info->abuf[2][index]; 
			if((index = *indexap - info->delaya[i][3]) < 0) {index += sizeap;}
			dat_rv[1] += info->abuf[3][index]; 
		}
		fb_ap1[0] = dat_er[0]; fb_ap1[1] = dat_er[1];
		fb_ap2[0] = dat_rv[0]; fb_ap2[1] = dat_rv[1];
		// out
		hist[0] = imuldiv16(dat_rv[0], levelrv) - imuldiv16(dat_er[0], leveler);
		hist[1] = imuldiv16(dat_rv[1], levelrv) - imuldiv16(dat_er[1], leveler);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = imuldiv28(dbHL[0], dcH[0]) + imuldiv28(dbHL[1], dcH[1]) + imuldiv28(dbHL[2], dcH[2])
			- imuldiv28(dbHL[3], dcH[3]) - imuldiv28(dbHL[4], dcH[4]);
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = imuldiv28(dbHR[0], dcH[0]) + imuldiv28(dbHR[1], dcH[1]) + imuldiv28(dbHR[2], dcH[2])
			- imuldiv28(dbHR[3], dcH[3]) - imuldiv28(dbHR[4], dcH[4]);
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];		
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
}

#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE) && defined(FLOAT_T_DOUBLE)
/*
SSE2 128bitSIMD : double*2ch, int32*4ch
x64AVXで問題・・?
*/
static void do_reverb_ex_chST(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0;
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	DATA_T *bufrd = info->buf2[REV_EX_RD];
	__m128d	vec_dcH0 = MM_LOAD1_PD(&hpf->dc[0]), vec_dcH1 = MM_LOAD1_PD(&hpf->dc[1]), vec_dcH2 = MM_LOAD1_PD(&hpf->dc[2]), 
		vec_dcH3 = MM_LOAD1_PD(&hpf->dc[3]), vec_dcH4 = MM_LOAD1_PD(&hpf->dc[4]),
		vec_dcL0 = MM_LOAD1_PD(&er_fc->dc[0]), vec_dcL1 = MM_LOAD1_PD(&er_fc->dc[1]);
	__m128d	vec_dbH0 = _mm_loadu_pd(&hpf->db[0]), vec_dbH1 = _mm_loadu_pd(&hpf->db[2]), vec_dbH2 = _mm_loadu_pd(&hpf->db[4]), 
		vec_dbH3 = _mm_loadu_pd(&hpf->db[6]), vec_dbH4 = _mm_loadu_pd(&hpf->db[8]), vec_dbL = _mm_loadu_pd(er_fc->db);
	__m128d vec_tmp1, vec_input_er, vec_input_rv, vec_mixer, vec_mixap, vec_mixrv, vec_tmp_rv, vec_db, vec_sprd,
		vec_leveler = MM_LOAD1_PD(&info->leveler), vec_levelrv = MM_LOAD1_PD(&info->levelrv),
		vec_dry = MM_LOAD1_PD(&info->flt_dry), vec_wet = MM_LOAD1_PD(&info->flt_wet),
		vec_feedback = MM_LOAD1_PD(&info->feedback), vec_hist = _mm_loadu_pd(info->hist);
	__m128d vec_sp_sprd = _mm_set_pd(-info->st_sprd, info->st_sprd);
	__m128i index2 = _mm_loadu_si128((__m128i *)info->index2), size2 = _mm_loadu_si128((__m128i *)info->size2);
	__m128i add_idx2 = _mm_set_epi32(1, 1, 2, 1);
	// CH_STEREO:
	for (k = 0; k < count; k += 2)
	{		
		int32 tmpi0;
		vec_sprd = _mm_mul_pd(_mm_set1_pd(buf[k] - buf[k + 1]), vec_sp_sprd);
		vec_input_er = _mm_add_pd(_mm_set1_pd((buf[k] + buf[k + 1]) * DIV_MIX_LEVEL), _mm_mul_pd(vec_hist, vec_feedback));
		// index2 (rv delay, ap
		index2 = _mm_add_epi32(index2, add_idx2);
		index2 = _mm_and_si128(index2, _mm_cmplt_epi32(index2, size2));
		tmpi0 = MM_EXTRACT_EPI32(index2, REV_EX_RD);
		// rv delay out
		vec_input_rv = _mm_load_pd(&bufrd[tmpi0]); // REV_EX_RD
		// unit
		vec_mixer = _mm_setzero_pd(); vec_mixrv = _mm_setzero_pd();
		for (i = 0; i < info->unit_num; i++) {
		ALIGN int32 tmpi[4];
		// index inc
		__m128i vec_index = _mm_loadu_si128((__m128i *)&info->index[i][0]); 
		__m128i vec_size = _mm_loadu_si128((__m128i *)&info->size[i][0]);
		vec_index = _mm_add_epi32(vec_index, _mm_set_epi32(1, 1, 1, 1));
		vec_index = _mm_and_si128(vec_index, _mm_cmplt_epi32(vec_index, vec_size));
		_mm_storeu_si128((__m128i *)&info->index[i][0], vec_index);
		// er
		_mm_store_si128((__m128i *)&tmpi, vec_index);
		vec_mixer = _mm_add_pd(vec_mixer, _mm_set_pd(info->buf[i][1][tmpi[1]], info->buf[i][0][tmpi[0]]));
		_mm_store_sd(&(info->buf[i][0][tmpi[0]]), vec_input_er); 
		_mm_store_sd(&(info->buf[i][1][tmpi[1]]), _mm_shuffle_pd(vec_input_er, vec_input_er, 0x1));
		vec_input_er = _mm_add_pd(vec_input_er, vec_sprd); // spread
		// rv save
		vec_tmp_rv = _mm_set_pd(*info->rv_in[i][1], *info->rv_in[i][0]);
		// rv out
		vec_tmp1 = _mm_set_pd(info->buf[i][3][tmpi[3]], info->buf[i][2][tmpi[2]]);
		lpf = &rv_fc[i];
		vec_db = _mm_loadu_pd(lpf->db);
		vec_db = MM_FMA2_PD(MM_LOAD1_PD(&lpf->dc[0]), vec_tmp1, MM_LOAD1_PD(&lpf->dc[1]), vec_db);
		_mm_storeu_pd(lpf->db, vec_db);
		vec_tmp1 = MM_FMA2_PD(vec_tmp1, vec_dry, vec_db, vec_wet);
		vec_mixrv = _mm_add_pd(vec_mixrv, vec_tmp1);
		_mm_storeu_pd(info->rv_out[i], vec_tmp1);
		// rv in
		vec_tmp1 = _mm_add_pd(vec_input_rv, _mm_mul_pd(vec_tmp_rv, MM_LOAD1_PD(&info->rv_feedback[i])));
		_mm_store_sd(&(info->buf[i][2][tmpi[2]]), vec_tmp1);
		_mm_store_sd(&(info->buf[i][3][tmpi[3]]), _mm_shuffle_pd(vec_tmp1, vec_tmp1, 0x1));
		}
		// er flt
		vec_dbL = MM_FMA2_PD(vec_dcL0, vec_mixer, vec_dcL1, vec_dbL);
		vec_mixer = MM_FMA2_PD(vec_mixer, vec_dry, vec_dbL, vec_wet);	
		// rv delay in
		_mm_store_pd(&bufrd[tmpi0], vec_mixer);	
		// out
		vec_hist = _mm_sub_pd(_mm_mul_pd(vec_mixrv, vec_levelrv), _mm_mul_pd(vec_mixer, vec_leveler));
		vec_dbH0 = vec_hist;
		vec_hist = vec_dbH2 = MM_FMA5_PD(vec_dcH0, vec_dbH0, vec_dcH1, vec_dbH1, vec_dcH2, vec_dbH2, vec_dcH3, vec_dbH3, vec_dcH4, vec_dbH4);
		vec_dbH4 = vec_dbH3; vec_dbH3 = vec_dbH2; vec_dbH2 = vec_dbH1; vec_dbH1 = vec_dbH0;
		_mm_store_pd(&buf[k], vec_hist);
	}
	_mm_storeu_pd(info->hist, vec_hist); _mm_storeu_pd(er_fc->db, vec_dbL);
	_mm_storeu_pd(&hpf->db[0], vec_dbH0); _mm_storeu_pd(&hpf->db[2], vec_dbH1); _mm_storeu_pd(&hpf->db[4], vec_dbH2);
	_mm_storeu_pd(&hpf->db[6], vec_dbH3); _mm_storeu_pd(&hpf->db[8], vec_dbH4);
	_mm_storeu_si128((__m128i *)info->index2, index2);
}

static void do_reverb_ex_chMS(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0;
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	DATA_T *bufrd = info->buf2[REV_EX_RD];
	__m128d	vec_dcH0 = MM_LOAD1_PD(&hpf->dc[0]), vec_dcH1 = MM_LOAD1_PD(&hpf->dc[1]), vec_dcH2 = MM_LOAD1_PD(&hpf->dc[2]), 
		vec_dcH3 = MM_LOAD1_PD(&hpf->dc[3]), vec_dcH4 = MM_LOAD1_PD(&hpf->dc[4]),
		vec_dcL0 = MM_LOAD1_PD(&er_fc->dc[0]), vec_dcL1 = MM_LOAD1_PD(&er_fc->dc[1]);
	__m128d	vec_dbH0 = _mm_loadu_pd(&hpf->db[0]), vec_dbH1 = _mm_loadu_pd(&hpf->db[2]), vec_dbH2 = _mm_loadu_pd(&hpf->db[4]), 
		vec_dbH3 = _mm_loadu_pd(&hpf->db[6]), vec_dbH4 = _mm_loadu_pd(&hpf->db[8]), vec_dbL = _mm_loadu_pd(er_fc->db);
	__m128d vec_tmp1, vec_input_er, vec_input_rv, vec_mixer, vec_mixap, vec_mixrv, vec_tmp_rv, vec_db, 
		vec_leveler = MM_LOAD1_PD(&info->leveler), vec_levelrv = MM_LOAD1_PD(&info->levelrv),
		vec_dry = MM_LOAD1_PD(&info->flt_dry), vec_wet = MM_LOAD1_PD(&info->flt_wet),
		vec_feedback = MM_LOAD1_PD(&info->feedback), vec_hist = _mm_loadu_pd(info->hist),
		vec_mix_level = _mm_set1_pd(DIV_MIX_LEVEL);
	__m128i index2 = _mm_loadu_si128((__m128i *)info->index2), size2 = _mm_loadu_si128((__m128i *)info->size2);
	__m128i add_idx2 = _mm_set_epi32(1, 1, 2, 1);
	// CH_MIX_STEREO:
	for (k = 0; k < count; k += 2)
	{		
		int32 tmpi0;
		vec_input_er = _mm_add_pd(_mm_set1_pd((buf[k] + buf[k + 1]) * DIV_MIX_LEVEL), _mm_mul_pd(vec_hist, vec_feedback));
		// index2 (rv delay, ap
		index2 = _mm_add_epi32(index2, add_idx2);
		index2 = _mm_and_si128(index2, _mm_cmplt_epi32(index2, size2));
		tmpi0 = MM_EXTRACT_EPI32(index2, REV_EX_RD);
		// rv delay out
		vec_input_rv = _mm_load_pd(&bufrd[tmpi0]); // REV_EX_RD
		// unit
		vec_mixer = _mm_setzero_pd(); vec_mixrv = _mm_setzero_pd();
		for (i = 0; i < info->unit_num; i++) {
		ALIGN int32 tmpi[4];
		// index inc
		__m128i vec_index = _mm_loadu_si128((__m128i *)&info->index[i][0]); 
		__m128i vec_size = _mm_loadu_si128((__m128i *)&info->size[i][0]);
		vec_index = _mm_add_epi32(vec_index, _mm_set_epi32(1, 1, 1, 1));
		vec_index = _mm_and_si128(vec_index, _mm_cmplt_epi32(vec_index, vec_size));
		_mm_storeu_si128((__m128i *)&info->index[i][0], vec_index);
		// er
		_mm_store_si128((__m128i *)&tmpi, vec_index);
		vec_mixer = _mm_add_pd(vec_mixer, _mm_set_pd(info->buf[i][1][tmpi[1]], info->buf[i][0][tmpi[0]]));
		_mm_store_sd(&(info->buf[i][0][tmpi[0]]), vec_input_er); 
		_mm_store_sd(&(info->buf[i][1][tmpi[1]]), _mm_shuffle_pd(vec_input_er, vec_input_er, 0x1));
		// rv save
		vec_tmp_rv = _mm_set_pd(*info->rv_in[i][1], *info->rv_in[i][0]);
		// rv out
		vec_tmp1 = _mm_set_pd(info->buf[i][3][tmpi[3]], info->buf[i][2][tmpi[2]]);
		lpf = &rv_fc[i];
		vec_db = _mm_loadu_pd(lpf->db);
		vec_db = MM_FMA2_PD(MM_LOAD1_PD(&lpf->dc[0]), vec_tmp1, MM_LOAD1_PD(&lpf->dc[1]), vec_db);
		_mm_storeu_pd(lpf->db, vec_db);
		vec_tmp1 = MM_FMA2_PD(vec_tmp1, vec_dry, vec_db, vec_wet);
		vec_mixrv = _mm_add_pd(vec_mixrv, vec_tmp1);
		_mm_storeu_pd(info->rv_out[i], vec_tmp1);
		// rv in
		vec_tmp1 = _mm_add_pd(vec_input_rv, _mm_mul_pd(vec_tmp_rv, MM_LOAD1_PD(&info->rv_feedback[i])));
		_mm_store_sd(&(info->buf[i][2][tmpi[2]]), vec_tmp1);
		_mm_store_sd(&(info->buf[i][3][tmpi[3]]), _mm_shuffle_pd(vec_tmp1, vec_tmp1, 0x1));
		}
		// er flt
		vec_dbL = MM_FMA2_PD(vec_dcL0, vec_mixer, vec_dcL1, vec_dbL);
		vec_mixer = MM_FMA2_PD(vec_mixer, vec_dry, vec_dbL, vec_wet);	
		// rv delay in
		_mm_store_pd(&bufrd[tmpi0], vec_mixer);	
		// out
		vec_hist = _mm_sub_pd(_mm_mul_pd(vec_mixrv, vec_levelrv), _mm_mul_pd(vec_mixer, vec_leveler));
		vec_dbH0 = vec_hist;
		vec_hist = vec_dbH2 = MM_FMA5_PD(vec_dcH0, vec_dbH0, vec_dcH1, vec_dbH1, vec_dcH2, vec_dbH2, vec_dcH3, vec_dbH3, vec_dcH4, vec_dbH4);
		vec_dbH4 = vec_dbH3; vec_dbH3 = vec_dbH2; vec_dbH2 = vec_dbH1; vec_dbH1 = vec_dbH0;
		_mm_store_pd(&buf[k], vec_hist);
	}
	_mm_storeu_pd(info->hist, vec_hist); _mm_storeu_pd(er_fc->db, vec_dbL);
	_mm_storeu_pd(&hpf->db[0], vec_dbH0); _mm_storeu_pd(&hpf->db[2], vec_dbH1); _mm_storeu_pd(&hpf->db[4], vec_dbH2);
	_mm_storeu_pd(&hpf->db[6], vec_dbH3); _mm_storeu_pd(&hpf->db[8], vec_dbH4);
	_mm_storeu_si128((__m128i *)info->index2, index2);
}

static void do_reverb_ex_chST_ap8(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0;
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	DATA_T *bufrd = info->buf2[REV_EX_RD];
	__m128d	vec_dcH0 = MM_LOAD1_PD(&hpf->dc[0]), vec_dcH1 = MM_LOAD1_PD(&hpf->dc[1]), vec_dcH2 = MM_LOAD1_PD(&hpf->dc[2]), 
		vec_dcH3 = MM_LOAD1_PD(&hpf->dc[3]), vec_dcH4 = MM_LOAD1_PD(&hpf->dc[4]),
		vec_dcL0 = MM_LOAD1_PD(&er_fc->dc[0]), vec_dcL1 = MM_LOAD1_PD(&er_fc->dc[1]);
	__m128d	vec_dbH0 = _mm_loadu_pd(&hpf->db[0]), vec_dbH1 = _mm_loadu_pd(&hpf->db[2]), vec_dbH2 = _mm_loadu_pd(&hpf->db[4]), 
		vec_dbH3 = _mm_loadu_pd(&hpf->db[6]), vec_dbH4 = _mm_loadu_pd(&hpf->db[8]), vec_dbL = _mm_loadu_pd(er_fc->db);
	__m128d vec_tmp1, vec_input_er, vec_input_rv, vec_mixer, vec_mixap, vec_mixrv, vec_tmp_rv, vec_db, vec_sprd,
		vec_leveler = MM_LOAD1_PD(&info->leveler), vec_levelrv = MM_LOAD1_PD(&info->levelrv),
		vec_dry = MM_LOAD1_PD(&info->flt_dry), vec_wet = MM_LOAD1_PD(&info->flt_wet),
		vec_feedback = MM_LOAD1_PD(&info->feedback), vec_hist = _mm_loadu_pd(info->hist);
	__m128d vec_sp_sprd = _mm_set_pd(-info->st_sprd, info->st_sprd);
	__m128i index2 = _mm_loadu_si128((__m128i *)info->index2), size2 = _mm_loadu_si128((__m128i *)info->size2);
	__m128i add_idx2 = _mm_set_epi32(1, 1, 2, 1);
	__m128i sizeap = _mm_set1_epi32(info->size2[REV_EX_AP1]);
	__m128d vec_ap_fb = _mm_set1_pd(REV_EX_AP_FB), vec_levelap = MM_LOAD1_PD(&info->levelap), 
		vec_fbap1 = _mm_loadu_pd(info->fb_ap1), vec_fbap2 = _mm_loadu_pd(info->fb_ap2);
	__m128i vec_index2;
	__m128d vtmp[2];
	// CH_STEREO:
	for (k = 0; k < count; k += 2)
	{		
		ALIGN int32 tmpi2[4];
		vec_sprd = _mm_mul_pd(_mm_set1_pd(buf[k] - buf[k + 1]), vec_sp_sprd);
		vec_input_er = _mm_add_pd(_mm_set1_pd((buf[k] + buf[k + 1]) * DIV_MIX_LEVEL), _mm_mul_pd(vec_hist, vec_feedback));
		// index2 (rv delay, ap
		index2 = _mm_add_epi32(index2, add_idx2);
		index2 = _mm_and_si128(index2, _mm_cmplt_epi32(index2, size2));
		_mm_store_si128((__m128i *)&tmpi2, index2);
		// rv delay out
		vec_input_rv = _mm_load_pd(&bufrd[tmpi2[REV_EX_RD]]);
		// unit
		vec_mixer = _mm_setzero_pd(); vec_mixrv = _mm_setzero_pd();
		for (i = 0; i < info->unit_num; i++) {
		ALIGN int32 tmpi[4];
		// index inc
		__m128i vec_index = _mm_loadu_si128((__m128i *)&info->index[i][0]); 
		__m128i vec_size = _mm_loadu_si128((__m128i *)&info->size[i][0]);
		vec_index = _mm_add_epi32(vec_index, _mm_set_epi32(1, 1, 1, 1));
		vec_index = _mm_and_si128(vec_index, _mm_cmplt_epi32(vec_index, vec_size));
		_mm_storeu_si128((__m128i *)&info->index[i][0], vec_index);
		// er
		_mm_store_si128((__m128i *)&tmpi, vec_index);
		vec_mixer = _mm_add_pd(vec_mixer, _mm_set_pd(info->buf[i][1][tmpi[1]], info->buf[i][0][tmpi[0]]));
		_mm_store_sd(&(info->buf[i][0][tmpi[0]]), vec_input_er); 
		_mm_store_sd(&(info->buf[i][1][tmpi[1]]), _mm_shuffle_pd(vec_input_er, vec_input_er, 0x1));
		vec_input_er = _mm_add_pd(vec_input_er, vec_sprd); // spread
		// rv save
		vec_tmp_rv = _mm_set_pd(*info->rv_in[i][1], *info->rv_in[i][0]);
		// rv out
		vec_tmp1 = _mm_set_pd(info->buf[i][3][tmpi[3]], info->buf[i][2][tmpi[2]]);
		lpf = &rv_fc[i];
		vec_db = _mm_loadu_pd(lpf->db);
		vec_db = MM_FMA2_PD(MM_LOAD1_PD(&lpf->dc[0]), vec_tmp1, MM_LOAD1_PD(&lpf->dc[1]), vec_db);
		_mm_storeu_pd(lpf->db, vec_db);
		vec_tmp1 = MM_FMA2_PD(vec_tmp1, vec_dry, vec_db, vec_wet);
		vec_mixrv = _mm_add_pd(vec_mixrv, vec_tmp1);
		_mm_storeu_pd(info->rv_out[i], vec_tmp1);
		// rv in
		vec_tmp1 = _mm_add_pd(vec_input_rv, _mm_mul_pd(vec_tmp_rv, MM_LOAD1_PD(&info->rv_feedback[i])));
		_mm_store_sd(&(info->buf[i][2][tmpi[2]]), vec_tmp1);
		_mm_store_sd(&(info->buf[i][3][tmpi[3]]), _mm_shuffle_pd(vec_tmp1, vec_tmp1, 0x1));
		}
		// er flt
		vec_dbL = MM_FMA2_PD(vec_dcL0, vec_mixer, vec_dcL1, vec_dbL);
		vec_mixer = MM_FMA2_PD(vec_mixer, vec_dry, vec_dbL, vec_wet);	
		// rv delay in
		_mm_store_pd(&bufrd[tmpi2[REV_EX_RD]], vec_mixer);
		// ap
		vec_index2 = _mm_shuffle_epi32(index2, 0xAA);
		vtmp[0] = MM_FMA2_PD(vec_mixer, vec_levelap, vec_fbap1, vec_ap_fb);
		vtmp[1] = MM_FMA2_PD(vec_mixrv, vec_levelap, vec_fbap2, vec_ap_fb);
		_mm_store_sd(&info->abuf[REV_EX_ER_L1][tmpi2[REV_EX_AP1]], vtmp[0]); 
		_mm_store_sd(&info->abuf[REV_EX_ER_R1][tmpi2[REV_EX_AP1]], _mm_shuffle_pd(vtmp[0], vtmp[0], 0x3)); 
		_mm_store_sd(&info->abuf[REV_EX_RV_L1][tmpi2[REV_EX_AP1]], vtmp[1]); 
		_mm_store_sd(&info->abuf[REV_EX_RV_R1][tmpi2[REV_EX_AP1]], _mm_shuffle_pd(vtmp[1], vtmp[0], 0x3)); 
		for (i = 0; i < REV_EX_AP_MAX; i++) {
		ALIGN int32 tmpi[4];
		__m128i vec_index;
		vec_index = _mm_sub_epi32(vec_index2, _mm_loadu_si128((__m128i *)info->delaya[i]));
		vec_index = _mm_add_epi32(vec_index, _mm_and_si128(sizeap, _mm_cmplt_epi32(vec_index, _mm_setzero_si128())));
		_mm_store_si128((__m128i *)&tmpi, vec_index);
		// ap1
		vec_mixer = _mm_add_pd(vec_mixer, _mm_set_pd(info->abuf[1][tmpi[1]], info->abuf[0][tmpi[0]]));
		// ap2
		vec_mixrv = _mm_add_pd(vec_mixrv, _mm_set_pd(info->abuf[3][tmpi[3]], info->abuf[2][tmpi[2]]));
		}
		vec_fbap1 = vec_mixer; vec_fbap2 = vec_mixrv;
		// out
		vec_hist = _mm_sub_pd(_mm_mul_pd(vec_mixrv, vec_levelrv), _mm_mul_pd(vec_mixer, vec_leveler));
		vec_dbH0 = vec_hist;
		vec_hist = vec_dbH2 = MM_FMA5_PD(vec_dcH0, vec_dbH0, vec_dcH1, vec_dbH1, vec_dcH2, vec_dbH2, vec_dcH3, vec_dbH3, vec_dcH4, vec_dbH4);
		vec_dbH4 = vec_dbH3; vec_dbH3 = vec_dbH2; vec_dbH2 = vec_dbH1; vec_dbH1 = vec_dbH0;
		_mm_store_pd(&buf[k], vec_hist);
	}
	_mm_storeu_pd(info->hist, vec_hist); _mm_storeu_pd(er_fc->db, vec_dbL);
	_mm_storeu_pd(&hpf->db[0], vec_dbH0); _mm_storeu_pd(&hpf->db[2], vec_dbH1); _mm_storeu_pd(&hpf->db[4], vec_dbH2);
	_mm_storeu_pd(&hpf->db[6], vec_dbH3); _mm_storeu_pd(&hpf->db[8], vec_dbH4);
	_mm_storeu_si128((__m128i *)info->index2, index2);
	_mm_storeu_pd(info->fb_ap1, vec_fbap1); _mm_storeu_pd(info->fb_ap2, vec_fbap2);
}

static void do_reverb_ex_chMS_ap8(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0;
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	DATA_T *bufrd = info->buf2[REV_EX_RD];
	__m128d	vec_dcH0 = MM_LOAD1_PD(&hpf->dc[0]), vec_dcH1 = MM_LOAD1_PD(&hpf->dc[1]), vec_dcH2 = MM_LOAD1_PD(&hpf->dc[2]), 
		vec_dcH3 = MM_LOAD1_PD(&hpf->dc[3]), vec_dcH4 = MM_LOAD1_PD(&hpf->dc[4]),
		vec_dcL0 = MM_LOAD1_PD(&er_fc->dc[0]), vec_dcL1 = MM_LOAD1_PD(&er_fc->dc[1]);
	__m128d	vec_dbH0 = _mm_loadu_pd(&hpf->db[0]), vec_dbH1 = _mm_loadu_pd(&hpf->db[2]), vec_dbH2 = _mm_loadu_pd(&hpf->db[4]), 
		vec_dbH3 = _mm_loadu_pd(&hpf->db[6]), vec_dbH4 = _mm_loadu_pd(&hpf->db[8]), vec_dbL = _mm_loadu_pd(er_fc->db);
	__m128d vec_tmp1, vec_input_er, vec_input_rv, vec_mixer, vec_mixap, vec_mixrv, vec_tmp_rv, vec_db, 
		vec_leveler = MM_LOAD1_PD(&info->leveler), vec_levelrv = MM_LOAD1_PD(&info->levelrv),
		vec_dry = MM_LOAD1_PD(&info->flt_dry), vec_wet = MM_LOAD1_PD(&info->flt_wet),
		vec_feedback = MM_LOAD1_PD(&info->feedback), vec_hist = _mm_loadu_pd(info->hist),
		vec_mix_level = _mm_set1_pd(DIV_MIX_LEVEL);
	__m128i index2 = _mm_loadu_si128((__m128i *)info->index2), size2 = _mm_loadu_si128((__m128i *)info->size2);
	__m128i add_idx2 = _mm_set_epi32(1, 1, 2, 1);
	__m128i sizeap = _mm_set1_epi32(info->size2[REV_EX_AP1]);
	__m128d vec_ap_fb = _mm_set1_pd(REV_EX_AP_FB), vec_levelap = MM_LOAD1_PD(&info->levelap), 
		vec_fbap1 = _mm_loadu_pd(info->fb_ap1), vec_fbap2 = _mm_loadu_pd(info->fb_ap2);
	__m128i vec_index2;
	__m128d vtmp[2];
	// CH_MIX_STEREO:
	for (k = 0; k < count; k += 2)
	{		
		ALIGN int32 tmpi2[4];
		vec_input_er = _mm_add_pd(_mm_set1_pd((buf[k] + buf[k + 1]) * DIV_MIX_LEVEL), _mm_mul_pd(vec_hist, vec_feedback));
		// index2 (rv delay, ap
		index2 = _mm_add_epi32(index2, add_idx2);
		index2 = _mm_and_si128(index2, _mm_cmplt_epi32(index2, size2));
		_mm_store_si128((__m128i *)&tmpi2, index2);
		// rv delay out
		vec_input_rv = _mm_load_pd(&bufrd[tmpi2[REV_EX_RD]]);
		// unit
		vec_mixer = _mm_setzero_pd(); vec_mixrv = _mm_setzero_pd();
		for (i = 0; i < info->unit_num; i++) {
		ALIGN int32 tmpi[4];
		// index inc
		__m128i vec_index = _mm_loadu_si128((__m128i *)&info->index[i][0]); 
		__m128i vec_size = _mm_loadu_si128((__m128i *)&info->size[i][0]);
		vec_index = _mm_add_epi32(vec_index, _mm_set_epi32(1, 1, 1, 1));
		vec_index = _mm_and_si128(vec_index, _mm_cmplt_epi32(vec_index, vec_size));
		_mm_storeu_si128((__m128i *)&info->index[i][0], vec_index);
		// er
		_mm_store_si128((__m128i *)&tmpi, vec_index);
		vec_mixer = _mm_add_pd(vec_mixer, _mm_set_pd(info->buf[i][1][tmpi[1]], info->buf[i][0][tmpi[0]]));
		_mm_store_sd(&(info->buf[i][0][tmpi[0]]), vec_input_er); 
		_mm_store_sd(&(info->buf[i][1][tmpi[1]]), _mm_shuffle_pd(vec_input_er, vec_input_er, 0x1));
		// rv save
		vec_tmp_rv = _mm_set_pd(*info->rv_in[i][1], *info->rv_in[i][0]);
		// rv out
		vec_tmp1 = _mm_set_pd(info->buf[i][3][tmpi[3]], info->buf[i][2][tmpi[2]]);
		lpf = &rv_fc[i];
		vec_db = _mm_loadu_pd(lpf->db);
		vec_db = MM_FMA2_PD(MM_LOAD1_PD(&lpf->dc[0]), vec_tmp1, MM_LOAD1_PD(&lpf->dc[1]), vec_db);
		_mm_storeu_pd(lpf->db, vec_db);
		vec_tmp1 = MM_FMA2_PD(vec_tmp1, vec_dry, vec_db, vec_wet);
		vec_mixrv = _mm_add_pd(vec_mixrv, vec_tmp1);
		_mm_storeu_pd(info->rv_out[i], vec_tmp1);
		// rv in
		vec_tmp1 = _mm_add_pd(vec_input_rv, _mm_mul_pd(vec_tmp_rv, MM_LOAD1_PD(&info->rv_feedback[i])));
		_mm_store_sd(&(info->buf[i][2][tmpi[2]]), vec_tmp1);
		_mm_store_sd(&(info->buf[i][3][tmpi[3]]), _mm_shuffle_pd(vec_tmp1, vec_tmp1, 0x1));
		}
		// er flt
		vec_dbL = MM_FMA2_PD(vec_dcL0, vec_mixer, vec_dcL1, vec_dbL);
		vec_mixer = MM_FMA2_PD(vec_mixer, vec_dry, vec_dbL, vec_wet);	
		// rv delay in
		_mm_store_pd(&bufrd[tmpi2[REV_EX_RD]], vec_mixer);	
		// ap
		vec_index2 = _mm_shuffle_epi32(index2, 0xAA);
		vtmp[0] = MM_FMA2_PD(vec_mixer, vec_levelap, vec_fbap1, vec_ap_fb);
		vtmp[1] = MM_FMA2_PD(vec_mixrv, vec_levelap, vec_fbap2, vec_ap_fb);
		_mm_store_sd(&info->abuf[REV_EX_ER_L1][tmpi2[REV_EX_AP1]], vtmp[0]); 
		_mm_store_sd(&info->abuf[REV_EX_ER_R1][tmpi2[REV_EX_AP1]], _mm_shuffle_pd(vtmp[0], vtmp[0], 0x3)); 
		_mm_store_sd(&info->abuf[REV_EX_RV_L1][tmpi2[REV_EX_AP1]], vtmp[1]); 
		_mm_store_sd(&info->abuf[REV_EX_RV_R1][tmpi2[REV_EX_AP1]], _mm_shuffle_pd(vtmp[1], vtmp[0], 0x3)); 
		for (i = 0; i < REV_EX_AP_MAX; i++) {
		ALIGN int32 tmpi[4];
		__m128i vec_index;
		vec_index = _mm_sub_epi32(vec_index2, _mm_loadu_si128((__m128i *)info->delaya[i]));
		vec_index = _mm_add_epi32(vec_index, _mm_and_si128(sizeap, _mm_cmplt_epi32(vec_index, _mm_setzero_si128())));
		_mm_store_si128((__m128i *)&tmpi, vec_index);
		// ap1
		vec_mixer = _mm_add_pd(vec_mixer, _mm_set_pd(info->abuf[1][tmpi[1]], info->abuf[0][tmpi[0]]));
		// ap2
		vec_mixrv = _mm_add_pd(vec_mixrv, _mm_set_pd(info->abuf[3][tmpi[3]], info->abuf[2][tmpi[2]]));
		}
		vec_fbap1 = vec_mixer; vec_fbap2 = vec_mixrv;	
		// out
		vec_hist = _mm_sub_pd(_mm_mul_pd(vec_mixrv, vec_levelrv), _mm_mul_pd(vec_mixer, vec_leveler));
		vec_dbH0 = vec_hist;
		vec_hist = vec_dbH2 = MM_FMA5_PD(vec_dcH0, vec_dbH0, vec_dcH1, vec_dbH1, vec_dcH2, vec_dbH2, vec_dcH3, vec_dbH3, vec_dcH4, vec_dbH4);
		vec_dbH4 = vec_dbH3; vec_dbH3 = vec_dbH2; vec_dbH2 = vec_dbH1; vec_dbH1 = vec_dbH0;
		_mm_store_pd(&buf[k], vec_hist);
	}
	_mm_storeu_pd(info->hist, vec_hist); _mm_storeu_pd(er_fc->db, vec_dbL);
	_mm_storeu_pd(&hpf->db[0], vec_dbH0); _mm_storeu_pd(&hpf->db[2], vec_dbH1); _mm_storeu_pd(&hpf->db[4], vec_dbH2);
	_mm_storeu_pd(&hpf->db[6], vec_dbH3); _mm_storeu_pd(&hpf->db[8], vec_dbH4);
	_mm_storeu_si128((__m128i *)info->index2, index2);
	_mm_storeu_pd(info->fb_ap1, vec_fbap1); _mm_storeu_pd(info->fb_ap2, vec_fbap2);
}

#else /* floating-point implementation */
static void do_reverb_ex_chST(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	FLOAT_T leveler = info->leveler, levelrv = info->levelrv, feedback = info->feedback,
		*rv_feedback = info->rv_feedback, flt_dry = info->flt_dry, flt_wet = info->flt_wet,
		*dcH = hpf->dc, *dcL = er_fc->dc, st_sprd = info->st_sprd;	
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T 	hist[2] = {info->hist[0], info->hist[1],}, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2], sprd;
	// CH_STEREO:
	RDTSC_TEST1
	for (k = 0; k < count; k++)
	{		
#if !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT)
		input[0] = buf[k] * info->in_level; input[1] = buf[k + 1] * info->in_level;
#else
		input[0] = buf[k]; input[1] = buf[k + 1];
#endif
		sprd = (input[0] - input[1]) * st_sprd;
		input[0] = input[1] = (input[0] + input[1]) * DIV_MIX_LEVEL;
		input[0] += hist[0] * feedback; input[1] += hist[1] * feedback;
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		//unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		for (i = 0; i < info->unit_num; i++) {
			// index inc
			int32 *index[4] = {&info->index[i][0], &info->index[i][1], &info->index[i][2], &info->index[i][3],};
			if (++(*index[0]) >= info->size[i][0]) {*index[0] = 0;}
			if (++(*index[1]) >= info->size[i][1]) {*index[1] = 0;}
			if (++(*index[2]) >= info->size[i][2]) {*index[2] = 0;}
			if (++(*index[3]) >= info->size[i][3]) {*index[3] = 0;}
			// er out
			dat_er[0] += info->buf[i][0][*index[0]]; dat_er[1] += info->buf[i][1][*index[1]];
			// er in
			info->buf[i][0][*index[0]] = input[0]; info->buf[i][1][*index[1]] = input[1];
			input[0] += sprd; input[1] -= sprd; // spread
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = info->buf[i][2][*index[2]];
			tmp1[1] = info->buf[i][3][*index[3]];
		//	sample_filter_stereo(&rv_fc1[i], &flt[0], &flt[1]);	
			lpf = &rv_fc[i];
			lpf->db[0] = lpf->dc[0] * tmp1[0] + lpf->dc[1] * lpf->db[0];
			lpf->db[1] = lpf->dc[0] * tmp1[1] + lpf->dc[1] * lpf->db[1];
			dat_rv[0] += (info->rv_out[i][0] = tmp1[0] * flt_dry + lpf->db[0] * flt_wet);
			dat_rv[1] += (info->rv_out[i][1] = tmp1[1] * flt_dry + lpf->db[1] * flt_wet);
			// rv in
			info->buf[i][2][*index[2]] = input_rv[0] + tmp_rv[0] * rv_feedback[i];
			info->buf[i][3][*index[3]] = input_rv[1] + tmp_rv[1] * rv_feedback[i];
		}
	//	sample_filter_stereo(er_fc, &dat_er[0], &dat_er[1]);
		dbL[0] = dcL[0] * dat_er[0] + dcL[1] * dbL[0];
		dbL[1] = dcL[0] * dat_er[1] + dcL[1] * dbL[1];
		dat_er[0] = dat_er[0] * flt_dry + dbL[0] * flt_wet;
		dat_er[1] = dat_er[1] * flt_dry + dbL[1] * flt_wet;	
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// out
		hist[0] = dat_rv[0] * levelrv - dat_er[0] * leveler;
		hist[1] = dat_rv[1] * levelrv - dat_er[1] * leveler;
	//	sample_filter_stereo(hpf, &hist[0], &hist[1]);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = dcH[0] * dbHL[0] + dcH[1] * dbHL[1] + dcH[2] * dbHL[2] + dcH[3] * dbHL[3] + dcH[4] * dbHL[4];
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = dcH[0] * dbHR[0] + dcH[1] * dbHR[1] + dcH[2] * dbHR[2] + dcH[3] * dbHR[3] + dcH[4] * dbHR[4];
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
	info->hist[0] = hist[0], info->hist[1] = hist[1];
	RDTSC_TEST2
}

static void do_reverb_ex_chMS(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	FLOAT_T leveler = info->leveler, levelrv = info->levelrv, feedback = info->feedback,
		*rv_feedback = info->rv_feedback, flt_dry = info->flt_dry, flt_wet = info->flt_wet,
		*dcH = hpf->dc, *dcL = er_fc->dc;	
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T	hist[2] = {info->hist[0], info->hist[1],}, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2];
	// CH_MIX_STEREO:
	for (k = 0; k < count; k++)
	{		
#if !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT)
		input[0] = input[1] = (buf[k] + buf[k + 1]) * DIV_MIX_LEVEL * info->in_level;
#else
		input[0] = input[1] = (buf[k] + buf[k + 1]) * DIV_MIX_LEVEL;
#endif
		input[0] += hist[0] * feedback; input[1] += hist[1] * feedback;
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		//unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		for (i = 0; i < info->unit_num; i++) {
			// index inc
			int32 *index[4] = {&info->index[i][0], &info->index[i][1], &info->index[i][2], &info->index[i][3],};
			if (++(*index[0]) >= info->size[i][0]) {*index[0] = 0;}
			if (++(*index[1]) >= info->size[i][1]) {*index[1] = 0;}
			if (++(*index[2]) >= info->size[i][2]) {*index[2] = 0;}
			if (++(*index[3]) >= info->size[i][3]) {*index[3] = 0;}
			// er out
			dat_er[0] += info->buf[i][0][*index[0]]; dat_er[1] += info->buf[i][1][*index[1]];
			// er in
			info->buf[i][0][*index[0]] = input[0]; info->buf[i][1][*index[1]] = input[1];
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = info->buf[i][2][*index[2]];
			tmp1[1] = info->buf[i][3][*index[3]];
		//	sample_filter_stereo(&rv_fc1[i], &flt[0], &flt[1]);	
			lpf = &rv_fc[i];
			lpf->db[0] = lpf->dc[0] * tmp1[0] + lpf->dc[1] * lpf->db[0];
			lpf->db[1] = lpf->dc[0] * tmp1[1] + lpf->dc[1] * lpf->db[1];
			dat_rv[0] += (info->rv_out[i][0] = tmp1[0] * flt_dry + lpf->db[0] * flt_wet);
			dat_rv[1] += (info->rv_out[i][1] = tmp1[1] * flt_dry + lpf->db[1] * flt_wet);
			// rv in
			info->buf[i][2][*index[2]] = input_rv[0] + tmp_rv[0] * rv_feedback[i];
			info->buf[i][3][*index[3]] = input_rv[1] + tmp_rv[1] * rv_feedback[i];
		}
	//	sample_filter_stereo(er_fc, &dat_er[0], &dat_er[1]);
		dbL[0] = dcL[0] * dat_er[0] + dcL[1] * dbL[0];
		dbL[1] = dcL[0] * dat_er[1] + dcL[1] * dbL[1];
		dat_er[0] = dat_er[0] * flt_dry + dbL[0] * flt_wet;
		dat_er[1] = dat_er[1] * flt_dry + dbL[1] * flt_wet;		
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// out
		hist[0] = dat_rv[0] * levelrv - dat_er[0] * leveler;
		hist[1] = dat_rv[1] * levelrv - dat_er[1] * leveler;
	//	sample_filter_stereo(hpf, &hist[0], &hist[1]);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = dcH[0] * dbHL[0] + dcH[1] * dbHL[1] + dcH[2] * dbHL[2] + dcH[3] * dbHL[3] + dcH[4] * dbHL[4];
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = dcH[0] * dbHR[0] + dcH[1] * dbHR[1] + dcH[2] * dbHR[2] + dcH[3] * dbHR[3] + dcH[4] * dbHR[4];
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
	info->hist[0] = hist[0], info->hist[1] = hist[1];
}

static void do_reverb_ex_chST_ap8(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	FLOAT_T leveler = info->leveler, levelrv = info->levelrv, feedback = info->feedback,
		*rv_feedback = info->rv_feedback, flt_dry = info->flt_dry, flt_wet = info->flt_wet,
		*dcH = hpf->dc, *dcL = er_fc->dc, st_sprd = info->st_sprd;	
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T	hist[2] = {info->hist[0], info->hist[1],}, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2], sprd;
	int32 *indexap = &info->index2[REV_EX_AP1], sizeap = info->size2[REV_EX_AP1];
	DATA_T *fb_ap1 = info->fb_ap1, *fb_ap2 = info->fb_ap2;
	FLOAT_T levelap = info->levelap;
	// CH_STEREO:
	RDTSC_TEST1
	for (k = 0; k < count; k++)
	{		
#if !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT)
		input[0] = buf[k] * info->in_level; input[1] = buf[k + 1] * info->in_level;
#else
		input[0] = buf[k]; input[1] = buf[k + 1];
#endif
		sprd = (input[0] - input[1]) * st_sprd;
		input[0] = input[1] = (input[0] + input[1]) * DIV_MIX_LEVEL;
		input[0] += hist[0] * feedback; input[1] += hist[1] * feedback;
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		//unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		for (i = 0; i < info->unit_num; i++) {
			// index inc
			int32 *index[4] = {&info->index[i][0], &info->index[i][1], &info->index[i][2], &info->index[i][3],};
			if (++(*index[0]) >= info->size[i][0]) {*index[0] = 0;}
			if (++(*index[1]) >= info->size[i][1]) {*index[1] = 0;}
			if (++(*index[2]) >= info->size[i][2]) {*index[2] = 0;}
			if (++(*index[3]) >= info->size[i][3]) {*index[3] = 0;}
			// er out
			dat_er[0] += info->buf[i][0][*index[0]]; dat_er[1] += info->buf[i][1][*index[1]];
			// er in
			info->buf[i][0][*index[0]] = input[0]; info->buf[i][1][*index[1]] = input[1];
			input[0] += sprd; input[1] -= sprd; // spread
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = info->buf[i][2][*index[2]];
			tmp1[1] = info->buf[i][3][*index[3]];
		//	sample_filter_stereo(&rv_fc1[i], &flt[0], &flt[1]);	
			lpf = &rv_fc[i];
			lpf->db[0] = lpf->dc[0] * tmp1[0] + lpf->dc[1] * lpf->db[0];
			lpf->db[1] = lpf->dc[0] * tmp1[1] + lpf->dc[1] * lpf->db[1];
			dat_rv[0] += (info->rv_out[i][0] = tmp1[0] * flt_dry + lpf->db[0] * flt_wet);
			dat_rv[1] += (info->rv_out[i][1] = tmp1[1] * flt_dry + lpf->db[1] * flt_wet);
			// rv in
			info->buf[i][2][*index[2]] = input_rv[0] + tmp_rv[0] * rv_feedback[i];
			info->buf[i][3][*index[3]] = input_rv[1] + tmp_rv[1] * rv_feedback[i];
		}
	//	sample_filter_stereo(er_fc, &dat_er[0], &dat_er[1]);
		dbL[0] = dcL[0] * dat_er[0] + dcL[1] * dbL[0];
		dbL[1] = dcL[0] * dat_er[1] + dcL[1] * dbL[1];
		dat_er[0] = dat_er[0] * flt_dry + dbL[0] * flt_wet;
		dat_er[1] = dat_er[1] * flt_dry + dbL[1] * flt_wet;	
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// ap
		if ((++(*indexap)) >= sizeap) {*indexap -= sizeap;}
		info->abuf[0][*indexap] = dat_er[0] * levelap + fb_ap1[0] * REV_EX_AP_FB; 
		info->abuf[1][*indexap] = dat_er[1] * levelap + fb_ap1[1] * REV_EX_AP_FB; 
		info->abuf[2][*indexap] = dat_rv[0] * levelap + fb_ap2[0] * REV_EX_AP_FB; 
		info->abuf[3][*indexap] = dat_rv[1] * levelap + fb_ap2[1] * REV_EX_AP_FB; 
		for (i = 0; i < REV_EX_AP_MAX; i++) {
			int32 index;
			// ap1 er
			if((index = *indexap - info->delaya[i][0]) < 0) {index += sizeap;} 
			dat_er[0] += info->abuf[0][index]; 
			if((index = *indexap - info->delaya[i][1]) < 0) {index += sizeap;}
			dat_er[1] += info->abuf[1][index]; 	
			// ap2 rv
			if((index = *indexap - info->delaya[i][2]) < 0) {index += sizeap;}
			dat_rv[0] += info->abuf[2][index]; 
			if((index = *indexap - info->delaya[i][3]) < 0) {index += sizeap;}
			dat_rv[1] += info->abuf[3][index]; 
		}
		fb_ap1[0] = dat_er[0]; fb_ap1[1] = dat_er[1];
		fb_ap2[0] = dat_rv[0]; fb_ap2[1] = dat_rv[1];
		// out
		hist[0] = dat_rv[0] * levelrv - dat_er[0] * leveler;
		hist[1] = dat_rv[1] * levelrv - dat_er[1] * leveler;
	//	sample_filter_stereo(hpf, &hist[0], &hist[1]);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = dcH[0] * dbHL[0] + dcH[1] * dbHL[1] + dcH[2] * dbHL[2] + dcH[3] * dbHL[3] + dcH[4] * dbHL[4];
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = dcH[0] * dbHR[0] + dcH[1] * dbHR[1] + dcH[2] * dbHR[2] + dcH[3] * dbHR[3] + dcH[4] * dbHR[4];
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
	info->hist[0] = hist[0], info->hist[1] = hist[1];
	RDTSC_TEST2
}

static void do_reverb_ex_chMS_ap8(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	FLOAT_T leveler = info->leveler, levelrv = info->levelrv, feedback = info->feedback,
		*rv_feedback = info->rv_feedback, flt_dry = info->flt_dry, flt_wet = info->flt_wet,
		*dcH = hpf->dc, *dcL = er_fc->dc;	
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T	hist[2] = {info->hist[0], info->hist[1],}, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2];
	int32 *indexap = &info->index2[REV_EX_AP1], sizeap = info->size2[REV_EX_AP1];
	DATA_T *fb_ap1 = info->fb_ap1, *fb_ap2 = info->fb_ap2;
	FLOAT_T levelap = info->levelap;
	// CH_MIX_STEREO:
	for (k = 0; k < count; k++)
	{		
#if !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT)
		input[0] = input[1] = (buf[k] + buf[k + 1]) * DIV_MIX_LEVEL * info->in_level;
#else
		input[0] = input[1] = (buf[k] + buf[k + 1]) * DIV_MIX_LEVEL;
#endif
		input[0] += hist[0] * feedback; input[1] += hist[1] * feedback;
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		//unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		for (i = 0; i < info->unit_num; i++) {
			// index inc
			int32 *index[4] = {&info->index[i][0], &info->index[i][1], &info->index[i][2], &info->index[i][3],};
			if (++(*index[0]) >= info->size[i][0]) {*index[0] = 0;}
			if (++(*index[1]) >= info->size[i][1]) {*index[1] = 0;}
			if (++(*index[2]) >= info->size[i][2]) {*index[2] = 0;}
			if (++(*index[3]) >= info->size[i][3]) {*index[3] = 0;}
			// er out
			dat_er[0] += info->buf[i][0][*index[0]]; dat_er[1] += info->buf[i][1][*index[1]];
			// er in
			info->buf[i][0][*index[0]] = input[0]; info->buf[i][1][*index[1]] = input[1];
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = info->buf[i][2][*index[2]];
			tmp1[1] = info->buf[i][3][*index[3]];
		//	sample_filter_stereo(&rv_fc1[i], &flt[0], &flt[1]);	
			lpf = &rv_fc[i];
			lpf->db[0] = lpf->dc[0] * tmp1[0] + lpf->dc[1] * lpf->db[0];
			lpf->db[1] = lpf->dc[0] * tmp1[1] + lpf->dc[1] * lpf->db[1];
			dat_rv[0] += (info->rv_out[i][0] = tmp1[0] * flt_dry + lpf->db[0] * flt_wet);
			dat_rv[1] += (info->rv_out[i][1] = tmp1[1] * flt_dry + lpf->db[1] * flt_wet);
			// rv in
			info->buf[i][2][*index[2]] = input_rv[0] + tmp_rv[0] * rv_feedback[i];
			info->buf[i][3][*index[3]] = input_rv[1] + tmp_rv[1] * rv_feedback[i];
		}
	//	sample_filter_stereo(er_fc, &dat_er[0], &dat_er[1]);
		dbL[0] = dcL[0] * dat_er[0] + dcL[1] * dbL[0];
		dbL[1] = dcL[0] * dat_er[1] + dcL[1] * dbL[1];
		dat_er[0] = dat_er[0] * flt_dry + dbL[0] * flt_wet;
		dat_er[1] = dat_er[1] * flt_dry + dbL[1] * flt_wet;		
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// ap
		if ((++(*indexap)) >= sizeap) {*indexap -= sizeap;}
		info->abuf[0][*indexap] = dat_er[0] * levelap + fb_ap1[0] * REV_EX_AP_FB; 
		info->abuf[1][*indexap] = dat_er[1] * levelap + fb_ap1[1] * REV_EX_AP_FB; 
		info->abuf[2][*indexap] = dat_rv[0] * levelap + fb_ap2[0] * REV_EX_AP_FB; 
		info->abuf[3][*indexap] = dat_rv[1] * levelap + fb_ap2[1] * REV_EX_AP_FB; 
		for (i = 0; i < REV_EX_AP_MAX; i++) {
			int32 index;
			// ap1 er
			if((index = *indexap - info->delaya[i][0]) < 0) {index += sizeap;} 
			dat_er[0] += info->abuf[0][index]; 
			if((index = *indexap - info->delaya[i][1]) < 0) {index += sizeap;}
			dat_er[1] += info->abuf[1][index]; 	
			// ap2 rv
			if((index = *indexap - info->delaya[i][2]) < 0) {index += sizeap;}
			dat_rv[0] += info->abuf[2][index]; 
			if((index = *indexap - info->delaya[i][3]) < 0) {index += sizeap;}
			dat_rv[1] += info->abuf[3][index]; 
		}
		fb_ap1[0] = dat_er[0]; fb_ap1[1] = dat_er[1];
		fb_ap2[0] = dat_rv[0]; fb_ap2[1] = dat_rv[1];
		// out
		hist[0] = dat_rv[0] * levelrv - dat_er[0] * leveler;
		hist[1] = dat_rv[1] * levelrv - dat_er[1] * leveler;
	//	sample_filter_stereo(hpf, &hist[0], &hist[1]);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = dcH[0] * dbHL[0] + dcH[1] * dbHL[1] + dcH[2] * dbHL[2] + dcH[3] * dbHL[3] + dcH[4] * dbHL[4];
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = dcH[0] * dbHR[0] + dcH[1] * dbHR[1] + dcH[2] * dbHR[2] + dcH[3] * dbHR[3] + dcH[4] * dbHR[4];
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
	info->hist[0] = hist[0], info->hist[1] = hist[1];
}
#endif


static void do_reverb_ex_mod_chST(DATA_T *buf, int32 count, InfoReverbEX *info);
static void do_reverb_ex_mod_chMS(DATA_T *buf, int32 count, InfoReverbEX *info);
static void do_reverb_ex_mod_chST_ap8(DATA_T *buf, int32 count, InfoReverbEX *info);
static void do_reverb_ex_mod_chMS_ap8(DATA_T *buf, int32 count, InfoReverbEX *info);

static int rev_ex_mod_init_delay(InfoReverbEX *info, int type, int num, int32 size)
{
	int32 bytes;
	rev_ex_free_delay(info, type, num);
//	if(size < 10) {size = 10;} 
	bytes = sizeof(DATA_T) * (size + 1); //  +1 interpolation
#ifdef ALIGN_SIZE
	info->buf[num][type] = (DATA_T *)aligned_malloc(bytes, ALIGN_SIZE);
#else
	info->buf[num][type] = (DATA_T *)safe_malloc(bytes);
#endif
	if(info->buf[num][type] == NULL) {return 1;} // error
	memset(info->buf[num][type], 0, bytes);
	info->alloc[num][type] = 1;
	return 0;
}

static void init_reverb_ex_mod(InfoReverbEX *info)
{
	int32 i, error = 0;
	FLOAT_T pdelay_cnt, room_cnt, dtS1, dtL1, dtS2, dtL2, lenS1, lenL1, lenS2, lenL2, lenA,
		qrt, ww, fbS, fbL, div_time;
	int num, num_div2;
	FLOAT_T div_num, norm, fbmax = 0;
	FLOAT_T lfo_rate, lfo_depth, delay_max = 0;

	//units	
	ext_reverb_ex_rv_num = clip_int(ext_reverb_ex_rv_num, 8, REV_EX_UNITS); // min 8
	num = ext_reverb_ex_rv_num;
	num_div2 = num / 2;
	div_num = 1.0 / (FLOAT_T)num;
	norm = pow(div_num, DIV_3_2);
	ext_reverb_ex_ap_num = ext_reverb_ex_ap_num ? REV_EX_AP_MAX : 0;
	// init
	init_prime_list();
	pdelay_cnt = info->er_time_ms * playmode_rate_ms;	
	room_cnt = REV_EX_ROOMSIZE_FCT * (FLOAT_T)play_mode->rate;	// leng[m] * div_s[s/m] * rate[cnt/s]
	qrt = pow(info->width * info->height * info->depth, DIV_3);
	lenS1 = info->depth;
	lenL1 = sqrt(sq(info->width) + sq(info->height) + sq(info->depth)) * 2.0;
	lenL2 = qrt * SQRT_2 * 2.0;
	lenS2 = lenL2 * DIV_PI;
	lenA = lenS2 * DIV_PI;
	if((pdelay_cnt -= room_cnt * lenS1) < 0)
		pdelay_cnt = 0;
	dtS1 = pdelay_cnt + room_cnt * lenS1;
	dtL1 = pdelay_cnt + room_cnt * lenL1;
	dtS2 = room_cnt * lenS2;
	dtL2 = room_cnt * lenL2;
	ww = sqrt(sqrt(info->width * info->height) / qrt);
	div_time = 1.0 / (info->rev_time_sec * ext_reverb_ex_time);
	fbL = pow(10.0, -3.0 * lenL2 * REV_EX_ROOMSIZE_FCT * div_time); // rev time to fb level
	fbS = pow(10.0, -3.0 * lenS2 * REV_EX_ROOMSIZE_FCT * div_time); // rev time to fb level
	// er/rv
	lfo_rate = ext_reverb_ex_rv_rate * div_playmode_rate;
	lfo_depth = ext_reverb_ex_rv_depth * playmode_rate_ms;
	for (i = 0; i < num; i++) {
		FLOAT_T rt, dt;
		int32 dtiL1, dtiR1;
		// er	
		rt = div_num * i;
		dt = dtS1 * (1.0 - rt) + dtL1 * rt; // dtS1->dtL1
		info->mdelay[i][REV_EX_ER_L1] = dt * pow(1.05, sqrt(rt) * get_white_noise_p());
		info->mdelay[i][REV_EX_ER_R1] = dt * pow(1.05, sqrt(rt) * get_white_noise_p());
		if(delay_max < info->mdelay[i][REV_EX_ER_L1])
			delay_max = info->mdelay[i][REV_EX_ER_L1];
		if(delay_max < info->mdelay[i][REV_EX_ER_R1])
			delay_max = info->mdelay[i][REV_EX_ER_R1];
		info->mcount[i][REV_EX_ER_L1] = 0;
		info->mcount[i][REV_EX_ER_R1] = 0;
		info->mrate[i][REV_EX_ER_L1] = lfo_rate * pow(1.15, get_white_noise_p());
		info->mrate[i][REV_EX_ER_R1] = lfo_rate * pow(1.15, get_white_noise_p());
		info->mdepth[i][REV_EX_ER_L1] = lfo_depth * pow(1.25, get_white_noise_p());
		info->mdepth[i][REV_EX_ER_R1] = lfo_depth * pow(1.25, get_white_noise_p());
		info->mphase[i][REV_EX_ER_L1] = get_white_noise_p();
		info->mphase[i][REV_EX_ER_R1] = get_white_noise_p();
		// fb
		rt = sqrt(div_num * i);
		info->rv_feedback[i] = fbS * (1.0 - rt) + fbL * rt;
		if(fbmax < info->rv_feedback[i])
			fbmax = info->rv_feedback[i];
		// rv
		rt = i < num_div2 ? sq(div_num * i * 2.0) : sq(1.0 - div_num * i * 2.0);
		dt = dtS2 * (1.0 - rt) + dtL2 * rt; // dtS2->dtL2->dtS2
		dtiL1 = dt * pow(ww, get_white_noise_p());
		dtiR1 = dt * pow(ww, get_white_noise_p());
		find_prime(&dtiL1);	find_prime(&dtiR1);
		info->mdelay[i][REV_EX_RV_L1] = dtiL1;
		info->mdelay[i][REV_EX_RV_R1] = dtiR1;
		if(delay_max < info->mdelay[i][REV_EX_RV_L1])
			delay_max = info->mdelay[i][REV_EX_RV_L1];
		if(delay_max < info->mdelay[i][REV_EX_RV_R1])
			delay_max = info->mdelay[i][REV_EX_RV_R1];
		info->mcount[i][REV_EX_RV_L1] = 0;
		info->mcount[i][REV_EX_RV_R1] = 0;
		info->mrate[i][REV_EX_RV_L1] = lfo_rate * pow(1.15, get_white_noise_p());
		info->mrate[i][REV_EX_RV_R1] = lfo_rate * pow(1.15, get_white_noise_p());
		info->mdepth[i][REV_EX_RV_L1] = lfo_depth * pow(1.25, get_white_noise_p());
		info->mdepth[i][REV_EX_RV_R1] = lfo_depth * pow(1.25, get_white_noise_p());
		info->mphase[i][REV_EX_RV_L1] = get_white_noise_p();
		info->mphase[i][REV_EX_RV_R1] = get_white_noise_p();
		// fbc
		rev_ex_init_rv_fbc(info, i, num);			
		set_sample_filter_type(&info->rv_fc1[i], FILTER_NONE);
		init_sample_filter(&info->rv_fc1[i], info->rev_damp_freq * pow(0.9, get_white_noise_p()) * REV_EX_DAMP, 0, FILTER_LPF6); //info->rev_damp_type);
	}
	info->size2[REV_EX_UNIT] = delay_max + lfo_depth * 1.26 + 1.5; // +0.5 integer
	info->index2[REV_EX_UNIT] = 0;
	// er/rv alloc
	for (i = 0; i < num; i++) {
		// er	
		error += rev_ex_mod_init_delay(info, REV_EX_ER_L1, i, info->size2[REV_EX_UNIT]);
		error += rev_ex_mod_init_delay(info, REV_EX_ER_R1, i, info->size2[REV_EX_UNIT]);
		// rv
		error += rev_ex_mod_init_delay(info, REV_EX_RV_L1, i, info->size2[REV_EX_UNIT]);
		error += rev_ex_mod_init_delay(info, REV_EX_RV_R1, i, info->size2[REV_EX_UNIT]);
	}
	rev_ex_init_rv_delay(info, info->rev_dly_ms * playmode_rate_ms);
	if(ext_reverb_ex_ap_num){
		int32 size = 0, apnum_div2 = ext_reverb_ex_ap_num / 2;
		FLOAT_T div_apnum = 1.0 / (FLOAT_T)ext_reverb_ex_ap_num;
		lfo_rate = ext_reverb_ex_ap_rate * div_playmode_rate;
		lfo_depth = ext_reverb_ex_ap_depth * playmode_rate_ms;
		for (i = 0; i < ext_reverb_ex_ap_num; i++) {
			FLOAT_T rt, dt;
			int32 dti;
			// ap1
			rt = div_apnum * i;
			dt = dtS1 * (1.0 - rt) + dtL1 * rt; // dtS1->dtL1
			dti = (dt - pdelay_cnt) * DIV_SQRT2;
			find_prime(&dti);
			dti = (dti + 1);
			info->adelay[i][REV_EX_ER_L1] = dti;
			info->adelay[i][REV_EX_ER_R1] = dti;
			if(dti > size)
				size = dti;
			info->acount[i][REV_EX_ER_L1] = 0;
			info->acount[i][REV_EX_ER_R1] = 0;
			info->arate[i][REV_EX_ER_L1] = lfo_rate * pow(1.15, get_white_noise_p());
			info->arate[i][REV_EX_ER_R1] = lfo_rate * pow(1.15, get_white_noise_p());
			info->adepth[i][REV_EX_ER_L1] = lfo_depth * pow(1.25, get_white_noise_p());
			info->adepth[i][REV_EX_ER_R1] = lfo_depth * pow(1.25, get_white_noise_p());
			info->aphase[i][REV_EX_ER_L1] = get_white_noise_p();
			info->aphase[i][REV_EX_ER_R1] = get_white_noise_p();
			// ap2
			rt = i < apnum_div2 ? sqrt(div_apnum * i * 2.0) : sqrt(1.0 - div_apnum * i * 2.0);
			dt = dtS2 * (1.0 - rt) + dtL2 * rt; // dtS2->dtL2->dtS2
			dti = dt * DIV_SQRT2;
			find_prime(&dti);
			dti = (dti + 1);	
			info->adelay[i][REV_EX_RV_L1] = dti;
			info->adelay[i][REV_EX_RV_R1] = dti;
			if(dti > size)
				size = dti;
			info->acount[i][REV_EX_RV_L1] = 0;
			info->acount[i][REV_EX_RV_R1] = 0;
			info->arate[i][REV_EX_RV_L1] = lfo_rate * pow(1.15, get_white_noise_p());
			info->arate[i][REV_EX_RV_R1] = lfo_rate * pow(1.15, get_white_noise_p());
			info->adepth[i][REV_EX_RV_L1] = lfo_depth * pow(1.25, get_white_noise_p());
			info->adepth[i][REV_EX_RV_R1] = lfo_depth * pow(1.25, get_white_noise_p());
			info->aphase[i][REV_EX_RV_L1] = get_white_noise_p();
			info->aphase[i][REV_EX_RV_R1] = get_white_noise_p();
		}
		size = (FLOAT_T)size + lfo_depth * 1.26 + 0.5;
		++size;
		if(size < 2) size = 2;
		info->size2[REV_EX_AP1] = size;
		info->size2[REV_EX_AP2] = size;
		info->index2[REV_EX_AP1] = 0;
		info->index2[REV_EX_AP2] = 0;
		error += rev_ex_init_ap_delay(info, size);
	}
	set_sample_filter_type(&info->er_fc, FILTER_NONE);
	init_sample_filter(&info->er_fc, info->er_damp_freq * REV_EX_DAMP, 0, FILTER_LPF6); //info->rev_damp_type);
	set_sample_filter_type(&info->hpf, FILTER_NONE);
	init_sample_filter(&info->hpf, REV_EX_HPF_FREQ, 0, FILTER_HPF_BW);	
	info->unit_num = num;
	info->st_sprd = div_num; // L+,R-
	info->flt_wet = (info->rev_damp_bal + 1.0) * DIV_2;
	info->flt_dry = 1.0 - info->flt_wet;
	info->feedback = info->rev_feedback * REV_EX_FEEDBACK;
	info->leveler = norm * REV_EX_ER_LEVEL
		* info->er_level * ext_reverb_ex_er_level * ext_reverb_ex_level;	
	if(fbmax < 0.01)
		fbmax = 0.01;
	else if(fbmax > 0.99)
		fbmax = 0.99;
	fbmax = sqrt(3.0 / pow(1.0 / (1.0 - fbmax), DIV_3_2));
	info->levelrv = sq(norm) / (sqrt(1.0 + (fbL + fbS) * DIV_2)) * REV_EX_RV_LEVEL
		* info->rev_level * ext_reverb_ex_rv_level * ext_reverb_ex_level * fbmax; // rv_fb
	info->levelap = (info->density + 1.0) * DIV_2 * REV_EX_AP_LEVEL;
	if(ext_reverb_ex_ap_num){
		info->leveler *= REV_EX_AP_BALANCE;
		info->levelrv *= REV_EX_AP_BALANCE;
	}
// int32の場合 er/rvのミックス部分がint32超える気がするので 入力下げて出力上げ 8bit分
#if !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT)
#if (OPT_MODE == 1)/* fixed-point implementation */
	info->in_leveli = TIM_FSCALE(DIV_MIX_LEVEL, 24 - 8); // input // imuldiv24 //  * DIV_MIX_LEVEL部分
	info->st_sprdi = TIM_FSCALE(info->st_sprd, 24 - 8); // input // imuldiv24 // * st_sprd部分
	info->flt_weti = TIM_FSCALE(info->flt_wet, 24);
	info->flt_dryi = TIM_FSCALE(info->flt_dry, 24);
	info->feedbacki = TIM_FSCALE(info->feedback, 24 - 8); // input // imuldiv24 // * feedback部分
	info->leveleri = TIM_FSCALE(info->leveler , 24); // output // imuldiv16
	info->levelrvi = TIM_FSCALE(info->levelrv , 24); // output // imuldiv16	
	info->levelapi = TIM_FSCALE(info->levelap , 24);;
	for (i = 0; i < num; i++)
		info->rv_feedbacki[i] = TIM_FSCALE(info->rv_feedback[i], 24);
#else // OPT_MODE 0 /* floating-point implementation */
	info->in_level = DIV_8BIT;
	info->leveler *= M_8BIT;
	info->levelrv *= M_8BIT;
#endif /* OPT_MODE == 1 */
#endif /* !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) */
	info->hist[0] = info->hist[1] = 0;	
	info->fb_ap1[0] = info->fb_ap1[1] = 0;	
	info->fb_ap2[0] = info->fb_ap2[1] = 0;	
	// func
	switch(info->mode){
	case CH_STEREO:
		info->do_reverb_mode = ext_reverb_ex_ap_num ? do_reverb_ex_mod_chST_ap8 : do_reverb_ex_mod_chST;
		break;
	case CH_MIX_STEREO:
		info->do_reverb_mode = ext_reverb_ex_ap_num ? do_reverb_ex_mod_chMS_ap8 : do_reverb_ex_mod_chMS;
		break;
	default:
		info->do_reverb_mode = do_reverb_ex_none;
		break;
	}
	if(error) info->do_reverb_mode = do_reverb_ex_none; // safe
	info->init = 1;
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void do_reverb_ex_mod_chST(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	int32 *mindex = &info->index2[REV_EX_UNIT], msize = info->size2[REV_EX_UNIT];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	int32 leveler = info->leveleri, levelrv = info->levelrvi, feedback = info->feedbacki,
		*rv_feedback = info->rv_feedbacki, flt_dry = info->flt_dryi, flt_wet = info->flt_weti,
		*dcH = hpf->dc, *dcL = er_fc->dc, in_level = info->in_leveli, st_sprd = info->st_sprdi;
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[8], *dbL = er_fc->db; 
	DATA_T *hist = info->hist, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2], sprd;
	FLOAT_T mindexf;
	// CH_STEREO:
	for (k = 0; k < count; k++)
	{		
		input[0] = buf[k]; input[1] = buf[k + 1];
		sprd = imuldiv24((input[0] - input[1]), st_sprd);
		input[0] = input[1] = imuldiv24((input[0] + input[1]), in_level);
		input[0] += imuldiv24(hist[0], feedback); input[1] += imuldiv24(hist[1], feedback);
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		// unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		if((++*mindex) >= msize) {*mindex = 0;}
		mindexf = *mindex;
		for (i = 0; i < info->unit_num; i++) {
			int32 index[4];
			FLOAT_T v1[4], v2[4];
			FLOAT_T fp1[4], fp2[4];	
			// lfo
			info->mcount[i][REV_EX_ER_L1] += info->mrate[i][REV_EX_ER_L1];
			info->mcount[i][REV_EX_ER_L1] -= floor(info->mcount[i][REV_EX_ER_L1]);
			info->mcount[i][REV_EX_ER_R1] += info->mrate[i][REV_EX_ER_R1];
			info->mcount[i][REV_EX_ER_R1] -= floor(info->mcount[i][REV_EX_ER_R1]);
			info->mcount[i][REV_EX_RV_L1] += info->mrate[i][REV_EX_RV_L1];
			info->mcount[i][REV_EX_RV_L1] -= floor(info->mcount[i][REV_EX_RV_L1]);
			info->mcount[i][REV_EX_RV_R1] += info->mrate[i][REV_EX_RV_R1];
			info->mcount[i][REV_EX_RV_R1] -= floor(info->mcount[i][REV_EX_RV_R1]);
			fp1[0] = mindexf - info->mdelay[i][REV_EX_ER_L1] - info->mdepth[i][REV_EX_ER_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_L1] + info->mphase[i][REV_EX_ER_L1]);	
			fp1[1] = mindexf - info->mdelay[i][REV_EX_ER_R1] - info->mdepth[i][REV_EX_ER_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_R1] + info->mphase[i][REV_EX_ER_R1]);	
			fp1[2] = mindexf - info->mdelay[i][REV_EX_RV_L1] - info->mdepth[i][REV_EX_RV_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_L1] + info->mphase[i][REV_EX_RV_L1]);	
			fp1[3] = mindexf - info->mdelay[i][REV_EX_RV_R1] - info->mdepth[i][REV_EX_RV_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_R1] + info->mphase[i][REV_EX_RV_R1]);	
			if(fp1[0] < 0) {fp1[0] += msize;}
			if(fp1[1] < 0) {fp1[1] += msize;}		
			if(fp1[2] < 0) {fp1[2] += msize;}
			if(fp1[3] < 0) {fp1[3] += msize;}			
			fp2[0] = floor(fp1[0]); index[0] = fp2[0]; 
			fp2[1] = floor(fp1[1]); index[1] = fp2[1];
			fp2[2] = floor(fp1[2]); index[2] = fp2[2]; 
			fp2[3] = floor(fp1[3]); index[3] = fp2[3]; 
			v1[0] = info->buf[i][REV_EX_ER_L1][index[0]]; v2[0] = info->buf[i][REV_EX_ER_L1][index[0] + 1];
			v1[1] = info->buf[i][REV_EX_ER_R1][index[1]]; v2[1] = info->buf[i][REV_EX_ER_R1][index[1] + 1];
			v1[2] = info->buf[i][REV_EX_RV_L1][index[2]]; v2[2] = info->buf[i][REV_EX_RV_L1][index[2] + 1];
			v1[3] = info->buf[i][REV_EX_RV_R1][index[3]]; v2[3] = info->buf[i][REV_EX_RV_R1][index[3] + 1];
			// er out
			dat_er[0] += v1[0] + (v2[0] - v1[0]) * (fp1[0] - fp2[0]); // linear interpolation
			dat_er[1] += v1[1] + (v2[1] - v1[1]) * (fp1[1] - fp2[1]); // linear interpolation
			// er in
			info->buf[i][0][*mindex] = input[0]; info->buf[i][1][*mindex] = input[1];
			input[0] += sprd; input[1] -= sprd; // spread
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = v1[2] + (v2[2] - v1[2]) * (fp1[2] - fp2[2]); // linear interpolation
			tmp1[1] = v1[3] + (v2[3] - v1[3]) * (fp1[3] - fp2[3]); // linear interpolation
			lpf = &rv_fc[i];
			lpf->db[0] = imuldiv28(tmp1[0], lpf->dc[0]) + imuldiv28(lpf->db[0], lpf->dc[1]);
			lpf->db[1] = imuldiv28(tmp1[1], lpf->dc[0]) + imuldiv28(lpf->db[1], lpf->dc[1]);
			dat_rv[0] += (info->rv_out[i][0] = imuldiv24(tmp1[0], flt_dry) + imuldiv24(lpf->db[0], flt_wet));
			dat_rv[1] += (info->rv_out[i][1] = imuldiv24(tmp1[1], flt_dry) + imuldiv24(lpf->db[1], flt_wet));
			// rv in
			info->buf[i][2][*mindex] = input_rv[0] + imuldiv24(tmp_rv[0], rv_feedback[i]);
			info->buf[i][3][*mindex] = input_rv[1] + imuldiv24(tmp_rv[1], rv_feedback[i]);

			if(*mindex == 0){
				info->buf[i][0][msize] = info->buf[i][0][0];
				info->buf[i][1][msize] = info->buf[i][1][0];
				info->buf[i][2][msize] = info->buf[i][2][0];
				info->buf[i][3][msize] = info->buf[i][3][0];
			}
		}
		// er flt
		dbL[0] = imuldiv28(dat_er[0], dcL[0]) + imuldiv28(dbL[0], dcL[1]);
		dbL[1] = imuldiv28(dat_er[1], dcL[0]) + imuldiv28(dbL[1], dcL[1]);
		dat_er[0] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[0], flt_wet);
		dat_er[1] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[1], flt_wet);
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// out
		hist[0] = imuldiv16(dat_rv[0], levelrv) - imuldiv16(dat_er[0], leveler);
		hist[1] = imuldiv16(dat_rv[1], levelrv) - imuldiv16(dat_er[1], leveler);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = imuldiv28(dbHL[0], dcH[0]) + imuldiv28(dbHL[1], dcH[1]) + imuldiv28(dbHL[2], dcH[2])
			- imuldiv28(dbHL[3], dcH[3]) - imuldiv28(dbHL[4], dcH[4]);
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = imuldiv28(dbHR[0], dcH[0]) + imuldiv28(dbHR[1], dcH[1]) + imuldiv28(dbHR[2], dcH[2])
			- imuldiv28(dbHR[3], dcH[3]) - imuldiv28(dbHR[4], dcH[4]);
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];		
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
}

static void do_reverb_ex_mod_chMS(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	int32 *mindex = &info->index2[REV_EX_UNIT], msize = info->size2[REV_EX_UNIT];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	int32 leveler = info->leveleri, levelrv = info->levelrvi, feedback = info->feedbacki,
		*rv_feedback = info->rv_feedbacki, flt_dry = info->flt_dryi, flt_wet = info->flt_weti,
		*dcH = hpf->dc, *dcL = er_fc->dc, in_level = info->in_leveli;
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T	*hist = info->hist, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2];
	FLOAT_T mindexf;
	// CH_MIX_STEREO:
	for (k = 0; k < count; k++)
	{		
		input[0] = input[1] = imuldiv24((buf[k] + buf[k + 1]), info->in_level);
		input[0] += imuldiv24(hist[0], feedback); input[1] += imuldiv24(hist[1], feedback);
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		// unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		if((++*mindex) >= msize) {*mindex = 0;}
		mindexf = *mindex;
		for (i = 0; i < info->unit_num; i++) {
			int32 index[4];
			FLOAT_T v1[4], v2[4];
			FLOAT_T fp1[4], fp2[4];	
			// lfo
			info->mcount[i][REV_EX_ER_L1] += info->mrate[i][REV_EX_ER_L1];
			info->mcount[i][REV_EX_ER_L1] -= floor(info->mcount[i][REV_EX_ER_L1]);
			info->mcount[i][REV_EX_ER_R1] += info->mrate[i][REV_EX_ER_R1];
			info->mcount[i][REV_EX_ER_R1] -= floor(info->mcount[i][REV_EX_ER_R1]);
			info->mcount[i][REV_EX_RV_L1] += info->mrate[i][REV_EX_RV_L1];
			info->mcount[i][REV_EX_RV_L1] -= floor(info->mcount[i][REV_EX_RV_L1]);
			info->mcount[i][REV_EX_RV_R1] += info->mrate[i][REV_EX_RV_R1];
			info->mcount[i][REV_EX_RV_R1] -= floor(info->mcount[i][REV_EX_RV_R1]);
			fp1[0] = mindexf - info->mdelay[i][REV_EX_ER_L1] - info->mdepth[i][REV_EX_ER_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_L1] + info->mphase[i][REV_EX_ER_L1]);	
			fp1[1] = mindexf - info->mdelay[i][REV_EX_ER_R1] - info->mdepth[i][REV_EX_ER_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_R1] + info->mphase[i][REV_EX_ER_R1]);	
			fp1[2] = mindexf - info->mdelay[i][REV_EX_RV_L1] - info->mdepth[i][REV_EX_RV_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_L1] + info->mphase[i][REV_EX_RV_L1]);	
			fp1[3] = mindexf - info->mdelay[i][REV_EX_RV_R1] - info->mdepth[i][REV_EX_RV_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_R1] + info->mphase[i][REV_EX_RV_R1]);	
			if(fp1[0] < 0) {fp1[0] += msize;}
			if(fp1[1] < 0) {fp1[1] += msize;}		
			if(fp1[2] < 0) {fp1[2] += msize;}
			if(fp1[3] < 0) {fp1[3] += msize;}			
			fp2[0] = floor(fp1[0]); index[0] = fp2[0]; 
			fp2[1] = floor(fp1[1]); index[1] = fp2[1];
			fp2[2] = floor(fp1[2]); index[2] = fp2[2]; 
			fp2[3] = floor(fp1[3]); index[3] = fp2[3]; 
			v1[0] = info->buf[i][REV_EX_ER_L1][index[0]]; v2[0] = info->buf[i][REV_EX_ER_L1][index[0] + 1];
			v1[1] = info->buf[i][REV_EX_ER_R1][index[1]]; v2[1] = info->buf[i][REV_EX_ER_R1][index[1] + 1];
			v1[2] = info->buf[i][REV_EX_RV_L1][index[2]]; v2[2] = info->buf[i][REV_EX_RV_L1][index[2] + 1];
			v1[3] = info->buf[i][REV_EX_RV_R1][index[3]]; v2[3] = info->buf[i][REV_EX_RV_R1][index[3] + 1];
			// er out
			dat_er[0] += v1[0] + (v2[0] - v1[0]) * (fp1[0] - fp2[0]); // linear interpolation
			dat_er[1] += v1[1] + (v2[1] - v1[1]) * (fp1[1] - fp2[1]); // linear interpolation
			// er in
			info->buf[i][0][*mindex] = input[0]; info->buf[i][1][*mindex] = input[1];
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = v1[2] + (v2[2] - v1[2]) * (fp1[2] - fp2[2]); // linear interpolation
			tmp1[1] = v1[3] + (v2[3] - v1[3]) * (fp1[3] - fp2[3]); // linear interpolation
			lpf = &rv_fc[i];
			lpf->db[0] = imuldiv28(tmp1[0], lpf->dc[0]) + imuldiv28(lpf->db[0], lpf->dc[1]);
			lpf->db[1] = imuldiv28(tmp1[1], lpf->dc[0]) + imuldiv28(lpf->db[1], lpf->dc[1]);
			dat_rv[0] += (info->rv_out[i][0] = imuldiv24(tmp1[0], flt_dry) + imuldiv24(lpf->db[0], flt_wet));
			dat_rv[1] += (info->rv_out[i][1] = imuldiv24(tmp1[1], flt_dry) + imuldiv24(lpf->db[1], flt_wet));
			// rv in
			info->buf[i][2][*mindex] = input_rv[0] + imuldiv24(tmp_rv[0], rv_feedback[i]);
			info->buf[i][3][*mindex] = input_rv[1] + imuldiv24(tmp_rv[1], rv_feedback[i]);

			if(*mindex == 0){
				info->buf[i][0][msize] = info->buf[i][0][0];
				info->buf[i][1][msize] = info->buf[i][1][0];
				info->buf[i][2][msize] = info->buf[i][2][0];
				info->buf[i][3][msize] = info->buf[i][3][0];
			}
		}
		// er flt
		dbL[0] = imuldiv28(dat_er[0], dcL[0]) + imuldiv28(dbL[0], dcL[1]);
		dbL[1] = imuldiv28(dat_er[1], dcL[0]) + imuldiv28(dbL[1], dcL[1]);
		dat_er[0] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[0], flt_wet);
		dat_er[1] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[1], flt_wet);
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// out
		hist[0] = imuldiv16(dat_rv[0], levelrv) - imuldiv16(dat_er[0], leveler);
		hist[1] = imuldiv16(dat_rv[1], levelrv) - imuldiv16(dat_er[1], leveler);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = imuldiv28(dbHL[0], dcH[0]) + imuldiv28(dbHL[1], dcH[1]) + imuldiv28(dbHL[2], dcH[2])
			- imuldiv28(dbHL[3], dcH[3]) - imuldiv28(dbHL[4], dcH[4]);
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = imuldiv28(dbHR[0], dcH[0]) + imuldiv28(dbHR[1], dcH[1]) + imuldiv28(dbHR[2], dcH[2])
			- imuldiv28(dbHR[3], dcH[3]) - imuldiv28(dbHR[4], dcH[4]);
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];		
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
}

static void do_reverb_ex_mod_chST_ap8(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	int32 *mindex = &info->index2[REV_EX_UNIT], msize = info->size2[REV_EX_UNIT];
	int32 *aindex = &info->index2[REV_EX_AP1], asize = info->size2[REV_EX_AP1];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	int32 leveler = info->leveleri, levelrv = info->levelrvi, feedback = info->feedbacki,
		*rv_feedback = info->rv_feedbacki, flt_dry = info->flt_dryi, flt_wet = info->flt_weti,
		*dcH = hpf->dc, *dcL = er_fc->dc, in_level = info->in_leveli, st_sprd = info->st_sprdi;
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T	*hist = info->hist, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2], sprd;
	DATA_T *bufa1 = info->buf2[REV_EX_AP1], *bufa2 = info->buf2[REV_EX_AP2], 
		*fb_ap1 = info->fb_ap1, *fb_ap2 = info->fb_ap2;
	int32 levelap = info->levelapi;
	const int32 apfbi = TIM_FSCALE(REV_EX_AP_FB, 24);
	FLOAT_T mindexf, aindexf;
	// CH_STEREO:
	for (k = 0; k < count; k++)
	{		
		input[0] = buf[k]; input[1] = buf[k + 1];
		sprd = imuldiv24((input[0] - input[1]), st_sprd);
		input[0] = input[1] = imuldiv24((input[0] + input[1]), in_level);
		input[0] += imuldiv24(hist[0], feedback); input[1] += imuldiv24(hist[1], feedback);
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		// unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		if((++*mindex) >= msize) {*mindex = 0;}
		mindexf = *mindex;
		for (i = 0; i < info->unit_num; i++) {
			int32 index[4];
			FLOAT_T v1[4], v2[4];
			FLOAT_T fp1[4], fp2[4];	
			// lfo
			info->mcount[i][REV_EX_ER_L1] += info->mrate[i][REV_EX_ER_L1];
			info->mcount[i][REV_EX_ER_L1] -= floor(info->mcount[i][REV_EX_ER_L1]);
			info->mcount[i][REV_EX_ER_R1] += info->mrate[i][REV_EX_ER_R1];
			info->mcount[i][REV_EX_ER_R1] -= floor(info->mcount[i][REV_EX_ER_R1]);
			info->mcount[i][REV_EX_RV_L1] += info->mrate[i][REV_EX_RV_L1];
			info->mcount[i][REV_EX_RV_L1] -= floor(info->mcount[i][REV_EX_RV_L1]);
			info->mcount[i][REV_EX_RV_R1] += info->mrate[i][REV_EX_RV_R1];
			info->mcount[i][REV_EX_RV_R1] -= floor(info->mcount[i][REV_EX_RV_R1]);
			fp1[0] = mindexf - info->mdelay[i][REV_EX_ER_L1] - info->mdepth[i][REV_EX_ER_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_L1] + info->mphase[i][REV_EX_ER_L1]);	
			fp1[1] = mindexf - info->mdelay[i][REV_EX_ER_R1] - info->mdepth[i][REV_EX_ER_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_R1] + info->mphase[i][REV_EX_ER_R1]);	
			fp1[2] = mindexf - info->mdelay[i][REV_EX_RV_L1] - info->mdepth[i][REV_EX_RV_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_L1] + info->mphase[i][REV_EX_RV_L1]);	
			fp1[3] = mindexf - info->mdelay[i][REV_EX_RV_R1] - info->mdepth[i][REV_EX_RV_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_R1] + info->mphase[i][REV_EX_RV_R1]);	
			if(fp1[0] < 0) {fp1[0] += msize;}
			if(fp1[1] < 0) {fp1[1] += msize;}		
			if(fp1[2] < 0) {fp1[2] += msize;}
			if(fp1[3] < 0) {fp1[3] += msize;}			
			fp2[0] = floor(fp1[0]); index[0] = fp2[0]; 
			fp2[1] = floor(fp1[1]); index[1] = fp2[1];
			fp2[2] = floor(fp1[2]); index[2] = fp2[2]; 
			fp2[3] = floor(fp1[3]); index[3] = fp2[3]; 
			v1[0] = info->buf[i][REV_EX_ER_L1][index[0]]; v2[0] = info->buf[i][REV_EX_ER_L1][index[0] + 1];
			v1[1] = info->buf[i][REV_EX_ER_R1][index[1]]; v2[1] = info->buf[i][REV_EX_ER_R1][index[1] + 1];
			v1[2] = info->buf[i][REV_EX_RV_L1][index[2]]; v2[2] = info->buf[i][REV_EX_RV_L1][index[2] + 1];
			v1[3] = info->buf[i][REV_EX_RV_R1][index[3]]; v2[3] = info->buf[i][REV_EX_RV_R1][index[3] + 1];
			// er out
			dat_er[0] += v1[0] + (v2[0] - v1[0]) * (fp1[0] - fp2[0]); // linear interpolation
			dat_er[1] += v1[1] + (v2[1] - v1[1]) * (fp1[1] - fp2[1]); // linear interpolation
			// er in
			info->buf[i][0][*mindex] = input[0]; info->buf[i][1][*mindex] = input[1];
			input[0] += sprd; input[1] -= sprd; // spread
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = v1[2] + (v2[2] - v1[2]) * (fp1[2] - fp2[2]); // linear interpolation
			tmp1[1] = v1[3] + (v2[3] - v1[3]) * (fp1[3] - fp2[3]); // linear interpolation
			lpf = &rv_fc[i];
			lpf->db[0] = imuldiv28(tmp1[0], lpf->dc[0]) + imuldiv28(lpf->db[0], lpf->dc[1]);
			lpf->db[1] = imuldiv28(tmp1[1], lpf->dc[0]) + imuldiv28(lpf->db[1], lpf->dc[1]);
			dat_rv[0] += (info->rv_out[i][0] = imuldiv24(tmp1[0], flt_dry) + imuldiv24(lpf->db[0], flt_wet));
			dat_rv[1] += (info->rv_out[i][1] = imuldiv24(tmp1[1], flt_dry) + imuldiv24(lpf->db[1], flt_wet));
			// rv in
			info->buf[i][2][*mindex] = input_rv[0] + imuldiv24(tmp_rv[0], rv_feedback[i]);
			info->buf[i][3][*mindex] = input_rv[1] + imuldiv24(tmp_rv[1], rv_feedback[i]);

			if(*mindex == 0){
				info->buf[i][0][msize] = info->buf[i][0][0];
				info->buf[i][1][msize] = info->buf[i][1][0];
				info->buf[i][2][msize] = info->buf[i][2][0];
				info->buf[i][3][msize] = info->buf[i][3][0];
			}
		}
		// er flt
		dbL[0] = imuldiv28(dat_er[0], dcL[0]) + imuldiv28(dbL[0], dcL[1]);
		dbL[1] = imuldiv28(dat_er[1], dcL[0]) + imuldiv28(dbL[1], dcL[1]);
		dat_er[0] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[0], flt_wet);
		dat_er[1] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[1], flt_wet);
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// ap
		if ((++(*aindex)) >= asize) {*aindex -= asize;}
		aindexf = aindexf;	
		info->abuf[REV_EX_ER_L1][*aindex] = imuldiv24(dat_er[0], levelap) + imuldiv24(fb_ap1[0], apfbi); 
		info->abuf[REV_EX_ER_R1][*aindex] = imuldiv24(dat_er[1], levelap) + imuldiv24(fb_ap1[1], apfbi); 
		info->abuf[REV_EX_RV_L1][*aindex] = imuldiv24(dat_rv[0], levelap) + imuldiv24(fb_ap2[0], apfbi); 
		info->abuf[REV_EX_RV_R1][*aindex] = imuldiv24(dat_rv[1], levelap) + imuldiv24(fb_ap2[1], apfbi);
		if(*aindex == 0){
			info->abuf[0][asize] = info->abuf[0][0];
			info->abuf[1][asize] = info->abuf[1][0];
			info->abuf[2][asize] = info->abuf[2][0];
			info->abuf[3][asize] = info->abuf[3][0];
		}	
		for (i = 0; i < REV_EX_AP_MAX; i++) {			
			int32 index[4];
			DATA_T v1[4], v2[4];
			FLOAT_T fp1[4], fp2[4];	
			// lfo
			info->acount[i][REV_EX_ER_L1] += info->arate[i][REV_EX_ER_L1];
			info->acount[i][REV_EX_ER_L1] -= floor(info->acount[i][REV_EX_ER_L1]);
			info->acount[i][REV_EX_ER_R1] += info->arate[i][REV_EX_ER_R1];
			info->acount[i][REV_EX_ER_R1] -= floor(info->acount[i][REV_EX_ER_R1]);
			info->acount[i][REV_EX_RV_L1] += info->arate[i][REV_EX_RV_L1];
			info->acount[i][REV_EX_RV_L1] -= floor(info->acount[i][REV_EX_RV_L1]);
			info->acount[i][REV_EX_RV_R1] += info->arate[i][REV_EX_RV_R1];
			info->acount[i][REV_EX_RV_R1] -= floor(info->acount[i][REV_EX_RV_R1]);
			fp1[0] = aindexf - info->adelay[i][REV_EX_ER_L1] - info->adepth[i][REV_EX_ER_L1]
				* lookup2_sine_p(info->acount[i][REV_EX_ER_L1] + info->aphase[i][REV_EX_ER_L1]);	
			fp1[1] = aindexf - info->adelay[i][REV_EX_ER_R1] - info->adepth[i][REV_EX_ER_R1]
				* lookup2_sine_p(info->acount[i][REV_EX_ER_R1] + info->aphase[i][REV_EX_ER_R1]);	
			fp1[2] = aindexf - info->adelay[i][REV_EX_RV_L1] - info->adepth[i][REV_EX_RV_L1]
				* lookup2_sine_p(info->acount[i][REV_EX_RV_L1] + info->aphase[i][REV_EX_RV_L1]);	
			fp1[3] = aindexf - info->adelay[i][REV_EX_RV_R1] - info->adepth[i][REV_EX_RV_R1]
				* lookup2_sine_p(info->acount[i][REV_EX_RV_R1] + info->aphase[i][REV_EX_RV_R1]);	
			if(fp1[0] < 0) {fp1[0] += asize;}
			if(fp1[1] < 0) {fp1[1] += asize;}		
			if(fp1[2] < 0) {fp1[2] += asize;}
			if(fp1[3] < 0) {fp1[3] += asize;}			
			fp2[0] = floor(fp1[0]);
			fp2[1] = floor(fp1[1]);
			fp2[2] = floor(fp1[2]);
			fp2[3] = floor(fp1[3]);
			index[0] = fp2[0]; 
			index[1] = fp2[1]; 
			index[2] = fp2[2]; 
			index[3] = fp2[3]; 
			v1[0] = info->abuf[REV_EX_ER_L1][index[0]]; v2[0] = info->abuf[REV_EX_ER_L1][index[0] + 1];
			v1[1] = info->abuf[REV_EX_ER_R1][index[1]]; v2[1] = info->abuf[REV_EX_ER_R1][index[1] + 1];
			v1[2] = info->abuf[REV_EX_RV_L1][index[2]]; v2[2] = info->abuf[REV_EX_RV_L1][index[2] + 1];
			v1[3] = info->abuf[REV_EX_RV_R1][index[3]]; v2[3] = info->abuf[REV_EX_RV_R1][index[3] + 1];
			dat_er[0] += v1[0] + (v2[0] - v1[0]) * (fp1[0] - fp2[0]); // linear interpolation
			dat_er[1] += v1[1] + (v2[1] - v1[1]) * (fp1[1] - fp2[1]); // linear interpolation
			dat_rv[0] += v1[2] + (v2[2] - v1[2]) * (fp1[2] - fp2[2]); // linear interpolation
			dat_rv[1] += v1[3] + (v2[3] - v1[3]) * (fp1[3] - fp2[3]); // linear interpolation
		}
		fb_ap1[0] = dat_er[0]; fb_ap1[1] = dat_er[1];
		fb_ap2[0] = dat_rv[0]; fb_ap2[1] = dat_rv[1];
		// out
		hist[0] = imuldiv16(dat_rv[0], levelrv) - imuldiv16(dat_er[0], leveler);
		hist[1] = imuldiv16(dat_rv[1], levelrv) - imuldiv16(dat_er[1], leveler);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = imuldiv28(dbHL[0], dcH[0]) + imuldiv28(dbHL[1], dcH[1]) + imuldiv28(dbHL[2], dcH[2])
			- imuldiv28(dbHL[3], dcH[3]) - imuldiv28(dbHL[4], dcH[4]);
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = imuldiv28(dbHR[0], dcH[0]) + imuldiv28(dbHR[1], dcH[1]) + imuldiv28(dbHR[2], dcH[2])
			- imuldiv28(dbHR[3], dcH[3]) - imuldiv28(dbHR[4], dcH[4]);
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];		
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
}

static void do_reverb_ex_mod_chMS_ap8(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	int32 *mindex = &info->index2[REV_EX_UNIT], msize = info->size2[REV_EX_UNIT];
	int32 *aindex = &info->index2[REV_EX_AP1], asize = info->size2[REV_EX_AP1];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	int32 leveler = info->leveleri, levelrv = info->levelrvi, feedback = info->feedbacki,
		*rv_feedback = info->rv_feedbacki, flt_dry = info->flt_dryi, flt_wet = info->flt_weti,
		*dcH = hpf->dc, *dcL = er_fc->dc, in_level = info->in_leveli;
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T	*hist = info->hist, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2];
	DATA_T *bufa1 = info->buf2[REV_EX_AP1], *bufa2 = info->buf2[REV_EX_AP2], 
		*fb_ap1 = info->fb_ap1, *fb_ap2 = info->fb_ap2;
	int32 levelap = info->levelapi;
	const int32 apfbi = TIM_FSCALE(REV_EX_AP_FB, 24);
	FLOAT_T mindexf, aindexf;
	// CH_MIX_STEREO:
	for (k = 0; k < count; k++)
	{		
		input[0] = input[1] = imuldiv24((buf[k] + buf[k + 1]), info->in_level);
		input[0] += imuldiv24(hist[0], feedback); input[1] += imuldiv24(hist[1], feedback);
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		// unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		if((++*mindex) >= msize) {*mindex = 0;}
		mindexf = *mindex;
		for (i = 0; i < info->unit_num; i++) {
			int32 index[4];
			FLOAT_T v1[4], v2[4];
			FLOAT_T fp1[4], fp2[4];	
			// lfo
			info->mcount[i][REV_EX_ER_L1] += info->mrate[i][REV_EX_ER_L1];
			info->mcount[i][REV_EX_ER_L1] -= floor(info->mcount[i][REV_EX_ER_L1]);
			info->mcount[i][REV_EX_ER_R1] += info->mrate[i][REV_EX_ER_R1];
			info->mcount[i][REV_EX_ER_R1] -= floor(info->mcount[i][REV_EX_ER_R1]);
			info->mcount[i][REV_EX_RV_L1] += info->mrate[i][REV_EX_RV_L1];
			info->mcount[i][REV_EX_RV_L1] -= floor(info->mcount[i][REV_EX_RV_L1]);
			info->mcount[i][REV_EX_RV_R1] += info->mrate[i][REV_EX_RV_R1];
			info->mcount[i][REV_EX_RV_R1] -= floor(info->mcount[i][REV_EX_RV_R1]);
			fp1[0] = mindexf - info->mdelay[i][REV_EX_ER_L1] - info->mdepth[i][REV_EX_ER_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_L1] + info->mphase[i][REV_EX_ER_L1]);	
			fp1[1] = mindexf - info->mdelay[i][REV_EX_ER_R1] - info->mdepth[i][REV_EX_ER_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_R1] + info->mphase[i][REV_EX_ER_R1]);	
			fp1[2] = mindexf - info->mdelay[i][REV_EX_RV_L1] - info->mdepth[i][REV_EX_RV_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_L1] + info->mphase[i][REV_EX_RV_L1]);	
			fp1[3] = mindexf - info->mdelay[i][REV_EX_RV_R1] - info->mdepth[i][REV_EX_RV_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_R1] + info->mphase[i][REV_EX_RV_R1]);	
			if(fp1[0] < 0) {fp1[0] += msize;}
			if(fp1[1] < 0) {fp1[1] += msize;}		
			if(fp1[2] < 0) {fp1[2] += msize;}
			if(fp1[3] < 0) {fp1[3] += msize;}			
			fp2[0] = floor(fp1[0]); index[0] = fp2[0]; 
			fp2[1] = floor(fp1[1]); index[1] = fp2[1];
			fp2[2] = floor(fp1[2]); index[2] = fp2[2]; 
			fp2[3] = floor(fp1[3]); index[3] = fp2[3]; 
			v1[0] = info->buf[i][REV_EX_ER_L1][index[0]]; v2[0] = info->buf[i][REV_EX_ER_L1][index[0] + 1];
			v1[1] = info->buf[i][REV_EX_ER_R1][index[1]]; v2[1] = info->buf[i][REV_EX_ER_R1][index[1] + 1];
			v1[2] = info->buf[i][REV_EX_RV_L1][index[2]]; v2[2] = info->buf[i][REV_EX_RV_L1][index[2] + 1];
			v1[3] = info->buf[i][REV_EX_RV_R1][index[3]]; v2[3] = info->buf[i][REV_EX_RV_R1][index[3] + 1];
			// er out
			dat_er[0] += v1[0] + (v2[0] - v1[0]) * (fp1[0] - fp2[0]); // linear interpolation
			dat_er[1] += v1[1] + (v2[1] - v1[1]) * (fp1[1] - fp2[1]); // linear interpolation
			// er in
			info->buf[i][0][*mindex] = input[0]; info->buf[i][1][*mindex] = input[1];
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = v1[2] + (v2[2] - v1[2]) * (fp1[2] - fp2[2]); // linear interpolation
			tmp1[1] = v1[3] + (v2[3] - v1[3]) * (fp1[3] - fp2[3]); // linear interpolation
			lpf = &rv_fc[i];
			lpf->db[0] = imuldiv28(tmp1[0], lpf->dc[0]) + imuldiv28(lpf->db[0], lpf->dc[1]);
			lpf->db[1] = imuldiv28(tmp1[1], lpf->dc[0]) + imuldiv28(lpf->db[1], lpf->dc[1]);
			dat_rv[0] += (info->rv_out[i][0] = imuldiv24(tmp1[0], flt_dry) + imuldiv24(lpf->db[0], flt_wet));
			dat_rv[1] += (info->rv_out[i][1] = imuldiv24(tmp1[1], flt_dry) + imuldiv24(lpf->db[1], flt_wet));
			// rv in
			info->buf[i][2][*mindex] = input_rv[0] + imuldiv24(tmp_rv[0], rv_feedback[i]);
			info->buf[i][3][*mindex] = input_rv[1] + imuldiv24(tmp_rv[1], rv_feedback[i]);

			if(*mindex == 0){
				info->buf[i][0][msize] = info->buf[i][0][0];
				info->buf[i][1][msize] = info->buf[i][1][0];
				info->buf[i][2][msize] = info->buf[i][2][0];
				info->buf[i][3][msize] = info->buf[i][3][0];
			}
		}
		// er flt
		dbL[0] = imuldiv28(dat_er[0], dcL[0]) + imuldiv28(dbL[0], dcL[1]);
		dbL[1] = imuldiv28(dat_er[1], dcL[0]) + imuldiv28(dbL[1], dcL[1]);
		dat_er[0] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[0], flt_wet);
		dat_er[1] = imuldiv24(dat_er, flt_dry) + imuldiv24(dbL[1], flt_wet);
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// ap
		if ((++(*aindex)) >= asize) {*aindex -= asize;}
		aindexf = aindexf;	
		info->abuf[REV_EX_ER_L1][*aindex] = imuldiv24(dat_er[0], levelap) + imuldiv24(fb_ap1[0], apfbi); 
		info->abuf[REV_EX_ER_R1][*aindex] = imuldiv24(dat_er[1], levelap) + imuldiv24(fb_ap1[1], apfbi); 
		info->abuf[REV_EX_RV_L1][*aindex] = imuldiv24(dat_rv[0], levelap) + imuldiv24(fb_ap2[0], apfbi); 
		info->abuf[REV_EX_RV_R1][*aindex] = imuldiv24(dat_rv[1], levelap) + imuldiv24(fb_ap2[1], apfbi);
		if(*aindex == 0){
			info->abuf[0][asize] = info->abuf[0][0];
			info->abuf[1][asize] = info->abuf[1][0];
			info->abuf[2][asize] = info->abuf[2][0];
			info->abuf[3][asize] = info->abuf[3][0];
		}		
		for (i = 0; i < REV_EX_AP_MAX; i++) {			
			int32 index[4];
			DATA_T v1[4], v2[4];
			FLOAT_T fp1[4], fp2[4];	
			// lfo
			info->acount[i][REV_EX_ER_L1] += info->arate[i][REV_EX_ER_L1];
			info->acount[i][REV_EX_ER_L1] -= floor(info->acount[i][REV_EX_ER_L1]);
			info->acount[i][REV_EX_ER_R1] += info->arate[i][REV_EX_ER_R1];
			info->acount[i][REV_EX_ER_R1] -= floor(info->acount[i][REV_EX_ER_R1]);
			info->acount[i][REV_EX_RV_L1] += info->arate[i][REV_EX_RV_L1];
			info->acount[i][REV_EX_RV_L1] -= floor(info->acount[i][REV_EX_RV_L1]);
			info->acount[i][REV_EX_RV_R1] += info->arate[i][REV_EX_RV_R1];
			info->acount[i][REV_EX_RV_R1] -= floor(info->acount[i][REV_EX_RV_R1]);
			fp1[0] = aindexf - info->adelay[i][REV_EX_ER_L1] - info->adepth[i][REV_EX_ER_L1]
				* lookup2_sine_p(info->acount[i][REV_EX_ER_L1] + info->aphase[i][REV_EX_ER_L1]);	
			fp1[1] = aindexf - info->adelay[i][REV_EX_ER_R1] - info->adepth[i][REV_EX_ER_R1]
				* lookup2_sine_p(info->acount[i][REV_EX_ER_R1] + info->aphase[i][REV_EX_ER_R1]);	
			fp1[2] = aindexf - info->adelay[i][REV_EX_RV_L1] - info->adepth[i][REV_EX_RV_L1]
				* lookup2_sine_p(info->acount[i][REV_EX_RV_L1] + info->aphase[i][REV_EX_RV_L1]);	
			fp1[3] = aindexf - info->adelay[i][REV_EX_RV_R1] - info->adepth[i][REV_EX_RV_R1]
				* lookup2_sine_p(info->acount[i][REV_EX_RV_R1] + info->aphase[i][REV_EX_RV_R1]);	
			if(fp1[0] < 0) {fp1[0] += asize;}
			if(fp1[1] < 0) {fp1[1] += asize;}		
			if(fp1[2] < 0) {fp1[2] += asize;}
			if(fp1[3] < 0) {fp1[3] += asize;}			
			fp2[0] = floor(fp1[0]);
			fp2[1] = floor(fp1[1]);
			fp2[2] = floor(fp1[2]);
			fp2[3] = floor(fp1[3]);
			index[0] = fp2[0]; 
			index[1] = fp2[1]; 
			index[2] = fp2[2]; 
			index[3] = fp2[3]; 
			v1[0] = info->abuf[REV_EX_ER_L1][index[0]]; v2[0] = info->abuf[REV_EX_ER_L1][index[0] + 1];
			v1[1] = info->abuf[REV_EX_ER_R1][index[1]]; v2[1] = info->abuf[REV_EX_ER_R1][index[1] + 1];
			v1[2] = info->abuf[REV_EX_RV_L1][index[2]]; v2[2] = info->abuf[REV_EX_RV_L1][index[2] + 1];
			v1[3] = info->abuf[REV_EX_RV_R1][index[3]]; v2[3] = info->abuf[REV_EX_RV_R1][index[3] + 1];
			dat_er[0] += v1[0] + (v2[0] - v1[0]) * (fp1[0] - fp2[0]); // linear interpolation
			dat_er[1] += v1[1] + (v2[1] - v1[1]) * (fp1[1] - fp2[1]); // linear interpolation
			dat_rv[0] += v1[2] + (v2[2] - v1[2]) * (fp1[2] - fp2[2]); // linear interpolation
			dat_rv[1] += v1[3] + (v2[3] - v1[3]) * (fp1[3] - fp2[3]); // linear interpolation
		}
		fb_ap1[0] = dat_er[0]; fb_ap1[1] = dat_er[1];
		fb_ap2[0] = dat_rv[0]; fb_ap2[1] = dat_rv[1];
		// out
		hist[0] = imuldiv16(dat_rv[0], levelrv) - imuldiv16(dat_er[0], leveler);
		hist[1] = imuldiv16(dat_rv[1], levelrv) - imuldiv16(dat_er[1], leveler);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = imuldiv28(dbHL[0], dcH[0]) + imuldiv28(dbHL[1], dcH[1]) + imuldiv28(dbHL[2], dcH[2])
			- imuldiv28(dbHL[3], dcH[3]) - imuldiv28(dbHL[4], dcH[4]);
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = imuldiv28(dbHR[0], dcH[0]) + imuldiv28(dbHR[1], dcH[1]) + imuldiv28(dbHR[2], dcH[2])
			- imuldiv28(dbHR[3], dcH[3]) - imuldiv28(dbHR[4], dcH[4]);
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];		
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
}

#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE) && defined(FLOAT_T_DOUBLE)	
/*
SSE2 128bitSIMD : double*2ch, int32*4ch
*/
static void do_reverb_ex_mod_chST(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0;
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	DATA_T *bufrd = info->buf2[REV_EX_RD];
	__m128d	vec_dcH0 = MM_LOAD1_PD(&hpf->dc[0]), vec_dcH1 = MM_LOAD1_PD(&hpf->dc[1]), vec_dcH2 = MM_LOAD1_PD(&hpf->dc[2]), 
		vec_dcH3 = MM_LOAD1_PD(&hpf->dc[3]), vec_dcH4 = MM_LOAD1_PD(&hpf->dc[4]),
		vec_dcL0 = MM_LOAD1_PD(&er_fc->dc[0]), vec_dcL1 = MM_LOAD1_PD(&er_fc->dc[1]);
	__m128d	vec_dbH0 = _mm_loadu_pd(&hpf->db[0]), vec_dbH1 = _mm_loadu_pd(&hpf->db[2]), vec_dbH2 = _mm_loadu_pd(&hpf->db[4]), 
		vec_dbH3 = _mm_loadu_pd(&hpf->db[6]), vec_dbH4 = _mm_loadu_pd(&hpf->db[8]), vec_dbL = _mm_loadu_pd(er_fc->db);
	__m128d vec_tmp1, vec_input_er, vec_input_rv, vec_mixer, vec_mixap, vec_mixrv, vec_tmp_rv, vec_db, vec_sprd,
		vec_leveler = MM_LOAD1_PD(&info->leveler), vec_levelrv = MM_LOAD1_PD(&info->levelrv),
		vec_dry = MM_LOAD1_PD(&info->flt_dry), vec_wet = MM_LOAD1_PD(&info->flt_wet),
		vec_feedback = MM_LOAD1_PD(&info->feedback), vec_hist = _mm_loadu_pd(info->hist);
	__m128d vec_sp_sprd = _mm_set_pd(-info->st_sprd, info->st_sprd);
	__m128i index2 = _mm_loadu_si128((__m128i *)info->index2), size2 = _mm_loadu_si128((__m128i *)info->size2);
	__m128i add_idx2 = _mm_set_epi32(1, 1, 2, 1);
	__m128d vmsize = _mm_set1_pd(info->size2[REV_EX_UNIT]), vmi;
	int32 msize = info->size2[REV_EX_UNIT], mindex;
	// CH_STEREO:
	for (k = 0; k < count; k += 2)
	{		
		int32 tmpi0;
		vec_sprd = _mm_mul_pd(_mm_set1_pd(buf[k] - buf[k + 1]), vec_sp_sprd);
		vec_input_er = _mm_add_pd(_mm_set1_pd((buf[k] + buf[k + 1]) * DIV_MIX_LEVEL), _mm_mul_pd(vec_hist, vec_feedback));
		// index2 (rv delay, ap
		index2 = _mm_add_epi32(index2, add_idx2);
		index2 = _mm_and_si128(index2, _mm_cmplt_epi32(index2, size2));
		tmpi0 = MM_EXTRACT_EPI32(index2, REV_EX_RD);
		// rv delay out
		vec_input_rv = _mm_load_pd(&bufrd[tmpi0]); // REV_EX_RD
		// unit
		vec_mixer = _mm_setzero_pd(); vec_mixrv = _mm_setzero_pd();
		vmi = _mm_cvtepi32_pd(_mm_shuffle_epi32(index2, 0x0));
		mindex = _mm_cvtsi128_si32(index2);
		for (i = 0; i < info->unit_num; i++) {
		__m128d vc[2], vr[2], vd[2], vfp[2], vtmp[4], vv1[2], vv2[2];
		__m128i vindex[2];
		// lfo
		vc[0] = _mm_add_pd(_mm_loadu_pd(&info->mcount[i][REV_EX_ER_L1]), _mm_loadu_pd(&info->mrate[i][REV_EX_ER_L1])); // mcount+mrate
		vc[1] = _mm_add_pd(_mm_loadu_pd(&info->mcount[i][REV_EX_RV_L1]), _mm_loadu_pd(&info->mrate[i][REV_EX_RV_L1])); // mcount+mrate
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1
		vc[0] = _mm_sub_pd(vc[0], _mm_floor_pd(vc[0])); // mcount-=floor(mcount)
		vc[1] = _mm_sub_pd(vc[1], _mm_floor_pd(vc[1])); // mcount-=floor(mcount)
#else
		vc[0] = _mm_sub_pd(vc[0], _mm_cvtepi32_pd(_mm_cvttpd_epi32(vc[0]))); // mcount-=(int)(mcount) +のみ
		vc[1] = _mm_sub_pd(vc[1], _mm_cvtepi32_pd(_mm_cvttpd_epi32(vc[1]))); // mcount-=(int)(mcount) +のみ
#endif
		_mm_storeu_pd(&info->mcount[i][REV_EX_ER_L1], vc[0]);
		_mm_storeu_pd(&info->mcount[i][REV_EX_RV_L1], vc[1]);
		vr[0] = _mm_add_pd(vc[0], _mm_loadu_pd(&info->mphase[i][REV_EX_ER_L1])); // mcount+mphase
		vr[1] = _mm_add_pd(vc[1], _mm_loadu_pd(&info->mphase[i][REV_EX_RV_L1])); // mcount+mphase
		vd[0] = _mm_set_pd(lookup2_sine_p(MM_EXTRACT_F64(vr[0],1)), lookup2_sine_p(MM_EXTRACT_F64(vr[0],0))); // lookup2_sine_p(mc)
		vd[1] = _mm_set_pd(lookup2_sine_p(MM_EXTRACT_F64(vr[1],1)), lookup2_sine_p(MM_EXTRACT_F64(vr[1],0))); // lookup2_sine_p(mc)	
		vd[0] = _mm_mul_pd(_mm_loadu_pd(&info->mdepth[i][REV_EX_ER_L1]), vd[0]); // mdepth* sine
		vd[1] = _mm_mul_pd(_mm_loadu_pd(&info->mdepth[i][REV_EX_RV_L1]), vd[1]); // mdepth* sine
		vfp[0] = _mm_sub_pd(_mm_sub_pd(vmi, _mm_loadu_pd(&info->mdelay[i][REV_EX_ER_L1])), vd[0]); // mindex-mdelay-mdepth
		vfp[1] = _mm_sub_pd(_mm_sub_pd(vmi, _mm_loadu_pd(&info->mdelay[i][REV_EX_RV_L1])), vd[1]); // mindex-mdelay-mdepth		
		vfp[0] = _mm_add_pd(vfp[0], _mm_and_pd(vmsize, _mm_cmplt_pd(vfp[0], _mm_setzero_pd())));	// fp<0 ? fp+msize	
		vfp[1] = _mm_add_pd(vfp[1], _mm_and_pd(vmsize, _mm_cmplt_pd(vfp[1], _mm_setzero_pd())));	// fp<0 ? fp+msize	
		vindex[0] = _mm_cvttpd_epi32(vfp[0]); // (int)floor(fp)
		vindex[1] = _mm_cvttpd_epi32(vfp[1]); // (int)floor(fp)
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1 floor
		vfp[0] = _mm_sub_pd(vfp[0], _mm_floor_pd(vfp[0])); // fp-floor(fp)
		vfp[1] = _mm_sub_pd(vfp[1], _mm_floor_pd(vfp[1])); // fp-floor(fp)
#else
		vfp[0] = _mm_sub_pd(vfp[0], _mm_cvtepi32_pd(vindex[0])); // fp-vindex
		vfp[1] = _mm_sub_pd(vfp[1], _mm_cvtepi32_pd(vindex[1])); // fp-vindex
#endif
		vtmp[0] = _mm_loadu_pd(&info->buf[i][REV_EX_ER_L1][MM_EXTRACT_I32(vindex[0],0)]); // v1v2
		vtmp[1] = _mm_loadu_pd(&info->buf[i][REV_EX_ER_R1][MM_EXTRACT_I32(vindex[0],1)]); // v1v2
		vtmp[2] = _mm_loadu_pd(&info->buf[i][REV_EX_RV_L1][MM_EXTRACT_I32(vindex[1],0)]); // v1v2
		vtmp[3] = _mm_loadu_pd(&info->buf[i][REV_EX_RV_R1][MM_EXTRACT_I32(vindex[1],1)]); // v1v2
		vv1[0] = _mm_shuffle_pd(vtmp[0], vtmp[1], 0x0);
		vv1[1] = _mm_shuffle_pd(vtmp[2], vtmp[3], 0x0);
		vv2[0] = _mm_shuffle_pd(vtmp[0], vtmp[1], 0x3);
		vv2[1] = _mm_shuffle_pd(vtmp[2], vtmp[3], 0x3);
		vv1[0] = MM_FMA_PD(_mm_sub_pd(vv2[0], vv1[0]), vfp[0], vv1[0]);
		vv1[1] = MM_FMA_PD(_mm_sub_pd(vv2[1], vv1[1]), vfp[1], vv1[1]);
		// er out
		vec_mixer = _mm_add_pd(vec_mixer, vv1[0]);
		_mm_store_sd(&(info->buf[i][0][mindex]), vec_input_er); 
		_mm_store_sd(&(info->buf[i][1][mindex]), _mm_shuffle_pd(vec_input_er, vec_input_er, 0x1));
		vec_input_er = _mm_add_pd(vec_input_er, vec_sprd); // spread
		// rv save
		vec_tmp_rv = _mm_set_pd(*info->rv_in[i][1], *info->rv_in[i][0]);
		// rv out
		vec_tmp1 = vv1[1];
		lpf = &rv_fc[i];
		vec_db = _mm_loadu_pd(lpf->db);
		vec_db = MM_FMA2_PD(MM_LOAD1_PD(&lpf->dc[0]), vec_tmp1, MM_LOAD1_PD(&lpf->dc[1]), vec_db);
		_mm_storeu_pd(lpf->db, vec_db);
		vec_tmp1 = MM_FMA2_PD(vec_tmp1, vec_dry, vec_db, vec_wet);
		vec_mixrv = _mm_add_pd(vec_mixrv, vec_tmp1);
		_mm_storeu_pd(info->rv_out[i], vec_tmp1);
		// rv in
		vec_tmp1 = _mm_add_pd(vec_input_rv, _mm_mul_pd(vec_tmp_rv, MM_LOAD1_PD(&info->rv_feedback[i])));
		_mm_store_sd(&(info->buf[i][2][mindex]), vec_tmp1);
		_mm_store_sd(&(info->buf[i][3][mindex]), _mm_shuffle_pd(vec_tmp1, vec_tmp1, 0x1));
		if(mindex == 0){
			info->buf[i][0][msize] = info->buf[i][0][0];
			info->buf[i][1][msize] = info->buf[i][1][0];
			info->buf[i][2][msize] = info->buf[i][2][0];
			info->buf[i][3][msize] = info->buf[i][3][0];
		}
		}
		// er flt
		vec_dbL = MM_FMA2_PD(vec_dcL0, vec_mixer, vec_dcL1, vec_dbL);
		vec_mixer = MM_FMA2_PD(vec_mixer, vec_dry, vec_dbL, vec_wet);	
		// rv delay in
		_mm_store_pd(&bufrd[tmpi0], vec_mixer);	
		// out
		vec_hist = _mm_sub_pd(_mm_mul_pd(vec_mixrv, vec_levelrv), _mm_mul_pd(vec_mixer, vec_leveler));
		vec_dbH0 = vec_hist;
		vec_hist = vec_dbH2 = MM_FMA5_PD(vec_dcH0, vec_dbH0, vec_dcH1, vec_dbH1, vec_dcH2, vec_dbH2, vec_dcH3, vec_dbH3, vec_dcH4, vec_dbH4);
		vec_dbH4 = vec_dbH3; vec_dbH3 = vec_dbH2; vec_dbH2 = vec_dbH1; vec_dbH1 = vec_dbH0;
		_mm_store_pd(&buf[k], vec_hist);
	}
	_mm_storeu_pd(info->hist, vec_hist); _mm_storeu_pd(er_fc->db, vec_dbL);
	_mm_storeu_pd(&hpf->db[0], vec_dbH0); _mm_storeu_pd(&hpf->db[2], vec_dbH1); _mm_storeu_pd(&hpf->db[4], vec_dbH2);
	_mm_storeu_pd(&hpf->db[6], vec_dbH3); _mm_storeu_pd(&hpf->db[8], vec_dbH4);
	_mm_storeu_si128((__m128i *)info->index2, index2);
}

static void do_reverb_ex_mod_chMS(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0;
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	DATA_T *bufrd = info->buf2[REV_EX_RD];
	__m128d	vec_dcH0 = MM_LOAD1_PD(&hpf->dc[0]), vec_dcH1 = MM_LOAD1_PD(&hpf->dc[1]), vec_dcH2 = MM_LOAD1_PD(&hpf->dc[2]), 
		vec_dcH3 = MM_LOAD1_PD(&hpf->dc[3]), vec_dcH4 = MM_LOAD1_PD(&hpf->dc[4]),
		vec_dcL0 = MM_LOAD1_PD(&er_fc->dc[0]), vec_dcL1 = MM_LOAD1_PD(&er_fc->dc[1]);
	__m128d	vec_dbH0 = _mm_loadu_pd(&hpf->db[0]), vec_dbH1 = _mm_loadu_pd(&hpf->db[2]), vec_dbH2 = _mm_loadu_pd(&hpf->db[4]), 
		vec_dbH3 = _mm_loadu_pd(&hpf->db[6]), vec_dbH4 = _mm_loadu_pd(&hpf->db[8]), vec_dbL = _mm_loadu_pd(er_fc->db);
	__m128d vec_tmp1, vec_input_er, vec_input_rv, vec_mixer, vec_mixap, vec_mixrv, vec_tmp_rv, vec_db, 
		vec_leveler = MM_LOAD1_PD(&info->leveler), vec_levelrv = MM_LOAD1_PD(&info->levelrv),
		vec_dry = MM_LOAD1_PD(&info->flt_dry), vec_wet = MM_LOAD1_PD(&info->flt_wet),
		vec_feedback = MM_LOAD1_PD(&info->feedback), vec_hist = _mm_loadu_pd(info->hist),
		vec_mix_level = _mm_set1_pd(DIV_MIX_LEVEL);
	__m128i index2 = _mm_loadu_si128((__m128i *)info->index2), size2 = _mm_loadu_si128((__m128i *)info->size2);
	__m128i add_idx2 = _mm_set_epi32(1, 1, 2, 1);
	__m128d vmsize = _mm_set1_pd(info->size2[REV_EX_UNIT]), vmi;
	int32 msize = info->size2[REV_EX_UNIT], mindex;
	// CH_MIX_STEREO:
	for (k = 0; k < count; k += 2)
	{		
		int32 tmpi0;
		vec_input_er = _mm_add_pd(_mm_set1_pd((buf[k] + buf[k + 1]) * DIV_MIX_LEVEL), _mm_mul_pd(vec_hist, vec_feedback));
		// index2 (rv delay, ap
		index2 = _mm_add_epi32(index2, add_idx2);
		index2 = _mm_and_si128(index2, _mm_cmplt_epi32(index2, size2));
		tmpi0 = MM_EXTRACT_EPI32(index2, REV_EX_RD);
		// rv delay out
		vec_input_rv = _mm_load_pd(&bufrd[tmpi0]); // REV_EX_RD
		// unit
		vec_mixer = _mm_setzero_pd(); vec_mixrv = _mm_setzero_pd();
		vmi = _mm_cvtepi32_pd(_mm_shuffle_epi32(index2, 0x0));
		mindex = _mm_cvtsi128_si32(index2);
		for (i = 0; i < info->unit_num; i++) {
		__m128d vc[2], vr[2], vd[2], vfp[2], vtmp[4], vv1[2], vv2[2];
		__m128i vindex[2];
		// lfo
		vc[0] = _mm_add_pd(_mm_loadu_pd(&info->mcount[i][REV_EX_ER_L1]), _mm_loadu_pd(&info->mrate[i][REV_EX_ER_L1])); // mcount+mrate
		vc[1] = _mm_add_pd(_mm_loadu_pd(&info->mcount[i][REV_EX_RV_L1]), _mm_loadu_pd(&info->mrate[i][REV_EX_RV_L1])); // mcount+mrate
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1
		vc[0] = _mm_sub_pd(vc[0], _mm_floor_pd(vc[0])); // mcount-=floor(mcount)
		vc[1] = _mm_sub_pd(vc[1], _mm_floor_pd(vc[1])); // mcount-=floor(mcount)
#else
		vc[0] = _mm_sub_pd(vc[0], _mm_cvtepi32_pd(_mm_cvttpd_epi32(vc[0]))); // mcount-=(int)(mcount) +のみ
		vc[1] = _mm_sub_pd(vc[1], _mm_cvtepi32_pd(_mm_cvttpd_epi32(vc[1]))); // mcount-=(int)(mcount) +のみ
#endif
		_mm_storeu_pd(&info->mcount[i][REV_EX_ER_L1], vc[0]);
		_mm_storeu_pd(&info->mcount[i][REV_EX_RV_L1], vc[1]);
		vr[0] = _mm_add_pd(vc[0], _mm_loadu_pd(&info->mphase[i][REV_EX_ER_L1])); // mcount+mphase
		vr[1] = _mm_add_pd(vc[1], _mm_loadu_pd(&info->mphase[i][REV_EX_RV_L1])); // mcount+mphase
		vd[0] = _mm_set_pd(lookup2_sine_p(MM_EXTRACT_F64(vr[0],1)), lookup2_sine_p(MM_EXTRACT_F64(vr[0],0))); // lookup2_sine_p(mc)
		vd[1] = _mm_set_pd(lookup2_sine_p(MM_EXTRACT_F64(vr[1],1)), lookup2_sine_p(MM_EXTRACT_F64(vr[1],0))); // lookup2_sine_p(mc)	
		vd[0] = _mm_mul_pd(_mm_loadu_pd(&info->mdepth[i][REV_EX_ER_L1]), vd[0]); // mdepth* sine
		vd[1] = _mm_mul_pd(_mm_loadu_pd(&info->mdepth[i][REV_EX_RV_L1]), vd[1]); // mdepth* sine
		vfp[0] = _mm_sub_pd(_mm_sub_pd(vmi, _mm_loadu_pd(&info->mdelay[i][REV_EX_ER_L1])), vd[0]); // mindex-mdelay-mdepth
		vfp[1] = _mm_sub_pd(_mm_sub_pd(vmi, _mm_loadu_pd(&info->mdelay[i][REV_EX_RV_L1])), vd[1]); // mindex-mdelay-mdepth		
		vfp[0] = _mm_add_pd(vfp[0], _mm_and_pd(vmsize, _mm_cmplt_pd(vfp[0], _mm_setzero_pd())));	// fp<0 ? fp+msize	
		vfp[1] = _mm_add_pd(vfp[1], _mm_and_pd(vmsize, _mm_cmplt_pd(vfp[1], _mm_setzero_pd())));	// fp<0 ? fp+msize	
		vindex[0] = _mm_cvttpd_epi32(vfp[0]); // (int)floor(fp)
		vindex[1] = _mm_cvttpd_epi32(vfp[1]); // (int)floor(fp)
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1 floor
		vfp[0] = _mm_sub_pd(vfp[0], _mm_floor_pd(vfp[0])); // fp-floor(fp)
		vfp[1] = _mm_sub_pd(vfp[1], _mm_floor_pd(vfp[1])); // fp-floor(fp)
#else
		vfp[0] = _mm_sub_pd(vfp[0], _mm_cvtepi32_pd(vindex[0])); // fp-vindex
		vfp[1] = _mm_sub_pd(vfp[1], _mm_cvtepi32_pd(vindex[1])); // fp-vindex
#endif
		vtmp[0] = _mm_loadu_pd(&info->buf[i][REV_EX_ER_L1][MM_EXTRACT_I32(vindex[0],0)]); // v1v2
		vtmp[1] = _mm_loadu_pd(&info->buf[i][REV_EX_ER_R1][MM_EXTRACT_I32(vindex[0],1)]); // v1v2
		vtmp[2] = _mm_loadu_pd(&info->buf[i][REV_EX_RV_L1][MM_EXTRACT_I32(vindex[1],0)]); // v1v2
		vtmp[3] = _mm_loadu_pd(&info->buf[i][REV_EX_RV_R1][MM_EXTRACT_I32(vindex[1],1)]); // v1v2
		vv1[0] = _mm_shuffle_pd(vtmp[0], vtmp[1], 0x0);
		vv1[1] = _mm_shuffle_pd(vtmp[2], vtmp[3], 0x0);
		vv2[0] = _mm_shuffle_pd(vtmp[0], vtmp[1], 0x3);
		vv2[1] = _mm_shuffle_pd(vtmp[2], vtmp[3], 0x3);
		vv1[0] = MM_FMA_PD(_mm_sub_pd(vv2[0], vv1[0]), vfp[0], vv1[0]);
		vv1[1] = MM_FMA_PD(_mm_sub_pd(vv2[1], vv1[1]), vfp[1], vv1[1]);
		// er out
		vec_mixer = _mm_add_pd(vec_mixer, vv1[0]);
		_mm_store_sd(&(info->buf[i][0][mindex]), vec_input_er); 
		_mm_store_sd(&(info->buf[i][1][mindex]), _mm_shuffle_pd(vec_input_er, vec_input_er, 0x1));
		// rv save
		vec_tmp_rv = _mm_set_pd(*info->rv_in[i][1], *info->rv_in[i][0]);
		// rv out
		vec_tmp1 = vv1[1];
		lpf = &rv_fc[i];
		vec_db = _mm_loadu_pd(lpf->db);
		vec_db = MM_FMA2_PD(MM_LOAD1_PD(&lpf->dc[0]), vec_tmp1, MM_LOAD1_PD(&lpf->dc[1]), vec_db);
		_mm_storeu_pd(lpf->db, vec_db);
		vec_tmp1 = MM_FMA2_PD(vec_tmp1, vec_dry, vec_db, vec_wet);
		vec_mixrv = _mm_add_pd(vec_mixrv, vec_tmp1);
		_mm_storeu_pd(info->rv_out[i], vec_tmp1);
		// rv in
		vec_tmp1 = _mm_add_pd(vec_input_rv, _mm_mul_pd(vec_tmp_rv, MM_LOAD1_PD(&info->rv_feedback[i])));
		_mm_store_sd(&(info->buf[i][2][mindex]), vec_tmp1);
		_mm_store_sd(&(info->buf[i][3][mindex]), _mm_shuffle_pd(vec_tmp1, vec_tmp1, 0x1));
		if(mindex == 0){
			info->buf[i][0][msize] = info->buf[i][0][0];
			info->buf[i][1][msize] = info->buf[i][1][0];
			info->buf[i][2][msize] = info->buf[i][2][0];
			info->buf[i][3][msize] = info->buf[i][3][0];
		}
		}
		// er flt
		vec_dbL = MM_FMA2_PD(vec_dcL0, vec_mixer, vec_dcL1, vec_dbL);
		vec_mixer = MM_FMA2_PD(vec_mixer, vec_dry, vec_dbL, vec_wet);	
		// rv delay in
		_mm_store_pd(&bufrd[tmpi0], vec_mixer);	
		// out
		vec_hist = _mm_sub_pd(_mm_mul_pd(vec_mixrv, vec_levelrv), _mm_mul_pd(vec_mixer, vec_leveler));
		vec_dbH0 = vec_hist;
		vec_hist = vec_dbH2 = MM_FMA5_PD(vec_dcH0, vec_dbH0, vec_dcH1, vec_dbH1, vec_dcH2, vec_dbH2, vec_dcH3, vec_dbH3, vec_dcH4, vec_dbH4);
		vec_dbH4 = vec_dbH3; vec_dbH3 = vec_dbH2; vec_dbH2 = vec_dbH1; vec_dbH1 = vec_dbH0;
		_mm_store_pd(&buf[k], vec_hist);
	}
	_mm_storeu_pd(info->hist, vec_hist); _mm_storeu_pd(er_fc->db, vec_dbL);
	_mm_storeu_pd(&hpf->db[0], vec_dbH0); _mm_storeu_pd(&hpf->db[2], vec_dbH1); _mm_storeu_pd(&hpf->db[4], vec_dbH2);
	_mm_storeu_pd(&hpf->db[6], vec_dbH3); _mm_storeu_pd(&hpf->db[8], vec_dbH4);
	_mm_storeu_si128((__m128i *)info->index2, index2);
}

static void do_reverb_ex_mod_chST_ap8(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0;
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	DATA_T *bufrd = info->buf2[REV_EX_RD];
	__m128d	vec_dcH0 = MM_LOAD1_PD(&hpf->dc[0]), vec_dcH1 = MM_LOAD1_PD(&hpf->dc[1]), vec_dcH2 = MM_LOAD1_PD(&hpf->dc[2]), 
		vec_dcH3 = MM_LOAD1_PD(&hpf->dc[3]), vec_dcH4 = MM_LOAD1_PD(&hpf->dc[4]),
		vec_dcL0 = MM_LOAD1_PD(&er_fc->dc[0]), vec_dcL1 = MM_LOAD1_PD(&er_fc->dc[1]);
	__m128d	vec_dbH0 = _mm_loadu_pd(&hpf->db[0]), vec_dbH1 = _mm_loadu_pd(&hpf->db[2]), vec_dbH2 = _mm_loadu_pd(&hpf->db[4]), 
		vec_dbH3 = _mm_loadu_pd(&hpf->db[6]), vec_dbH4 = _mm_loadu_pd(&hpf->db[8]), vec_dbL = _mm_loadu_pd(er_fc->db);
	__m128d vec_tmp1, vec_input_er, vec_input_rv, vec_mixer, vec_mixap, vec_mixrv, vec_tmp_rv, vec_db, vec_sprd,
		vec_leveler = MM_LOAD1_PD(&info->leveler), vec_levelrv = MM_LOAD1_PD(&info->levelrv),
		vec_dry = MM_LOAD1_PD(&info->flt_dry), vec_wet = MM_LOAD1_PD(&info->flt_wet),
		vec_feedback = MM_LOAD1_PD(&info->feedback), vec_hist = _mm_loadu_pd(info->hist);
	__m128d vec_sp_sprd = _mm_set_pd(-info->st_sprd, info->st_sprd);
	__m128i index2 = _mm_loadu_si128((__m128i *)info->index2), size2 = _mm_loadu_si128((__m128i *)info->size2);
	__m128i add_idx2 = _mm_set_epi32(1, 1, 2, 1);
	__m128d vec_ap_fb = _mm_set1_pd(REV_EX_AP_FB), vec_levelap = MM_LOAD1_PD(&info->levelap), 
		vec_fbap1 = _mm_loadu_pd(info->fb_ap1), vec_fbap2 = _mm_loadu_pd(info->fb_ap2);
	__m128d vmsize = _mm_set1_pd(info->size2[REV_EX_UNIT]), vmi;
	__m128d vasize = _mm_set1_pd(info->size2[REV_EX_AP1]), vai;
	__m128d vtmp[2];
	int32 msize = info->size2[REV_EX_UNIT], mindex;
	// CH_STEREO:
	for (k = 0; k < count; k += 2)
	{		
		ALIGN int32 tmpi2[4];
		vec_sprd = _mm_mul_pd(_mm_set1_pd(buf[k] - buf[k + 1]), vec_sp_sprd);
		vec_input_er = _mm_add_pd(_mm_set1_pd((buf[k] + buf[k + 1]) * DIV_MIX_LEVEL), _mm_mul_pd(vec_hist, vec_feedback));
		// index2 (rv delay, ap
		index2 = _mm_add_epi32(index2, add_idx2);
		index2 = _mm_and_si128(index2, _mm_cmplt_epi32(index2, size2));
		_mm_store_si128((__m128i *)&tmpi2, index2);
		// rv delay out
		vec_input_rv = _mm_load_pd(&bufrd[tmpi2[REV_EX_RD]]);
		// unit
		vec_mixer = _mm_setzero_pd(); vec_mixrv = _mm_setzero_pd();
		vmi = _mm_cvtepi32_pd(_mm_shuffle_epi32(index2, 0x0));
		mindex = _mm_cvtsi128_si32(index2);
		for (i = 0; i < info->unit_num; i++) {
		__m128d vc[2], vr[2], vd[2], vfp[2], vtmp[4], vv1[2], vv2[2];
		__m128i vindex[2];
		// lfo
		vc[0] = _mm_add_pd(_mm_loadu_pd(&info->mcount[i][REV_EX_ER_L1]), _mm_loadu_pd(&info->mrate[i][REV_EX_ER_L1])); // mcount+mrate
		vc[1] = _mm_add_pd(_mm_loadu_pd(&info->mcount[i][REV_EX_RV_L1]), _mm_loadu_pd(&info->mrate[i][REV_EX_RV_L1])); // mcount+mrate
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1
		vc[0] = _mm_sub_pd(vc[0], _mm_floor_pd(vc[0])); // mcount-=floor(mcount)
		vc[1] = _mm_sub_pd(vc[1], _mm_floor_pd(vc[1])); // mcount-=floor(mcount)
#else
		vc[0] = _mm_sub_pd(vc[0], _mm_cvtepi32_pd(_mm_cvttpd_epi32(vc[0]))); // mcount-=(int)(mcount) +のみ
		vc[1] = _mm_sub_pd(vc[1], _mm_cvtepi32_pd(_mm_cvttpd_epi32(vc[1]))); // mcount-=(int)(mcount) +のみ
#endif
		_mm_storeu_pd(&info->mcount[i][REV_EX_ER_L1], vc[0]);
		_mm_storeu_pd(&info->mcount[i][REV_EX_RV_L1], vc[1]);
		vr[0] = _mm_add_pd(vc[0], _mm_loadu_pd(&info->mphase[i][REV_EX_ER_L1])); // mcount+mphase
		vr[1] = _mm_add_pd(vc[1], _mm_loadu_pd(&info->mphase[i][REV_EX_RV_L1])); // mcount+mphase
		vd[0] = _mm_set_pd(lookup2_sine_p(MM_EXTRACT_F64(vr[0],1)), lookup2_sine_p(MM_EXTRACT_F64(vr[0],0))); // lookup2_sine_p(mc)
		vd[1] = _mm_set_pd(lookup2_sine_p(MM_EXTRACT_F64(vr[1],1)), lookup2_sine_p(MM_EXTRACT_F64(vr[1],0))); // lookup2_sine_p(mc)	
		vd[0] = _mm_mul_pd(_mm_loadu_pd(&info->mdepth[i][REV_EX_ER_L1]), vd[0]); // mdepth* sine
		vd[1] = _mm_mul_pd(_mm_loadu_pd(&info->mdepth[i][REV_EX_RV_L1]), vd[1]); // mdepth* sine
		vfp[0] = _mm_sub_pd(_mm_sub_pd(vmi, _mm_loadu_pd(&info->mdelay[i][REV_EX_ER_L1])), vd[0]); // mindex-mdelay-mdepth
		vfp[1] = _mm_sub_pd(_mm_sub_pd(vmi, _mm_loadu_pd(&info->mdelay[i][REV_EX_RV_L1])), vd[1]); // mindex-mdelay-mdepth		
		vfp[0] = _mm_add_pd(vfp[0], _mm_and_pd(vmsize, _mm_cmplt_pd(vfp[0], _mm_setzero_pd())));	// fp<0 ? fp+msize	
		vfp[1] = _mm_add_pd(vfp[1], _mm_and_pd(vmsize, _mm_cmplt_pd(vfp[1], _mm_setzero_pd())));	// fp<0 ? fp+msize	
		vindex[0] = _mm_cvttpd_epi32(vfp[0]); // (int)floor(fp)
		vindex[1] = _mm_cvttpd_epi32(vfp[1]); // (int)floor(fp)
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1 floor
		vfp[0] = _mm_sub_pd(vfp[0], _mm_floor_pd(vfp[0])); // fp-floor(fp)
		vfp[1] = _mm_sub_pd(vfp[1], _mm_floor_pd(vfp[1])); // fp-floor(fp)
#else
		vfp[0] = _mm_sub_pd(vfp[0], _mm_cvtepi32_pd(vindex[0])); // fp-vindex
		vfp[1] = _mm_sub_pd(vfp[1], _mm_cvtepi32_pd(vindex[1])); // fp-vindex
#endif
		vtmp[0] = _mm_loadu_pd(&info->buf[i][REV_EX_ER_L1][MM_EXTRACT_I32(vindex[0],0)]); // v1v2
		vtmp[1] = _mm_loadu_pd(&info->buf[i][REV_EX_ER_R1][MM_EXTRACT_I32(vindex[0],1)]); // v1v2
		vtmp[2] = _mm_loadu_pd(&info->buf[i][REV_EX_RV_L1][MM_EXTRACT_I32(vindex[1],0)]); // v1v2
		vtmp[3] = _mm_loadu_pd(&info->buf[i][REV_EX_RV_R1][MM_EXTRACT_I32(vindex[1],1)]); // v1v2
		vv1[0] = _mm_shuffle_pd(vtmp[0], vtmp[1], 0x0);
		vv1[1] = _mm_shuffle_pd(vtmp[2], vtmp[3], 0x0);
		vv2[0] = _mm_shuffle_pd(vtmp[0], vtmp[1], 0x3);
		vv2[1] = _mm_shuffle_pd(vtmp[2], vtmp[3], 0x3);
		vv1[0] = MM_FMA_PD(_mm_sub_pd(vv2[0], vv1[0]), vfp[0], vv1[0]);
		vv1[1] = MM_FMA_PD(_mm_sub_pd(vv2[1], vv1[1]), vfp[1], vv1[1]);
		// er out
		vec_mixer = _mm_add_pd(vec_mixer, vv1[0]);
		_mm_store_sd(&(info->buf[i][0][mindex]), vec_input_er); 
		_mm_store_sd(&(info->buf[i][1][mindex]), _mm_shuffle_pd(vec_input_er, vec_input_er, 0x1));
		vec_input_er = _mm_add_pd(vec_input_er, vec_sprd); // spread
		// rv save
		vec_tmp_rv = _mm_set_pd(*info->rv_in[i][1], *info->rv_in[i][0]);
		// rv out
		vec_tmp1 = vv1[1];
		lpf = &rv_fc[i];
		vec_db = _mm_loadu_pd(lpf->db);
		vec_db = MM_FMA2_PD(MM_LOAD1_PD(&lpf->dc[0]), vec_tmp1, MM_LOAD1_PD(&lpf->dc[1]), vec_db);
		_mm_storeu_pd(lpf->db, vec_db);
		vec_tmp1 = MM_FMA2_PD(vec_tmp1, vec_dry, vec_db, vec_wet);
		vec_mixrv = _mm_add_pd(vec_mixrv, vec_tmp1);
		_mm_storeu_pd(info->rv_out[i], vec_tmp1);
		// rv in
		vec_tmp1 = _mm_add_pd(vec_input_rv, _mm_mul_pd(vec_tmp_rv, MM_LOAD1_PD(&info->rv_feedback[i])));
		_mm_store_sd(&(info->buf[i][2][mindex]), vec_tmp1);
		_mm_store_sd(&(info->buf[i][3][mindex]), _mm_shuffle_pd(vec_tmp1, vec_tmp1, 0x1));
		if(mindex == 0){
			info->buf[i][0][msize] = info->buf[i][0][0];
			info->buf[i][1][msize] = info->buf[i][1][0];
			info->buf[i][2][msize] = info->buf[i][2][0];
			info->buf[i][3][msize] = info->buf[i][3][0];
		}
		}
		// er flt
		vec_dbL = MM_FMA2_PD(vec_dcL0, vec_mixer, vec_dcL1, vec_dbL);
		vec_mixer = MM_FMA2_PD(vec_mixer, vec_dry, vec_dbL, vec_wet);	
		// rv delay in
		_mm_store_pd(&bufrd[tmpi2[REV_EX_RD]], vec_mixer);
		// ap
		vai = _mm_cvtepi32_pd(_mm_shuffle_epi32(index2, 0xAA));
		vtmp[0] = MM_FMA2_PD(vec_mixer, vec_levelap, vec_fbap1, vec_ap_fb);
		vtmp[1] = MM_FMA2_PD(vec_mixrv, vec_levelap, vec_fbap2, vec_ap_fb);
		_mm_store_sd(&info->abuf[REV_EX_ER_L1][tmpi2[REV_EX_AP1]], vtmp[0]); 
		_mm_store_sd(&info->abuf[REV_EX_ER_R1][tmpi2[REV_EX_AP1]], _mm_shuffle_pd(vtmp[0], vtmp[0], 0x3)); 
		_mm_store_sd(&info->abuf[REV_EX_RV_L1][tmpi2[REV_EX_AP1]], vtmp[1]); 
		_mm_store_sd(&info->abuf[REV_EX_RV_R1][tmpi2[REV_EX_AP1]], _mm_shuffle_pd(vtmp[1], vtmp[0], 0x3)); 
		if(tmpi2[REV_EX_AP1] == 0){
			info->abuf[0][info->size2[REV_EX_AP1]] = info->abuf[0][0];
			info->abuf[1][info->size2[REV_EX_AP1]] = info->abuf[1][0];
			info->abuf[2][info->size2[REV_EX_AP1]] = info->abuf[2][0];
			info->abuf[3][info->size2[REV_EX_AP1]] = info->abuf[3][0];
		}		
		for (i = 0; i < REV_EX_AP_MAX; i++) {				
		__m128d vc[2], vr[2], vd[2], vfp[2], vtmp[4], vv1[2], vv2[2];
		__m128i vindex[2];
		// lfo
		vc[0] = _mm_add_pd(_mm_loadu_pd(&info->acount[i][REV_EX_ER_L1]), _mm_loadu_pd(&info->arate[i][REV_EX_ER_L1])); // mcount+mrate
		vc[1] = _mm_add_pd(_mm_loadu_pd(&info->acount[i][REV_EX_RV_L1]), _mm_loadu_pd(&info->arate[i][REV_EX_RV_L1])); // mcount+mrate
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1
		vc[0] = _mm_sub_pd(vc[0], _mm_floor_pd(vc[0])); // count-=floor(count)
		vc[1] = _mm_sub_pd(vc[1], _mm_floor_pd(vc[1])); // count-=floor(count)
#else
		vc[0] = _mm_sub_pd(vc[0], _mm_cvtepi32_pd(_mm_cvttpd_epi32(vc[0]))); // count-=floor(count) +のみ
		vc[1] = _mm_sub_pd(vc[1], _mm_cvtepi32_pd(_mm_cvttpd_epi32(vc[1]))); // count-=floor(count) +のみ
#endif
		_mm_storeu_pd(&info->acount[i][REV_EX_ER_L1], vc[0]);
		_mm_storeu_pd(&info->acount[i][REV_EX_RV_L1], vc[1]);
		vr[0] = _mm_add_pd(vc[0], _mm_loadu_pd(&info->aphase[i][REV_EX_ER_L1])); // count+phase
		vr[1] = _mm_add_pd(vc[1], _mm_loadu_pd(&info->aphase[i][REV_EX_RV_L1])); // count+phase
		vd[0] = _mm_set_pd(lookup2_sine_p(MM_EXTRACT_F64(vr[0],1)), lookup2_sine_p(MM_EXTRACT_F64(vr[0],0))); // lookup2_sine_p(count)
		vd[1] = _mm_set_pd(lookup2_sine_p(MM_EXTRACT_F64(vr[1],1)), lookup2_sine_p(MM_EXTRACT_F64(vr[1],0))); // lookup2_sine_p(cuont)	
		vd[0] = _mm_mul_pd(_mm_loadu_pd(&info->adepth[i][REV_EX_ER_L1]), vd[0]); // depth* sine
		vd[1] = _mm_mul_pd(_mm_loadu_pd(&info->adepth[i][REV_EX_RV_L1]), vd[1]); // depth* sine
		vfp[0] = _mm_sub_pd(_mm_sub_pd(vai, _mm_loadu_pd(&info->adelay[i][REV_EX_ER_L1])), vd[0]); // index-delay-depth
		vfp[1] = _mm_sub_pd(_mm_sub_pd(vai, _mm_loadu_pd(&info->adelay[i][REV_EX_RV_L1])), vd[1]); // index-delay-depth		
		vfp[0] = _mm_add_pd(vfp[0], _mm_and_pd(vasize, _mm_cmplt_pd(vfp[0], _mm_setzero_pd())));	// fp<0 ? fp+size	
		vfp[1] = _mm_add_pd(vfp[1], _mm_and_pd(vasize, _mm_cmplt_pd(vfp[1], _mm_setzero_pd())));	// fp<0 ? fp+size	
		vindex[0] = _mm_cvttpd_epi32(vfp[0]); // (int)floor(fp)
		vindex[1] = _mm_cvttpd_epi32(vfp[1]); // (int)floor(fp)
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1 floor
		vfp[0] = _mm_sub_pd(vfp[0], _mm_floor_pd(vfp[0])); // fp-floor(fp)
		vfp[1] = _mm_sub_pd(vfp[1], _mm_floor_pd(vfp[1])); // fp-floor(fp)
#else
		vfp[0] = _mm_sub_pd(vfp[0], _mm_cvtepi32_pd(vindex[0])); // fp-vindex
		vfp[1] = _mm_sub_pd(vfp[1], _mm_cvtepi32_pd(vindex[1])); // fp-vindex
#endif
		vtmp[0] = _mm_loadu_pd(&info->abuf[REV_EX_ER_L1][MM_EXTRACT_I32(vindex[0],0)]); // v1v2
		vtmp[1] = _mm_loadu_pd(&info->abuf[REV_EX_ER_R1][MM_EXTRACT_I32(vindex[0],1)]); // v1v2
		vtmp[2] = _mm_loadu_pd(&info->abuf[REV_EX_RV_L1][MM_EXTRACT_I32(vindex[1],0)]); // v1v2
		vtmp[3] = _mm_loadu_pd(&info->abuf[REV_EX_RV_R1][MM_EXTRACT_I32(vindex[1],1)]); // v1v2
		vv1[0] = _mm_shuffle_pd(vtmp[0], vtmp[1], 0x0);
		vv1[1] = _mm_shuffle_pd(vtmp[2], vtmp[3], 0x0);
		vv2[0] = _mm_shuffle_pd(vtmp[0], vtmp[1], 0x3);
		vv2[1] = _mm_shuffle_pd(vtmp[2], vtmp[3], 0x3);
		vec_mixer = _mm_add_pd(vec_mixer, MM_FMA_PD(_mm_sub_pd(vv2[0], vv1[0]), vfp[0], vv1[0]));
		vec_mixrv = _mm_add_pd(vec_mixrv, MM_FMA_PD(_mm_sub_pd(vv2[1], vv1[1]), vfp[1], vv1[1]));
		}
		vec_fbap1 = vec_mixer; vec_fbap2 = vec_mixrv;
		// out
		vec_hist = _mm_sub_pd(_mm_mul_pd(vec_mixrv, vec_levelrv), _mm_mul_pd(vec_mixer, vec_leveler));
		vec_dbH0 = vec_hist;
		vec_hist = vec_dbH2 = MM_FMA5_PD(vec_dcH0, vec_dbH0, vec_dcH1, vec_dbH1, vec_dcH2, vec_dbH2, vec_dcH3, vec_dbH3, vec_dcH4, vec_dbH4);
		vec_dbH4 = vec_dbH3; vec_dbH3 = vec_dbH2; vec_dbH2 = vec_dbH1; vec_dbH1 = vec_dbH0;
		_mm_store_pd(&buf[k], vec_hist);
	}
	_mm_storeu_pd(info->hist, vec_hist); _mm_storeu_pd(er_fc->db, vec_dbL);
	_mm_storeu_pd(&hpf->db[0], vec_dbH0); _mm_storeu_pd(&hpf->db[2], vec_dbH1); _mm_storeu_pd(&hpf->db[4], vec_dbH2);
	_mm_storeu_pd(&hpf->db[6], vec_dbH3); _mm_storeu_pd(&hpf->db[8], vec_dbH4);
	_mm_storeu_si128((__m128i *)info->index2, index2);
	_mm_storeu_pd(info->fb_ap1, vec_fbap1); _mm_storeu_pd(info->fb_ap2, vec_fbap2);
}

static void do_reverb_ex_mod_chMS_ap8(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0;
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	DATA_T *bufrd = info->buf2[REV_EX_RD];
	__m128d	vec_dcH0 = MM_LOAD1_PD(&hpf->dc[0]), vec_dcH1 = MM_LOAD1_PD(&hpf->dc[1]), vec_dcH2 = MM_LOAD1_PD(&hpf->dc[2]), 
		vec_dcH3 = MM_LOAD1_PD(&hpf->dc[3]), vec_dcH4 = MM_LOAD1_PD(&hpf->dc[4]),
		vec_dcL0 = MM_LOAD1_PD(&er_fc->dc[0]), vec_dcL1 = MM_LOAD1_PD(&er_fc->dc[1]);
	__m128d	vec_dbH0 = _mm_loadu_pd(&hpf->db[0]), vec_dbH1 = _mm_loadu_pd(&hpf->db[2]), vec_dbH2 = _mm_loadu_pd(&hpf->db[4]), 
		vec_dbH3 = _mm_loadu_pd(&hpf->db[6]), vec_dbH4 = _mm_loadu_pd(&hpf->db[8]), vec_dbL = _mm_loadu_pd(er_fc->db);
	__m128d vec_tmp1, vec_input_er, vec_input_rv, vec_mixer, vec_mixap, vec_mixrv, vec_tmp_rv, vec_db, 
		vec_leveler = MM_LOAD1_PD(&info->leveler), vec_levelrv = MM_LOAD1_PD(&info->levelrv),
		vec_dry = MM_LOAD1_PD(&info->flt_dry), vec_wet = MM_LOAD1_PD(&info->flt_wet),
		vec_feedback = MM_LOAD1_PD(&info->feedback), vec_hist = _mm_loadu_pd(info->hist),
		vec_mix_level = _mm_set1_pd(DIV_MIX_LEVEL);
	__m128i index2 = _mm_loadu_si128((__m128i *)info->index2), size2 = _mm_loadu_si128((__m128i *)info->size2);
	__m128i add_idx2 = _mm_set_epi32(1, 1, 2, 1);
	__m128d vec_ap_fb = _mm_set1_pd(REV_EX_AP_FB), vec_levelap = MM_LOAD1_PD(&info->levelap), 
		vec_fbap1 = _mm_loadu_pd(info->fb_ap1), vec_fbap2 = _mm_loadu_pd(info->fb_ap2);
	__m128d vmsize = _mm_set1_pd(info->size2[REV_EX_UNIT]), vmi;
	__m128d vasize = _mm_set1_pd(info->size2[REV_EX_AP1]), vai;
	__m128d vtmp[2];
	int32 msize = info->size2[REV_EX_UNIT], mindex;
	// CH_MIX_STEREO:
	for (k = 0; k < count; k += 2)
	{		
		ALIGN int32 tmpi2[4];
		vec_input_er = _mm_add_pd(_mm_set1_pd((buf[k] + buf[k + 1]) * DIV_MIX_LEVEL), _mm_mul_pd(vec_hist, vec_feedback));
		// index2 (rv delay, ap
		index2 = _mm_add_epi32(index2, add_idx2);
		index2 = _mm_and_si128(index2, _mm_cmplt_epi32(index2, size2));
		_mm_store_si128((__m128i *)&tmpi2, index2);
		// rv delay out
		vec_input_rv = _mm_load_pd(&bufrd[tmpi2[REV_EX_RD]]);
		// unit
		vec_mixer = _mm_setzero_pd(); vec_mixrv = _mm_setzero_pd();
		vmi = _mm_cvtepi32_pd(_mm_shuffle_epi32(index2, 0x0));
		mindex = _mm_cvtsi128_si32(index2);
		for (i = 0; i < info->unit_num; i++) {
		__m128d vc[2], vr[2], vd[2], vfp[2], vtmp[4], vv1[2], vv2[2];
		__m128i vindex[2];
		// lfo
		vc[0] = _mm_add_pd(_mm_loadu_pd(&info->mcount[i][REV_EX_ER_L1]), _mm_loadu_pd(&info->mrate[i][REV_EX_ER_L1])); // mcount+mrate
		vc[1] = _mm_add_pd(_mm_loadu_pd(&info->mcount[i][REV_EX_RV_L1]), _mm_loadu_pd(&info->mrate[i][REV_EX_RV_L1])); // mcount+mrate
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1
		vc[0] = _mm_sub_pd(vc[0], _mm_floor_pd(vc[0])); // mcount-=floor(mcount)
		vc[1] = _mm_sub_pd(vc[1], _mm_floor_pd(vc[1])); // mcount-=floor(mcount)
#else
		vc[0] = _mm_sub_pd(vc[0], _mm_cvtepi32_pd(_mm_cvttpd_epi32(vc[0]))); // mcount-=(int)(mcount) +のみ
		vc[1] = _mm_sub_pd(vc[1], _mm_cvtepi32_pd(_mm_cvttpd_epi32(vc[1]))); // mcount-=(int)(mcount) +のみ
#endif
		_mm_storeu_pd(&info->mcount[i][REV_EX_ER_L1], vc[0]);
		_mm_storeu_pd(&info->mcount[i][REV_EX_RV_L1], vc[1]);
		vr[0] = _mm_add_pd(vc[0], _mm_loadu_pd(&info->mphase[i][REV_EX_ER_L1])); // mcount+mphase
		vr[1] = _mm_add_pd(vc[1], _mm_loadu_pd(&info->mphase[i][REV_EX_RV_L1])); // mcount+mphase
		vd[0] = _mm_set_pd(lookup2_sine_p(MM_EXTRACT_F64(vr[0],1)), lookup2_sine_p(MM_EXTRACT_F64(vr[0],0))); // lookup2_sine_p(mc)
		vd[1] = _mm_set_pd(lookup2_sine_p(MM_EXTRACT_F64(vr[1],1)), lookup2_sine_p(MM_EXTRACT_F64(vr[1],0))); // lookup2_sine_p(mc)	
		vd[0] = _mm_mul_pd(_mm_loadu_pd(&info->mdepth[i][REV_EX_ER_L1]), vd[0]); // mdepth* sine
		vd[1] = _mm_mul_pd(_mm_loadu_pd(&info->mdepth[i][REV_EX_RV_L1]), vd[1]); // mdepth* sine
		vfp[0] = _mm_sub_pd(_mm_sub_pd(vmi, _mm_loadu_pd(&info->mdelay[i][REV_EX_ER_L1])), vd[0]); // mindex-mdelay-mdepth
		vfp[1] = _mm_sub_pd(_mm_sub_pd(vmi, _mm_loadu_pd(&info->mdelay[i][REV_EX_RV_L1])), vd[1]); // mindex-mdelay-mdepth		
		vfp[0] = _mm_add_pd(vfp[0], _mm_and_pd(vmsize, _mm_cmplt_pd(vfp[0], _mm_setzero_pd())));	// fp<0 ? fp+msize	
		vfp[1] = _mm_add_pd(vfp[1], _mm_and_pd(vmsize, _mm_cmplt_pd(vfp[1], _mm_setzero_pd())));	// fp<0 ? fp+msize	
		vindex[0] = _mm_cvttpd_epi32(vfp[0]); // (int)floor(fp)
		vindex[1] = _mm_cvttpd_epi32(vfp[1]); // (int)floor(fp)
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1 floor
		vfp[0] = _mm_sub_pd(vfp[0], _mm_floor_pd(vfp[0])); // fp-floor(fp)
		vfp[1] = _mm_sub_pd(vfp[1], _mm_floor_pd(vfp[1])); // fp-floor(fp)
#else
		vfp[0] = _mm_sub_pd(vfp[0], _mm_cvtepi32_pd(vindex[0])); // fp-vindex
		vfp[1] = _mm_sub_pd(vfp[1], _mm_cvtepi32_pd(vindex[1])); // fp-vindex
#endif
		vtmp[0] = _mm_loadu_pd(&info->buf[i][REV_EX_ER_L1][MM_EXTRACT_I32(vindex[0],0)]); // v1v2
		vtmp[1] = _mm_loadu_pd(&info->buf[i][REV_EX_ER_R1][MM_EXTRACT_I32(vindex[0],1)]); // v1v2
		vtmp[2] = _mm_loadu_pd(&info->buf[i][REV_EX_RV_L1][MM_EXTRACT_I32(vindex[1],0)]); // v1v2
		vtmp[3] = _mm_loadu_pd(&info->buf[i][REV_EX_RV_R1][MM_EXTRACT_I32(vindex[1],1)]); // v1v2
		vv1[0] = _mm_shuffle_pd(vtmp[0], vtmp[1], 0x0);
		vv1[1] = _mm_shuffle_pd(vtmp[2], vtmp[3], 0x0);
		vv2[0] = _mm_shuffle_pd(vtmp[0], vtmp[1], 0x3);
		vv2[1] = _mm_shuffle_pd(vtmp[2], vtmp[3], 0x3);
		vv1[0] = MM_FMA_PD(_mm_sub_pd(vv2[0], vv1[0]), vfp[0], vv1[0]);
		vv1[1] = MM_FMA_PD(_mm_sub_pd(vv2[1], vv1[1]), vfp[1], vv1[1]);
		// er out
		vec_mixer = _mm_add_pd(vec_mixer, vv1[0]);
		_mm_store_sd(&(info->buf[i][0][mindex]), vec_input_er); 
		_mm_store_sd(&(info->buf[i][1][mindex]), _mm_shuffle_pd(vec_input_er, vec_input_er, 0x1));
		// rv save
		vec_tmp_rv = _mm_set_pd(*info->rv_in[i][1], *info->rv_in[i][0]);
		// rv out
		vec_tmp1 = vv1[1];
		lpf = &rv_fc[i];
		vec_db = _mm_loadu_pd(lpf->db);
		vec_db = MM_FMA2_PD(MM_LOAD1_PD(&lpf->dc[0]), vec_tmp1, MM_LOAD1_PD(&lpf->dc[1]), vec_db);
		_mm_storeu_pd(lpf->db, vec_db);
		vec_tmp1 = MM_FMA2_PD(vec_tmp1, vec_dry, vec_db, vec_wet);
		vec_mixrv = _mm_add_pd(vec_mixrv, vec_tmp1);
		_mm_storeu_pd(info->rv_out[i], vec_tmp1);
		// rv in
		vec_tmp1 = _mm_add_pd(vec_input_rv, _mm_mul_pd(vec_tmp_rv, MM_LOAD1_PD(&info->rv_feedback[i])));
		_mm_store_sd(&(info->buf[i][2][mindex]), vec_tmp1);
		_mm_store_sd(&(info->buf[i][3][mindex]), _mm_shuffle_pd(vec_tmp1, vec_tmp1, 0x1));
		if(mindex == 0){
			info->buf[i][0][msize] = info->buf[i][0][0];
			info->buf[i][1][msize] = info->buf[i][1][0];
			info->buf[i][2][msize] = info->buf[i][2][0];
			info->buf[i][3][msize] = info->buf[i][3][0];
		}
		}
		// er flt
		vec_dbL = MM_FMA2_PD(vec_dcL0, vec_mixer, vec_dcL1, vec_dbL);
		vec_mixer = MM_FMA2_PD(vec_mixer, vec_dry, vec_dbL, vec_wet);	
		// rv delay in
		_mm_store_pd(&bufrd[tmpi2[REV_EX_RD]], vec_mixer);	
		// ap
		vai = _mm_cvtepi32_pd(_mm_shuffle_epi32(index2, 0xAA));
		vtmp[0] = MM_FMA2_PD(vec_mixer, vec_levelap, vec_fbap1, vec_ap_fb);
		vtmp[1] = MM_FMA2_PD(vec_mixrv, vec_levelap, vec_fbap2, vec_ap_fb);
		_mm_store_sd(&info->abuf[REV_EX_ER_L1][tmpi2[REV_EX_AP1]], vtmp[0]); 
		_mm_store_sd(&info->abuf[REV_EX_ER_R1][tmpi2[REV_EX_AP1]], _mm_shuffle_pd(vtmp[0], vtmp[0], 0x3)); 
		_mm_store_sd(&info->abuf[REV_EX_RV_L1][tmpi2[REV_EX_AP1]], vtmp[1]); 
		_mm_store_sd(&info->abuf[REV_EX_RV_R1][tmpi2[REV_EX_AP1]], _mm_shuffle_pd(vtmp[1], vtmp[0], 0x3)); 
		if(tmpi2[REV_EX_AP1] == 0){
			info->abuf[0][info->size2[REV_EX_AP1]] = info->abuf[0][0];
			info->abuf[1][info->size2[REV_EX_AP1]] = info->abuf[1][0];
			info->abuf[2][info->size2[REV_EX_AP1]] = info->abuf[2][0];
			info->abuf[3][info->size2[REV_EX_AP1]] = info->abuf[3][0];
		}		
		for (i = 0; i < REV_EX_AP_MAX; i++) {				
		__m128d vc[2], vr[2], vd[2], vfp[2], vtmp[4], vv1[2], vv2[2];
		__m128i vindex[2];
		// lfo
		vc[0] = _mm_add_pd(_mm_loadu_pd(&info->acount[i][REV_EX_ER_L1]), _mm_loadu_pd(&info->arate[i][REV_EX_ER_L1])); // mcount+mrate
		vc[1] = _mm_add_pd(_mm_loadu_pd(&info->acount[i][REV_EX_RV_L1]), _mm_loadu_pd(&info->arate[i][REV_EX_RV_L1])); // mcount+mrate
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1
		vc[0] = _mm_sub_pd(vc[0], _mm_floor_pd(vc[0])); // count-=floor(count)
		vc[1] = _mm_sub_pd(vc[1], _mm_floor_pd(vc[1])); // count-=floor(count)
#else
		vc[0] = _mm_sub_pd(vc[0], _mm_cvtepi32_pd(_mm_cvttpd_epi32(vc[0]))); // count-=floor(count) +のみ
		vc[1] = _mm_sub_pd(vc[1], _mm_cvtepi32_pd(_mm_cvttpd_epi32(vc[1]))); // count-=floor(count) +のみ
#endif
		_mm_storeu_pd(&info->acount[i][REV_EX_ER_L1], vc[0]);
		_mm_storeu_pd(&info->acount[i][REV_EX_RV_L1], vc[1]);
		vr[0] = _mm_add_pd(vc[0], _mm_loadu_pd(&info->aphase[i][REV_EX_ER_L1])); // count+phase
		vr[1] = _mm_add_pd(vc[1], _mm_loadu_pd(&info->aphase[i][REV_EX_RV_L1])); // count+phase
		vd[0] = _mm_set_pd(lookup2_sine_p(MM_EXTRACT_F64(vr[0],1)), lookup2_sine_p(MM_EXTRACT_F64(vr[0],0))); // lookup2_sine_p(count)
		vd[1] = _mm_set_pd(lookup2_sine_p(MM_EXTRACT_F64(vr[1],1)), lookup2_sine_p(MM_EXTRACT_F64(vr[1],0))); // lookup2_sine_p(cuont)	
		vd[0] = _mm_mul_pd(_mm_loadu_pd(&info->adepth[i][REV_EX_ER_L1]), vd[0]); // depth* sine
		vd[1] = _mm_mul_pd(_mm_loadu_pd(&info->adepth[i][REV_EX_RV_L1]), vd[1]); // depth* sine
		vfp[0] = _mm_sub_pd(_mm_sub_pd(vai, _mm_loadu_pd(&info->adelay[i][REV_EX_ER_L1])), vd[0]); // index-delay-depth
		vfp[1] = _mm_sub_pd(_mm_sub_pd(vai, _mm_loadu_pd(&info->adelay[i][REV_EX_RV_L1])), vd[1]); // index-delay-depth		
		vfp[0] = _mm_add_pd(vfp[0], _mm_and_pd(vasize, _mm_cmplt_pd(vfp[0], _mm_setzero_pd())));	// fp<0 ? fp+size	
		vfp[1] = _mm_add_pd(vfp[1], _mm_and_pd(vasize, _mm_cmplt_pd(vfp[1], _mm_setzero_pd())));	// fp<0 ? fp+size	
		vindex[0] = _mm_cvttpd_epi32(vfp[0]); // (int)floor(fp)
		vindex[1] = _mm_cvttpd_epi32(vfp[1]); // (int)floor(fp)
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1 floor
		vfp[0] = _mm_sub_pd(vfp[0], _mm_floor_pd(vfp[0])); // fp-floor(fp)
		vfp[1] = _mm_sub_pd(vfp[1], _mm_floor_pd(vfp[1])); // fp-floor(fp)
#else
		vfp[0] = _mm_sub_pd(vfp[0], _mm_cvtepi32_pd(vindex[0])); // fp-vindex
		vfp[1] = _mm_sub_pd(vfp[1], _mm_cvtepi32_pd(vindex[1])); // fp-vindex
#endif
		vtmp[0] = _mm_loadu_pd(&info->abuf[REV_EX_ER_L1][MM_EXTRACT_I32(vindex[0],0)]); // v1v2
		vtmp[1] = _mm_loadu_pd(&info->abuf[REV_EX_ER_R1][MM_EXTRACT_I32(vindex[0],1)]); // v1v2
		vtmp[2] = _mm_loadu_pd(&info->abuf[REV_EX_RV_L1][MM_EXTRACT_I32(vindex[1],0)]); // v1v2
		vtmp[3] = _mm_loadu_pd(&info->abuf[REV_EX_RV_R1][MM_EXTRACT_I32(vindex[1],1)]); // v1v2
		vv1[0] = _mm_shuffle_pd(vtmp[0], vtmp[1], 0x0);
		vv1[1] = _mm_shuffle_pd(vtmp[2], vtmp[3], 0x0);
		vv2[0] = _mm_shuffle_pd(vtmp[0], vtmp[1], 0x3);
		vv2[1] = _mm_shuffle_pd(vtmp[2], vtmp[3], 0x3);
		vec_mixer = _mm_add_pd(vec_mixer, MM_FMA_PD(_mm_sub_pd(vv2[0], vv1[0]), vfp[0], vv1[0]));
		vec_mixrv = _mm_add_pd(vec_mixrv, MM_FMA_PD(_mm_sub_pd(vv2[1], vv1[1]), vfp[1], vv1[1]));
		}
		vec_fbap1 = vec_mixer; vec_fbap2 = vec_mixrv;	
		// out
		vec_hist = _mm_sub_pd(_mm_mul_pd(vec_mixrv, vec_levelrv), _mm_mul_pd(vec_mixer, vec_leveler));
		vec_dbH0 = vec_hist;
		vec_hist = vec_dbH2 = MM_FMA5_PD(vec_dcH0, vec_dbH0, vec_dcH1, vec_dbH1, vec_dcH2, vec_dbH2, vec_dcH3, vec_dbH3, vec_dcH4, vec_dbH4);
		vec_dbH4 = vec_dbH3; vec_dbH3 = vec_dbH2; vec_dbH2 = vec_dbH1; vec_dbH1 = vec_dbH0;
		_mm_store_pd(&buf[k], vec_hist);
	}
	_mm_storeu_pd(info->hist, vec_hist); _mm_storeu_pd(er_fc->db, vec_dbL);
	_mm_storeu_pd(&hpf->db[0], vec_dbH0); _mm_storeu_pd(&hpf->db[2], vec_dbH1); _mm_storeu_pd(&hpf->db[4], vec_dbH2);
	_mm_storeu_pd(&hpf->db[6], vec_dbH3); _mm_storeu_pd(&hpf->db[8], vec_dbH4);
	_mm_storeu_si128((__m128i *)info->index2, index2);
	_mm_storeu_pd(info->fb_ap1, vec_fbap1); _mm_storeu_pd(info->fb_ap2, vec_fbap2);
}

#else /* floating-point implementation */
static void do_reverb_ex_mod_chST(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	int32 *mindex = &info->index2[REV_EX_UNIT], msize = info->size2[REV_EX_UNIT];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	FLOAT_T leveler = info->leveler, levelrv = info->levelrv, feedback = info->feedback,
		*rv_feedback = info->rv_feedback, flt_dry = info->flt_dry, flt_wet = info->flt_wet,
		*dcH = hpf->dc, *dcL = er_fc->dc, st_sprd = info->st_sprd;	
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T 	hist[2] = {info->hist[0], info->hist[1],}, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2], sprd;
	FLOAT_T mindexf;
	// CH_STEREO:
	RDTSC_TEST1
	for (k = 0; k < count; k++)
	{		
#if !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT)
		input[0] = buf[k] * info->in_level; input[1] = buf[k + 1] * info->in_level;
#else
		input[0] = buf[k]; input[1] = buf[k + 1];
#endif
		sprd = (input[0] - input[1]) * st_sprd;
		input[0] = input[1] = (input[0] + input[1]) * DIV_MIX_LEVEL;
		input[0] += hist[0] * feedback; input[1] += hist[1] * feedback;
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		//unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		if((++*mindex) >= msize) {*mindex = 0;}
		mindexf = *mindex;
		for (i = 0; i < info->unit_num; i++) {	
			int32 index[4];
			DATA_T v1[4], v2[4];
			FLOAT_T fp1[4], fp2[4];	
			// lfo
			info->mcount[i][REV_EX_ER_L1] += info->mrate[i][REV_EX_ER_L1];
			info->mcount[i][REV_EX_ER_L1] -= floor(info->mcount[i][REV_EX_ER_L1]);
			info->mcount[i][REV_EX_ER_R1] += info->mrate[i][REV_EX_ER_R1];
			info->mcount[i][REV_EX_ER_R1] -= floor(info->mcount[i][REV_EX_ER_R1]);
			info->mcount[i][REV_EX_RV_L1] += info->mrate[i][REV_EX_RV_L1];
			info->mcount[i][REV_EX_RV_L1] -= floor(info->mcount[i][REV_EX_RV_L1]);
			info->mcount[i][REV_EX_RV_R1] += info->mrate[i][REV_EX_RV_R1];
			info->mcount[i][REV_EX_RV_R1] -= floor(info->mcount[i][REV_EX_RV_R1]);
			fp1[0] = mindexf - info->mdelay[i][REV_EX_ER_L1] - info->mdepth[i][REV_EX_ER_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_L1] + info->mphase[i][REV_EX_ER_L1]);	
			fp1[1] = mindexf - info->mdelay[i][REV_EX_ER_R1] - info->mdepth[i][REV_EX_ER_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_R1] + info->mphase[i][REV_EX_ER_R1]);	
			fp1[2] = mindexf - info->mdelay[i][REV_EX_RV_L1] - info->mdepth[i][REV_EX_RV_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_L1] + info->mphase[i][REV_EX_RV_L1]);	
			fp1[3] = mindexf - info->mdelay[i][REV_EX_RV_R1] - info->mdepth[i][REV_EX_RV_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_R1] + info->mphase[i][REV_EX_RV_R1]);	
			if(fp1[0] < 0) {fp1[0] += msize;}
			if(fp1[1] < 0) {fp1[1] += msize;}		
			if(fp1[2] < 0) {fp1[2] += msize;}
			if(fp1[3] < 0) {fp1[3] += msize;}			
			fp2[0] = floor(fp1[0]); index[0] = fp2[0]; 
			fp2[1] = floor(fp1[1]); index[1] = fp2[1];
			fp2[2] = floor(fp1[2]); index[2] = fp2[2]; 
			fp2[3] = floor(fp1[3]); index[3] = fp2[3]; 
			v1[0] = info->buf[i][REV_EX_ER_L1][index[0]]; v2[0] = info->buf[i][REV_EX_ER_L1][index[0] + 1];
			v1[1] = info->buf[i][REV_EX_ER_R1][index[1]]; v2[1] = info->buf[i][REV_EX_ER_R1][index[1] + 1];
			v1[2] = info->buf[i][REV_EX_RV_L1][index[2]]; v2[2] = info->buf[i][REV_EX_RV_L1][index[2] + 1];
			v1[3] = info->buf[i][REV_EX_RV_R1][index[3]]; v2[3] = info->buf[i][REV_EX_RV_R1][index[3] + 1];
			// er out
			dat_er[0] += v1[0] + (v2[0] - v1[0]) * (fp1[0] - fp2[0]); // linear interpolation
			dat_er[1] += v1[1] + (v2[1] - v1[1]) * (fp1[1] - fp2[1]); // linear interpolation
			// er in
			info->buf[i][0][*mindex] = input[0]; info->buf[i][1][*mindex] = input[1];
			input[0] += sprd; input[1] -= sprd; // spread
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = v1[2] + (v2[2] - v1[2]) * (fp1[2] - fp2[2]); // linear interpolation
			tmp1[1] = v1[3] + (v2[3] - v1[3]) * (fp1[3] - fp2[3]); // linear interpolation
		//	sample_filter_stereo(&rv_fc1[i], &flt[0], &flt[1]);	
			lpf = &rv_fc[i];
			lpf->db[0] = lpf->dc[0] * tmp1[0] + lpf->dc[1] * lpf->db[0];
			lpf->db[1] = lpf->dc[0] * tmp1[1] + lpf->dc[1] * lpf->db[1];
			dat_rv[0] += (info->rv_out[i][0] = tmp1[0] * flt_dry + lpf->db[0] * flt_wet);
			dat_rv[1] += (info->rv_out[i][1] = tmp1[1] * flt_dry + lpf->db[1] * flt_wet);
			// rv in
			info->buf[i][2][*mindex] = input_rv[0] + tmp_rv[0] * rv_feedback[i];
			info->buf[i][3][*mindex] = input_rv[1] + tmp_rv[1] * rv_feedback[i];	
			if(*mindex == 0){
				info->buf[i][0][msize] = info->buf[i][0][0];
				info->buf[i][1][msize] = info->buf[i][1][0];
				info->buf[i][2][msize] = info->buf[i][2][0];
				info->buf[i][3][msize] = info->buf[i][3][0];
			}
		}
	//	sample_filter_stereo(er_fc, &dat_er[0], &dat_er[1]);
		dbL[0] = dcL[0] * dat_er[0] + dcL[1] * dbL[0];
		dbL[1] = dcL[0] * dat_er[1] + dcL[1] * dbL[1];
		dat_er[0] = dat_er[0] * flt_dry + dbL[0] * flt_wet;
		dat_er[1] = dat_er[1] * flt_dry + dbL[1] * flt_wet;	
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// out
		hist[0] = dat_rv[0] * levelrv - dat_er[0] * leveler;
		hist[1] = dat_rv[1] * levelrv - dat_er[1] * leveler;
	//	sample_filter_stereo(hpf, &hist[0], &hist[1]);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = dcH[0] * dbHL[0] + dcH[1] * dbHL[1] + dcH[2] * dbHL[2] + dcH[3] * dbHL[3] + dcH[4] * dbHL[4];
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = dcH[0] * dbHR[0] + dcH[1] * dbHR[1] + dcH[2] * dbHR[2] + dcH[3] * dbHR[3] + dcH[4] * dbHR[4];
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
	info->hist[0] = hist[0], info->hist[1] = hist[1];
	RDTSC_TEST2
}

static void do_reverb_ex_mod_chMS(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	int32 *mindex = &info->index2[REV_EX_UNIT], msize = info->size2[REV_EX_UNIT];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	FLOAT_T leveler = info->leveler, levelrv = info->levelrv, feedback = info->feedback,
		*rv_feedback = info->rv_feedback, flt_dry = info->flt_dry, flt_wet = info->flt_wet,
		*dcH = hpf->dc, *dcL = er_fc->dc;	
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T	hist[2] = {info->hist[0], info->hist[1],}, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2];
	FLOAT_T mindexf;
	// CH_MIX_STEREO:
	for (k = 0; k < count; k++)
	{		
#if !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT)
		input[0] = input[1] = (buf[k] + buf[k + 1]) * DIV_MIX_LEVEL * info->in_level;
#else
		input[0] = input[1] = (buf[k] + buf[k + 1]) * DIV_MIX_LEVEL;
#endif
		input[0] += hist[0] * feedback; input[1] += hist[1] * feedback;
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		//unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		if((++*mindex) >= msize) {*mindex = 0;}
		mindexf = *mindex;
		for (i = 0; i < info->unit_num; i++) {
			int32 index[4];
			DATA_T v1[4], v2[4];
			FLOAT_T fp1[4], fp2[4];	
			// lfo
			info->mcount[i][REV_EX_ER_L1] += info->mrate[i][REV_EX_ER_L1];
			info->mcount[i][REV_EX_ER_L1] -= floor(info->mcount[i][REV_EX_ER_L1]);
			info->mcount[i][REV_EX_ER_R1] += info->mrate[i][REV_EX_ER_R1];
			info->mcount[i][REV_EX_ER_R1] -= floor(info->mcount[i][REV_EX_ER_R1]);
			info->mcount[i][REV_EX_RV_L1] += info->mrate[i][REV_EX_RV_L1];
			info->mcount[i][REV_EX_RV_L1] -= floor(info->mcount[i][REV_EX_RV_L1]);
			info->mcount[i][REV_EX_RV_R1] += info->mrate[i][REV_EX_RV_R1];
			info->mcount[i][REV_EX_RV_R1] -= floor(info->mcount[i][REV_EX_RV_R1]);
			fp1[0] = mindexf - info->mdelay[i][REV_EX_ER_L1] - info->mdepth[i][REV_EX_ER_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_L1] + info->mphase[i][REV_EX_ER_L1]);	
			fp1[1] = mindexf - info->mdelay[i][REV_EX_ER_R1] - info->mdepth[i][REV_EX_ER_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_R1] + info->mphase[i][REV_EX_ER_R1]);	
			fp1[2] = mindexf - info->mdelay[i][REV_EX_RV_L1] - info->mdepth[i][REV_EX_RV_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_L1] + info->mphase[i][REV_EX_RV_L1]);	
			fp1[3] = mindexf - info->mdelay[i][REV_EX_RV_R1] - info->mdepth[i][REV_EX_RV_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_R1] + info->mphase[i][REV_EX_RV_R1]);	
			if(fp1[0] < 0) {fp1[0] += msize;}
			if(fp1[1] < 0) {fp1[1] += msize;}		
			if(fp1[2] < 0) {fp1[2] += msize;}
			if(fp1[3] < 0) {fp1[3] += msize;}			
			fp2[0] = floor(fp1[0]);
			fp2[1] = floor(fp1[1]);
			fp2[2] = floor(fp1[2]);
			fp2[3] = floor(fp1[3]);
			index[0] = fp2[0]; 
			index[1] = fp2[1]; 
			index[2] = fp2[2]; 
			index[3] = fp2[3]; 
			v1[0] = info->buf[i][REV_EX_ER_L1][index[0]]; v2[0] = info->buf[i][REV_EX_ER_L1][index[0] + 1];
			v1[1] = info->buf[i][REV_EX_ER_R1][index[1]]; v2[1] = info->buf[i][REV_EX_ER_R1][index[1] + 1];
			v1[2] = info->buf[i][REV_EX_RV_L1][index[2]]; v2[2] = info->buf[i][REV_EX_RV_L1][index[2] + 1];
			v1[3] = info->buf[i][REV_EX_RV_R1][index[3]]; v2[3] = info->buf[i][REV_EX_RV_R1][index[3] + 1];
			// er out
			dat_er[0] += v1[0] + (v2[0] - v1[0]) * (fp1[0] - fp2[0]); // linear interpolation
			dat_er[1] += v1[1] + (v2[1] - v1[1]) * (fp1[1] - fp2[1]); // linear interpolation
			// er in
			info->buf[i][0][*mindex] = input[0]; info->buf[i][1][*mindex] = input[1];
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = v1[2] + (v2[2] - v1[2]) * (fp1[2] - fp2[2]); // linear interpolation
			tmp1[1] = v1[3] + (v2[3] - v1[3]) * (fp1[3] - fp2[3]); // linear interpolation
		//	sample_filter_stereo(&rv_fc1[i], &flt[0], &flt[1]);	
			lpf = &rv_fc[i];
			lpf->db[0] = lpf->dc[0] * tmp1[0] + lpf->dc[1] * lpf->db[0];
			lpf->db[1] = lpf->dc[0] * tmp1[1] + lpf->dc[1] * lpf->db[1];
			dat_rv[0] += (info->rv_out[i][0] = tmp1[0] * flt_dry + lpf->db[0] * flt_wet);
			dat_rv[1] += (info->rv_out[i][1] = tmp1[1] * flt_dry + lpf->db[1] * flt_wet);
			// rv in
			info->buf[i][2][*mindex] = input_rv[0] + tmp_rv[0] * rv_feedback[i];
			info->buf[i][3][*mindex] = input_rv[1] + tmp_rv[1] * rv_feedback[i];	
			if(*mindex == 0){
				info->buf[i][0][msize] = info->buf[i][0][0];
				info->buf[i][1][msize] = info->buf[i][1][0];
				info->buf[i][2][msize] = info->buf[i][2][0];
				info->buf[i][3][msize] = info->buf[i][3][0];
			}
		}
	//	sample_filter_stereo(er_fc, &dat_er[0], &dat_er[1]);
		dbL[0] = dcL[0] * dat_er[0] + dcL[1] * dbL[0];
		dbL[1] = dcL[0] * dat_er[1] + dcL[1] * dbL[1];
		dat_er[0] = dat_er[0] * flt_dry + dbL[0] * flt_wet;
		dat_er[1] = dat_er[1] * flt_dry + dbL[1] * flt_wet;		
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// out
		hist[0] = dat_rv[0] * levelrv - dat_er[0] * leveler;
		hist[1] = dat_rv[1] * levelrv - dat_er[1] * leveler;
	//	sample_filter_stereo(hpf, &hist[0], &hist[1]);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = dcH[0] * dbHL[0] + dcH[1] * dbHL[1] + dcH[2] * dbHL[2] + dcH[3] * dbHL[3] + dcH[4] * dbHL[4];
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = dcH[0] * dbHR[0] + dcH[1] * dbHR[1] + dcH[2] * dbHR[2] + dcH[3] * dbHR[3] + dcH[4] * dbHR[4];
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
	info->hist[0] = hist[0], info->hist[1] = hist[1];
}

static void do_reverb_ex_mod_chST_ap8(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	int32 *mindex = &info->index2[REV_EX_UNIT], msize = info->size2[REV_EX_UNIT];
	int32 *aindex = &info->index2[REV_EX_AP1], asize = info->size2[REV_EX_AP1];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	FLOAT_T leveler = info->leveler, levelrv = info->levelrv, feedback = info->feedback,
		*rv_feedback = info->rv_feedback, flt_dry = info->flt_dry, flt_wet = info->flt_wet,
		*dcH = hpf->dc, *dcL = er_fc->dc, st_sprd = info->st_sprd;	
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T	hist[2] = {info->hist[0], info->hist[1],}, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2], sprd;
	DATA_T *bufa1 = info->buf2[REV_EX_AP1], *bufa2 = info->buf2[REV_EX_AP2], 
		*fb_ap1 = info->fb_ap1, *fb_ap2 = info->fb_ap2;
	FLOAT_T levelap = info->levelap;
	FLOAT_T mindexf, aindexf;
	// CH_STEREO:
	RDTSC_TEST1
	for (k = 0; k < count; k++)
	{		
#if !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT)
		input[0] = buf[k] * info->in_level; input[1] = buf[k + 1] * info->in_level;
#else
		input[0] = buf[k]; input[1] = buf[k + 1];
#endif
		sprd = (input[0] - input[1]) * st_sprd;
		input[0] = input[1] = (input[0] + input[1]) * DIV_MIX_LEVEL;
		input[0] += hist[0] * feedback; input[1] += hist[1] * feedback;
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		//unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		if((++*mindex) >= msize) {*mindex = 0;}
		mindexf = *mindex;
		for (i = 0; i < info->unit_num; i++) {
			int32 index[4];
			DATA_T v1[4], v2[4];
			FLOAT_T fp1[4], fp2[4];	
			// lfo
			info->mcount[i][REV_EX_ER_L1] += info->mrate[i][REV_EX_ER_L1];
			info->mcount[i][REV_EX_ER_L1] -= floor(info->mcount[i][REV_EX_ER_L1]);
			info->mcount[i][REV_EX_ER_R1] += info->mrate[i][REV_EX_ER_R1];
			info->mcount[i][REV_EX_ER_R1] -= floor(info->mcount[i][REV_EX_ER_R1]);
			info->mcount[i][REV_EX_RV_L1] += info->mrate[i][REV_EX_RV_L1];
			info->mcount[i][REV_EX_RV_L1] -= floor(info->mcount[i][REV_EX_RV_L1]);
			info->mcount[i][REV_EX_RV_R1] += info->mrate[i][REV_EX_RV_R1];
			info->mcount[i][REV_EX_RV_R1] -= floor(info->mcount[i][REV_EX_RV_R1]);
			fp1[0] = mindexf - info->mdelay[i][REV_EX_ER_L1] - info->mdepth[i][REV_EX_ER_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_L1] + info->mphase[i][REV_EX_ER_L1]);	
			fp1[1] = mindexf - info->mdelay[i][REV_EX_ER_R1] - info->mdepth[i][REV_EX_ER_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_R1] + info->mphase[i][REV_EX_ER_R1]);	
			fp1[2] = mindexf - info->mdelay[i][REV_EX_RV_L1] - info->mdepth[i][REV_EX_RV_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_L1] + info->mphase[i][REV_EX_RV_L1]);	
			fp1[3] = mindexf - info->mdelay[i][REV_EX_RV_R1] - info->mdepth[i][REV_EX_RV_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_R1] + info->mphase[i][REV_EX_RV_R1]);	
			if(fp1[0] < 0) {fp1[0] += msize;}
			if(fp1[1] < 0) {fp1[1] += msize;}		
			if(fp1[2] < 0) {fp1[2] += msize;}
			if(fp1[3] < 0) {fp1[3] += msize;}			
			fp2[0] = floor(fp1[0]);
			fp2[1] = floor(fp1[1]);
			fp2[2] = floor(fp1[2]);
			fp2[3] = floor(fp1[3]);
			index[0] = fp2[0]; 
			index[1] = fp2[1]; 
			index[2] = fp2[2]; 
			index[3] = fp2[3]; 
			v1[0] = info->buf[i][REV_EX_ER_L1][index[0]]; v2[0] = info->buf[i][REV_EX_ER_L1][index[0] + 1];
			v1[1] = info->buf[i][REV_EX_ER_R1][index[1]]; v2[1] = info->buf[i][REV_EX_ER_R1][index[1] + 1];
			v1[2] = info->buf[i][REV_EX_RV_L1][index[2]]; v2[2] = info->buf[i][REV_EX_RV_L1][index[2] + 1];
			v1[3] = info->buf[i][REV_EX_RV_R1][index[3]]; v2[3] = info->buf[i][REV_EX_RV_R1][index[3] + 1];
			// er out
			dat_er[0] += v1[0] + (v2[0] - v1[0]) * (fp1[0] - fp2[0]); // linear interpolation
			dat_er[1] += v1[1] + (v2[1] - v1[1]) * (fp1[1] - fp2[1]); // linear interpolation
			// er in
			info->buf[i][0][*mindex] = input[0]; info->buf[i][1][*mindex] = input[1];
			input[0] += sprd; input[1] -= sprd; // spread
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = v1[2] + (v2[2] - v1[2]) * (fp1[2] - fp2[2]); // linear interpolation
			tmp1[1] = v1[3] + (v2[3] - v1[3]) * (fp1[3] - fp2[3]); // linear interpolation
		//	sample_filter_stereo(&rv_fc1[i], &flt[0], &flt[1]);	
			lpf = &rv_fc[i];
			lpf->db[0] = lpf->dc[0] * tmp1[0] + lpf->dc[1] * lpf->db[0];
			lpf->db[1] = lpf->dc[0] * tmp1[1] + lpf->dc[1] * lpf->db[1];
			dat_rv[0] += (info->rv_out[i][0] = tmp1[0] * flt_dry + lpf->db[0] * flt_wet);
			dat_rv[1] += (info->rv_out[i][1] = tmp1[1] * flt_dry + lpf->db[1] * flt_wet);
			// rv in
			info->buf[i][2][*mindex] = input_rv[0] + tmp_rv[0] * rv_feedback[i];
			info->buf[i][3][*mindex] = input_rv[1] + tmp_rv[1] * rv_feedback[i];
	
			if(*mindex == 0){
				info->buf[i][0][msize] = info->buf[i][0][0];
				info->buf[i][1][msize] = info->buf[i][1][0];
				info->buf[i][2][msize] = info->buf[i][2][0];
				info->buf[i][3][msize] = info->buf[i][3][0];
			}
		}
	//	sample_filter_stereo(er_fc, &dat_er[0], &dat_er[1]);
		dbL[0] = dcL[0] * dat_er[0] + dcL[1] * dbL[0];
		dbL[1] = dcL[0] * dat_er[1] + dcL[1] * dbL[1];
		dat_er[0] = dat_er[0] * flt_dry + dbL[0] * flt_wet;
		dat_er[1] = dat_er[1] * flt_dry + dbL[1] * flt_wet;	
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// ap
		if ((++(*aindex)) >= asize) {*aindex -= asize;}
		aindexf = *aindex;
		info->abuf[REV_EX_ER_L1][*aindex] = dat_er[0] * levelap + fb_ap1[0] * REV_EX_AP_FB; 
		info->abuf[REV_EX_ER_R1][*aindex] = dat_er[1] * levelap + fb_ap1[1] * REV_EX_AP_FB; 
		info->abuf[REV_EX_RV_L1][*aindex] = dat_rv[0] * levelap + fb_ap2[0] * REV_EX_AP_FB; 
		info->abuf[REV_EX_RV_R1][*aindex] = dat_rv[1] * levelap + fb_ap2[1] * REV_EX_AP_FB; 
		if(*aindex == 0){
			info->abuf[0][asize] = info->abuf[0][0];
			info->abuf[1][asize] = info->abuf[1][0];
			info->abuf[2][asize] = info->abuf[2][0];
			info->abuf[3][asize] = info->abuf[3][0];
		}		
		for (i = 0; i < REV_EX_AP_MAX; i++) {			
			int32 index[4];
			DATA_T v1[4], v2[4];
			FLOAT_T fp1[4], fp2[4];	
			// lfo
			info->acount[i][REV_EX_ER_L1] += info->arate[i][REV_EX_ER_L1];
			info->acount[i][REV_EX_ER_L1] -= floor(info->acount[i][REV_EX_ER_L1]);
			info->acount[i][REV_EX_ER_R1] += info->arate[i][REV_EX_ER_R1];
			info->acount[i][REV_EX_ER_R1] -= floor(info->acount[i][REV_EX_ER_R1]);
			info->acount[i][REV_EX_RV_L1] += info->arate[i][REV_EX_RV_L1];
			info->acount[i][REV_EX_RV_L1] -= floor(info->acount[i][REV_EX_RV_L1]);
			info->acount[i][REV_EX_RV_R1] += info->arate[i][REV_EX_RV_R1];
			info->acount[i][REV_EX_RV_R1] -= floor(info->acount[i][REV_EX_RV_R1]);
			fp1[0] = aindexf - info->adelay[i][REV_EX_ER_L1] - info->adepth[i][REV_EX_ER_L1]
				* lookup2_sine_p(info->acount[i][REV_EX_ER_L1] + info->aphase[i][REV_EX_ER_L1]);	
			fp1[1] = aindexf - info->adelay[i][REV_EX_ER_R1] - info->adepth[i][REV_EX_ER_R1]
				* lookup2_sine_p(info->acount[i][REV_EX_ER_R1] + info->aphase[i][REV_EX_ER_R1]);	
			fp1[2] = aindexf - info->adelay[i][REV_EX_RV_L1] - info->adepth[i][REV_EX_RV_L1]
				* lookup2_sine_p(info->acount[i][REV_EX_RV_L1] + info->aphase[i][REV_EX_RV_L1]);	
			fp1[3] = aindexf - info->adelay[i][REV_EX_RV_R1] - info->adepth[i][REV_EX_RV_R1]
				* lookup2_sine_p(info->acount[i][REV_EX_RV_R1] + info->aphase[i][REV_EX_RV_R1]);	
			if(fp1[0] < 0) {fp1[0] += asize;}
			if(fp1[1] < 0) {fp1[1] += asize;}		
			if(fp1[2] < 0) {fp1[2] += asize;}
			if(fp1[3] < 0) {fp1[3] += asize;}			
			fp2[0] = floor(fp1[0]);
			fp2[1] = floor(fp1[1]);
			fp2[2] = floor(fp1[2]);
			fp2[3] = floor(fp1[3]);
			index[0] = fp2[0]; 
			index[1] = fp2[1]; 
			index[2] = fp2[2]; 
			index[3] = fp2[3]; 
			v1[0] = info->abuf[REV_EX_ER_L1][index[0]]; v2[0] = info->abuf[REV_EX_ER_L1][index[0] + 1];
			v1[1] = info->abuf[REV_EX_ER_R1][index[1]]; v2[1] = info->abuf[REV_EX_ER_R1][index[1] + 1];
			v1[2] = info->abuf[REV_EX_RV_L1][index[2]]; v2[2] = info->abuf[REV_EX_RV_L1][index[2] + 1];
			v1[3] = info->abuf[REV_EX_RV_R1][index[3]]; v2[3] = info->abuf[REV_EX_RV_R1][index[3] + 1];
			dat_er[0] += v1[0] + (v2[0] - v1[0]) * (fp1[0] - fp2[0]); // linear interpolation
			dat_er[1] += v1[1] + (v2[1] - v1[1]) * (fp1[1] - fp2[1]); // linear interpolation
			dat_rv[0] += v1[2] + (v2[2] - v1[2]) * (fp1[2] - fp2[2]); // linear interpolation
			dat_rv[1] += v1[3] + (v2[3] - v1[3]) * (fp1[3] - fp2[3]); // linear interpolation
		}
		fb_ap1[0] = dat_er[0]; fb_ap1[1] = dat_er[1];
		fb_ap2[0] = dat_rv[0]; fb_ap2[1] = dat_rv[1];
		// out
		hist[0] = dat_rv[0] * levelrv - dat_er[0] * leveler;
		hist[1] = dat_rv[1] * levelrv - dat_er[1] * leveler;
	//	sample_filter_stereo(hpf, &hist[0], &hist[1]);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = dcH[0] * dbHL[0] + dcH[1] * dbHL[1] + dcH[2] * dbHL[2] + dcH[3] * dbHL[3] + dcH[4] * dbHL[4];
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = dcH[0] * dbHR[0] + dcH[1] * dbHR[1] + dcH[2] * dbHR[2] + dcH[3] * dbHR[3] + dcH[4] * dbHR[4];
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
	info->hist[0] = hist[0], info->hist[1] = hist[1];
	RDTSC_TEST2
}

static void do_reverb_ex_mod_chMS_ap8(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int32 i, k = 0, *indexrd = &info->index2[REV_EX_RD], sizerd = info->size2[REV_EX_RD];
	int32 *mindex = &info->index2[REV_EX_UNIT], msize = info->size2[REV_EX_UNIT];
	int32 *aindex = &info->index2[REV_EX_AP1], asize = info->size2[REV_EX_AP1];
	FilterCoefficients *er_fc = &info->er_fc, *rv_fc = info->rv_fc1, *hpf = &info->hpf, *lpf;
	FLOAT_T leveler = info->leveler, levelrv = info->levelrv, feedback = info->feedback,
		*rv_feedback = info->rv_feedback, flt_dry = info->flt_dry, flt_wet = info->flt_wet,
		*dcH = hpf->dc, *dcL = er_fc->dc;	
	FILTER_T *dbHL = &hpf->db[0], *dbHR = &hpf->db[5], *dbL = er_fc->db;
	DATA_T	hist[2] = {info->hist[0], info->hist[1],}, *bufrd = info->buf2[REV_EX_RD],
		input[2], input_rv[2], dat_er[2], dat_rv[2], tmp1[2], tmp_rv[2];
	DATA_T *bufa1 = info->buf2[REV_EX_AP1], *bufa2 = info->buf2[REV_EX_AP2], 
		*fb_ap1 = info->fb_ap1, *fb_ap2 = info->fb_ap2;
	FLOAT_T levelap = info->levelap;
	FLOAT_T mindexf, aindexf;
	// CH_MIX_STEREO:
	for (k = 0; k < count; k++)
	{		
#if !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT)
		input[0] = input[1] = (buf[k] + buf[k + 1]) * DIV_MIX_LEVEL * info->in_level;
#else
		input[0] = input[1] = (buf[k] + buf[k + 1]) * DIV_MIX_LEVEL;
#endif
		input[0] += hist[0] * feedback; input[1] += hist[1] * feedback;
		// rv delay out
		if ((*indexrd += 2) >= sizerd) {*indexrd = 0;}
		input_rv[0] = bufrd[*indexrd]; input_rv[1] = bufrd[*indexrd + 1];
		//unit
		dat_er[0] = 0; dat_er[1] = 0; dat_rv[0] = 0, dat_rv[1] = 0;
		if((++*mindex) >= msize) {*mindex = 0;}
		mindexf = *mindex;
		for (i = 0; i < info->unit_num; i++) {
			int32 index[4];
			DATA_T v1[4], v2[4];
			FLOAT_T fp1[4], fp2[4];	
			// lfo
			info->mcount[i][REV_EX_ER_L1] += info->mrate[i][REV_EX_ER_L1];
			info->mcount[i][REV_EX_ER_L1] -= floor(info->mcount[i][REV_EX_ER_L1]);
			info->mcount[i][REV_EX_ER_R1] += info->mrate[i][REV_EX_ER_R1];
			info->mcount[i][REV_EX_ER_R1] -= floor(info->mcount[i][REV_EX_ER_R1]);
			info->mcount[i][REV_EX_RV_L1] += info->mrate[i][REV_EX_RV_L1];
			info->mcount[i][REV_EX_RV_L1] -= floor(info->mcount[i][REV_EX_RV_L1]);
			info->mcount[i][REV_EX_RV_R1] += info->mrate[i][REV_EX_RV_R1];
			info->mcount[i][REV_EX_RV_R1] -= floor(info->mcount[i][REV_EX_RV_R1]);
			fp1[0] = mindexf - info->mdelay[i][REV_EX_ER_L1] - info->mdepth[i][REV_EX_ER_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_L1] + info->mphase[i][REV_EX_ER_L1]);	
			fp1[1] = mindexf - info->mdelay[i][REV_EX_ER_R1] - info->mdepth[i][REV_EX_ER_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_ER_R1] + info->mphase[i][REV_EX_ER_R1]);	
			fp1[2] = mindexf - info->mdelay[i][REV_EX_RV_L1] - info->mdepth[i][REV_EX_RV_L1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_L1] + info->mphase[i][REV_EX_RV_L1]);	
			fp1[3] = mindexf - info->mdelay[i][REV_EX_RV_R1] - info->mdepth[i][REV_EX_RV_R1]
				* lookup2_sine_p(info->mcount[i][REV_EX_RV_R1] + info->mphase[i][REV_EX_RV_R1]);	
			if(fp1[0] < 0) {fp1[0] += msize;}
			if(fp1[1] < 0) {fp1[1] += msize;}		
			if(fp1[2] < 0) {fp1[2] += msize;}
			if(fp1[3] < 0) {fp1[3] += msize;}			
			fp2[0] = floor(fp1[0]);
			fp2[1] = floor(fp1[1]);
			fp2[2] = floor(fp1[2]);
			fp2[3] = floor(fp1[3]);
			index[0] = fp2[0]; 
			index[1] = fp2[1]; 
			index[2] = fp2[2]; 
			index[3] = fp2[3]; 
			v1[0] = info->buf[i][REV_EX_ER_L1][index[0]]; v2[0] = info->buf[i][REV_EX_ER_L1][index[0] + 1];
			v1[1] = info->buf[i][REV_EX_ER_R1][index[1]]; v2[1] = info->buf[i][REV_EX_ER_R1][index[1] + 1];
			v1[2] = info->buf[i][REV_EX_RV_L1][index[2]]; v2[2] = info->buf[i][REV_EX_RV_L1][index[2] + 1];
			v1[3] = info->buf[i][REV_EX_RV_R1][index[3]]; v2[3] = info->buf[i][REV_EX_RV_R1][index[3] + 1];
			// er out
			dat_er[0] += v1[0] + (v2[0] - v1[0]) * (fp1[0] - fp2[0]); // linear interpolation
			dat_er[1] += v1[1] + (v2[1] - v1[1]) * (fp1[1] - fp2[1]); // linear interpolation
			// er in
			info->buf[i][0][*mindex] = input[0]; info->buf[i][1][*mindex] = input[1];
			// rv save
			tmp_rv[0] = *info->rv_in[i][0]; tmp_rv[1] = *info->rv_in[i][1];
			// rv out	
			tmp1[0] = v1[2] + (v2[2] - v1[2]) * (fp1[2] - fp2[2]); // linear interpolation
			tmp1[1] = v1[3] + (v2[3] - v1[3]) * (fp1[3] - fp2[3]); // linear interpolation
		//	sample_filter_stereo(&rv_fc1[i], &flt[0], &flt[1]);	
			lpf = &rv_fc[i];
			lpf->db[0] = lpf->dc[0] * tmp1[0] + lpf->dc[1] * lpf->db[0];
			lpf->db[1] = lpf->dc[0] * tmp1[1] + lpf->dc[1] * lpf->db[1];
			dat_rv[0] += (info->rv_out[i][0] = tmp1[0] * flt_dry + lpf->db[0] * flt_wet);
			dat_rv[1] += (info->rv_out[i][1] = tmp1[1] * flt_dry + lpf->db[1] * flt_wet);
			// rv in
			info->buf[i][2][*mindex] = input_rv[0] + tmp_rv[0] * rv_feedback[i];
			info->buf[i][3][*mindex] = input_rv[1] + tmp_rv[1] * rv_feedback[i];	
			if(*mindex == 0){
				info->buf[i][0][msize] = info->buf[i][0][0];
				info->buf[i][1][msize] = info->buf[i][1][0];
				info->buf[i][2][msize] = info->buf[i][2][0];
				info->buf[i][3][msize] = info->buf[i][3][0];
			}
		}
	//	sample_filter_stereo(er_fc, &dat_er[0], &dat_er[1]);
		dbL[0] = dcL[0] * dat_er[0] + dcL[1] * dbL[0];
		dbL[1] = dcL[0] * dat_er[1] + dcL[1] * dbL[1];
		dat_er[0] = dat_er[0] * flt_dry + dbL[0] * flt_wet;
		dat_er[1] = dat_er[1] * flt_dry + dbL[1] * flt_wet;		
		// rv delay in
		bufrd[*indexrd] = dat_er[0]; bufrd[*indexrd + 1] = dat_er[1];
		// ap
		if ((++(*aindex)) >= asize) {*aindex -= asize;}
		aindexf = *aindex;
		info->abuf[REV_EX_ER_L1][*aindex] = dat_er[0] * levelap + fb_ap1[0] * REV_EX_AP_FB; 
		info->abuf[REV_EX_ER_R1][*aindex] = dat_er[1] * levelap + fb_ap1[1] * REV_EX_AP_FB; 
		info->abuf[REV_EX_RV_L1][*aindex] = dat_rv[0] * levelap + fb_ap2[0] * REV_EX_AP_FB; 
		info->abuf[REV_EX_RV_R1][*aindex] = dat_rv[1] * levelap + fb_ap2[1] * REV_EX_AP_FB; 
		if(*aindex == 0){
			info->abuf[0][asize] = info->abuf[0][0];
			info->abuf[1][asize] = info->abuf[1][0];
			info->abuf[2][asize] = info->abuf[2][0];
			info->abuf[3][asize] = info->abuf[3][0];
		}		
		for (i = 0; i < REV_EX_AP_MAX; i++) {			
			int32 index[4];
			DATA_T v1[4], v2[4];
			FLOAT_T fp1[4], fp2[4];	
			// lfo
			info->acount[i][REV_EX_ER_L1] += info->arate[i][REV_EX_ER_L1];
			info->acount[i][REV_EX_ER_L1] -= floor(info->acount[i][REV_EX_ER_L1]);
			info->acount[i][REV_EX_ER_R1] += info->arate[i][REV_EX_ER_R1];
			info->acount[i][REV_EX_ER_R1] -= floor(info->acount[i][REV_EX_ER_R1]);
			info->acount[i][REV_EX_RV_L1] += info->arate[i][REV_EX_RV_L1];
			info->acount[i][REV_EX_RV_L1] -= floor(info->acount[i][REV_EX_RV_L1]);
			info->acount[i][REV_EX_RV_R1] += info->arate[i][REV_EX_RV_R1];
			info->acount[i][REV_EX_RV_R1] -= floor(info->acount[i][REV_EX_RV_R1]);
			fp1[0] = aindexf - info->adelay[i][REV_EX_ER_L1] - info->adepth[i][REV_EX_ER_L1]
				* lookup2_sine_p(info->acount[i][REV_EX_ER_L1] + info->aphase[i][REV_EX_ER_L1]);	
			fp1[1] = aindexf - info->adelay[i][REV_EX_ER_R1] - info->adepth[i][REV_EX_ER_R1]
				* lookup2_sine_p(info->acount[i][REV_EX_ER_R1] + info->aphase[i][REV_EX_ER_R1]);	
			fp1[2] = aindexf - info->adelay[i][REV_EX_RV_L1] - info->adepth[i][REV_EX_RV_L1]
				* lookup2_sine_p(info->acount[i][REV_EX_RV_L1] + info->aphase[i][REV_EX_RV_L1]);	
			fp1[3] = aindexf - info->adelay[i][REV_EX_RV_R1] - info->adepth[i][REV_EX_RV_R1]
				* lookup2_sine_p(info->acount[i][REV_EX_RV_R1] + info->aphase[i][REV_EX_RV_R1]);	
			if(fp1[0] < 0) {fp1[0] += asize;}
			if(fp1[1] < 0) {fp1[1] += asize;}		
			if(fp1[2] < 0) {fp1[2] += asize;}
			if(fp1[3] < 0) {fp1[3] += asize;}			
			fp2[0] = floor(fp1[0]);
			fp2[1] = floor(fp1[1]);
			fp2[2] = floor(fp1[2]);
			fp2[3] = floor(fp1[3]);
			index[0] = fp2[0]; 
			index[1] = fp2[1]; 
			index[2] = fp2[2]; 
			index[3] = fp2[3]; 
			v1[0] = info->abuf[REV_EX_ER_L1][index[0]]; v2[0] = info->abuf[REV_EX_ER_L1][index[0] + 1];
			v1[1] = info->abuf[REV_EX_ER_R1][index[1]]; v2[1] = info->abuf[REV_EX_ER_R1][index[1] + 1];
			v1[2] = info->abuf[REV_EX_RV_L1][index[2]]; v2[2] = info->abuf[REV_EX_RV_L1][index[2] + 1];
			v1[3] = info->abuf[REV_EX_RV_R1][index[3]]; v2[3] = info->abuf[REV_EX_RV_R1][index[3] + 1];
			dat_er[0] += v1[0] + (v2[0] - v1[0]) * (fp1[0] - fp2[0]); // linear interpolation
			dat_er[1] += v1[1] + (v2[1] - v1[1]) * (fp1[1] - fp2[1]); // linear interpolation
			dat_rv[0] += v1[2] + (v2[2] - v1[2]) * (fp1[2] - fp2[2]); // linear interpolation
			dat_rv[1] += v1[3] + (v2[3] - v1[3]) * (fp1[3] - fp2[3]); // linear interpolation
		}
		fb_ap1[0] = dat_er[0]; fb_ap1[1] = dat_er[1];
		fb_ap2[0] = dat_rv[0]; fb_ap2[1] = dat_rv[1];
		// out
		hist[0] = dat_rv[0] * levelrv - dat_er[0] * leveler;
		hist[1] = dat_rv[1] * levelrv - dat_er[1] * leveler;
	//	sample_filter_stereo(hpf, &hist[0], &hist[1]);
		dbHL[0] = hist[0];	
		hist[0] = dbHL[2] = dcH[0] * dbHL[0] + dcH[1] * dbHL[1] + dcH[2] * dbHL[2] + dcH[3] * dbHL[3] + dcH[4] * dbHL[4];
		dbHL[4] = dbHL[3];
		dbHL[3] = dbHL[2];
		dbHL[2] = dbHL[1];
		dbHL[1] = dbHL[0];
		dbHR[0] = hist[1];	
		hist[1] = dbHR[2] = dcH[0] * dbHR[0] + dcH[1] * dbHR[1] + dcH[2] * dbHR[2] + dcH[3] * dbHR[3] + dcH[4] * dbHR[4];
		dbHR[4] = dbHR[3];
		dbHR[3] = dbHR[2];
		dbHR[2] = dbHR[1];
		dbHR[1] = dbHR[0];
		buf[k] = hist[0]; buf[++k] = hist[1];
	}
	info->hist[0] = hist[0], info->hist[1] = hist[1];
}
#endif

static void do_reverb_ex(DATA_T *buf, int32 count, InfoReverbEX *info)
{
	int i;
	if(count == MAGIC_INIT_EFFECT_INFO) {
		init_reverb_ex(info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_reverb_ex(info);
		return;
	} if(count < 0)
		return;	
	info->do_reverb_mode(buf, count, info);
}




// reverb ex2
#ifdef REV_EX2


static void do_reverb_ex2(DATA_T *buf, int32 count, InfoReverbEX2 *info)
{
	int i;
	if(count == MAGIC_INIT_EFFECT_INFO) {
		init_reverb_ex2(info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_reverb_ex(info);
		return;
	} if(count < 0)
		return;	
	info->do_reverb_mode(buf, count, info);
}
#endif



/*                      */
/*  Plate Reverberator  */
/*                      */
#define PLATE_SAMPLERATE 29761.0
#define PLATE_DECAY 0.50
#define PLATE_DECAY_DIFFUSION1 0.70
#define PLATE_DECAY_DIFFUSION2 0.50
#define PLATE_INPUT_DIFFUSION1 0.750
#define PLATE_INPUT_DIFFUSION2 0.625
#define PLATE_BANDWIDTH 0.9955
#define PLATE_DAMPING 0.0005
#define PLATE_WET 0.75
#define PLATE_FEEDBACK (0.125)
#define PLATE_ER_LEVEL (0.75)
#define PLATE_RV_LEVEL (0.60)

double ext_plate_reverb_level = 1.0;
double ext_plate_reverb_time = 1.0;

/*! calculate delay sample in current sample-rate */
static inline int32 get_plate_delay(double delay, double t)
{
	return (int32)(delay * (FLOAT_T)play_mode->rate * t / PLATE_SAMPLERATE);
}

/*! Plate Reverberator; this implementation is specialized for system effect. */
#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void CALLINGCONV do_plate_reverb(int32 *buf, int32 count, InfoPlateReverb *info)
{
	int32 i;
	int32 x, xd, val, outl, outr, temp1, temp2, temp3;
	simple_delay *pd = &(info->pd), *pdR = &(info->pdR), *od1l = &(info->od1l), *od2l = &(info->od2l),
		*od3l = &(info->od3l), *od4l = &(info->od4l), *od5l = &(info->od5l),
		*od6l = &(info->od6l), *od1r = &(info->od1r), *od2r = &(info->od2r),
		*od3r = &(info->od3r), *od4r = &(info->od4r), *od5r = &(info->od5r),
		*od7r = &(info->od7r), *od7l = &(info->od7l), *od6r = &(info->od6r),
		*td1 = &(info->td1), *td2 = &(info->td2), *td1d = &(info->td1d), *td2d = &(info->td2d);
	allpass *ap1 = &(info->ap1), *ap2 = &(info->ap2), *ap3 = &(info->ap3), *ap4 = &(info->ap4),
		*ap1R = &(info->ap1R), *ap2R = &(info->ap2R), *ap3R = &(info->ap3R), *ap4R = &(info->ap4R),
		*ap6 = &(info->ap6), *ap6d = &(info->ap6d);
	mod_allpass *ap5 = &(info->ap5), *ap5d = &(info->ap5d);
	lfo *lfo1 = &(info->lfo1), *lfo1d = &(info->lfo1d);
	FilterCoefficients *lpf1 = &(info->lpf1), *lpf2 = &(info->lpf2);
	int32 t1 = info->t1, t1d = info->t1d;
	int32 decayi = info->decayi, ddif1i = info->ddif1i, ddif2i = info->ddif2i,
		idif1i = info->idif1i, idif2i = info->idif2i;
	int32 erL, erR;
	int32 histL = info->histL, histR = info->histR;
	int32 leveler = info->leveleri, levelrv = info->levelrvi, feedback = info->feedbacki, wet = info->weti;
	double t;

	if (count == MAGIC_INIT_EFFECT_INFO) {
		info->feedback = PLATE_WET * info->rev_feedback * PLATE_FEEDBACK;
		info->feedbacki = TIM_FSCALE(info->feedback, 24);
		info->levelrv = info->rev_level * PLATE_RV_LEVEL;
		info->levelrvi = TIM_FSCALE(info->rev_level, 24);
		info->leveler = info->er_level * PLATE_ER_LEVEL;
		info->leveleri = TIM_FSCALE(info->er_level, 24);
		info->wet = PLATE_WET * info->rev_wet * ext_plate_reverb_level;
		info->weti = TIM_FSCALE(info->wet, 24);

		init_lfo(lfo1, 1.30, LFO_SINE, 0);
		init_lfo(lfo1d, 1.30, LFO_SINE, 0);
		t = (info->rev_time_sec * ext_plate_reverb_time) / reverb_time_table[64] - 1.0;
		t = 1.0 + t * DIV_2;
		set_delay(pd, info->er_time_ms * playmode_rate_ms);
		set_delay(pdR, info->er_time_ms * playmode_rate_ms);
		set_delay(td1, get_plate_delay(4453, t)),
		set_delay(td1d, get_plate_delay(4217, t));
		set_delay(td2, get_plate_delay(3720, t));
		set_delay(td2d, get_plate_delay(3163, t));
		set_delay(od1l, get_plate_delay(266, t));
		set_delay(od2l, get_plate_delay(2974, t));
		set_delay(od3l, get_plate_delay(1913, t));
		set_delay(od4l, get_plate_delay(1996, t));
		set_delay(od5l, get_plate_delay(1990, t));
		set_delay(od6l, get_plate_delay(187, t));
		set_delay(od7l, get_plate_delay(1066, t));
		set_delay(od1r, get_plate_delay(353, t));
		set_delay(od2r, get_plate_delay(3627, t));
		set_delay(od3r, get_plate_delay(1228, t));
		set_delay(od4r, get_plate_delay(2673, t));
		set_delay(od5r, get_plate_delay(2111, t));
		set_delay(od6r, get_plate_delay(335, t));
		set_delay(od7r, get_plate_delay(121, t));
		set_allpass(ap1, get_plate_delay(142, t), info->rev_diff * PLATE_INPUT_DIFFUSION1);
		set_allpass(ap2, get_plate_delay(107, t), info->rev_diff * PLATE_INPUT_DIFFUSION1);
		set_allpass(ap3, get_plate_delay(379, t), info->rev_diff * PLATE_INPUT_DIFFUSION2);
		set_allpass(ap4, get_plate_delay(277, t), info->rev_diff * PLATE_INPUT_DIFFUSION2);
		set_allpass(ap1R, get_plate_delay(142, t), info->rev_diff * PLATE_INPUT_DIFFUSION1);
		set_allpass(ap2R, get_plate_delay(107, t), info->rev_diff * PLATE_INPUT_DIFFUSION1);
		set_allpass(ap3R, get_plate_delay(379, t), info->rev_diff * PLATE_INPUT_DIFFUSION2);
		set_allpass(ap4R, get_plate_delay(277, t), info->rev_diff * PLATE_INPUT_DIFFUSION2);
		set_allpass(ap6, get_plate_delay(1800, t), info->rev_diff * PLATE_DECAY_DIFFUSION2);
		set_allpass(ap6d, get_plate_delay(2656, t), info->rev_diff * PLATE_DECAY_DIFFUSION2);
		set_mod_allpass(ap5, get_plate_delay(672, t), get_plate_delay(16, t), info->rev_diff * PLATE_DECAY_DIFFUSION1);
		set_mod_allpass(ap5d, get_plate_delay(908, t), get_plate_delay(16, t), info->rev_diff * PLATE_DECAY_DIFFUSION1);
///r
		init_sample_filter(lpf1, (FLOAT_T)44100.0 * PLATE_BANDWIDTH, 0, FILTER_LPF6);
		init_sample_filter(lpf2, (FLOAT_T)44100.0 * (1.0 - info->rev_damp), 0, FILTER_LPF6);
//		lpf1->a = PLATE_BANDWIDTH; lpf2->a = 1.0 - PLATE_DAMPING;
//		init_filter_lowpass1(lpf1);
//		init_filter_lowpass1(lpf2);
		//lpf1->freq = (FLOAT_T)44100.0 * PLATE_BANDWIDTH;
		//lpf2->freq = (FLOAT_T)44100.0 * (1.0 - info->rev_damp);
		//calc_filter_lowpass1(lpf1);
		//calc_filter_lowpass1(lpf1R);
		//calc_filter_lowpass1(lpf2);
		//init_filter_lowpass1(lpf1);
		//init_filter_lowpass1(lpf1R);
		//init_filter_lowpass1(lpf2);

		info->t1 = info->t1d = 0;
		info->decay = PLATE_DECAY;
		info->decayi = TIM_FSCALE(info->decay, 24);
		info->ddif1 = info->rev_diff * PLATE_DECAY_DIFFUSION1;
		info->ddif1i = TIM_FSCALE(info->ddif1, 24);
		info->ddif2 = info->rev_diff * PLATE_DECAY_DIFFUSION2;
		info->ddif2i = TIM_FSCALE(info->ddif2, 24);
		info->idif1 = info->rev_diff * PLATE_INPUT_DIFFUSION1;
		info->idif1i = TIM_FSCALE(info->idif1, 24);
		info->idif2 = info->rev_diff * PLATE_INPUT_DIFFUSION2;
		info->idif2i = TIM_FSCALE(info->idif2, 24);
		return;
	} else if (count == MAGIC_FREE_EFFECT_INFO) {
		free_delay(pd);	free_delay(pdR);	free_delay(td1); free_delay(td1d); free_delay(td2);
		free_delay(td2d); free_delay(od1l); free_delay(od2l); free_delay(od3l);
		free_delay(od4l); free_delay(od5l); free_delay(od6l); free_delay(od7l);
		free_delay(od1r); free_delay(od2r);	free_delay(od3r); free_delay(od4r);
		free_delay(od5r); free_delay(od6r);	free_delay(od7r);
		free_allpass(ap1); free_allpass(ap2); free_allpass(ap3); free_allpass(ap4);
		free_allpass(ap1R); free_allpass(ap2R); free_allpass(ap3R); free_allpass(ap4R);
		free_allpass(ap6); free_allpass(ap6d);	free_mod_allpass(ap5); free_mod_allpass(ap5d);
		return;
	}
	switch (info->mode) {
	case CH_STEREO:
		for (i = 0; i < count; i++)
		{
			outr = outl = 0;
			erL = imuldiv24(buf[i], wet) + imuldiv24(histL, feedback);
			erR = imuldiv24(buf[i + 1], wet) + imuldiv24(histR, feedback);

			do_delay(&erL, pd->buf, pd->size, &pd->index);
			sample_filter_left(lpf1, &erL);
			do_allpass(&erL, ap1->buf, ap1->size, &ap1->index, idif1i);
			do_allpass(&erL, ap2->buf, ap2->size, &ap2->index, idif1i);
			do_allpass(&erL, ap3->buf, ap3->size, &ap3->index, idif2i);
			do_allpass(&erL, ap4->buf, ap4->size, &ap4->index, idif2i);
			do_delay(&erR, pd->buf, pd->size, &pd->index);
			sample_filter_right(lpf1, &erR);
			do_allpass(&erR, ap1R->buf, ap1R->size, &ap1R->index, idif1i);
			do_allpass(&erR, ap2R->buf, ap2R->size, &ap2R->index, idif1i);
			do_allpass(&erR, ap3R->buf, ap3R->size, &ap3R->index, idif2i);
			do_allpass(&erR, ap4R->buf, ap4R->size, &ap4R->index, idif2i);

			x = imuldiv24((erL + erR), DIV_MIX_LEVELi);
			/* tank structure */
			xd = x;
			x += imuldiv24(t1d, decayi);
			val = do_lfo(lfo1);
			do_mod_allpass(&x, ap5->buf, ap5->size, &ap5->rindex, &ap5->windex,
				ap5->ndelay, ap5->depth, val, &ap5->hist, ddif1i);
			temp1 = temp2 = temp3 = x;	/* n_out_1 */
			do_delay(&temp1, od5l->buf, od5l->size, &od5l->index);
			outl -= temp1;	/* left output 5 */
			do_delay(&temp2, od1r->buf, od1r->size, &od1r->index);
			outr += temp2;	/* right output 1 */
			do_delay(&temp3, od2r->buf, od2r->size, &od2r->index);
			outr += temp3;	/* right output 2 */
			do_delay(&x, td1->buf, td1->size, &td1->index);
			sample_filter_left(lpf2, &x);
			temp1 = temp2 = x;	/* n_out_2 */
			do_delay(&temp1, od6l->buf, od6l->size, &od6l->index);
			outl -= temp1;	/* left output 6 */
			do_delay(&temp2, od3r->buf, od3r->size, &od3r->index);
			outr -= temp2;	/* right output 3 */
			x = imuldiv24(x, decayi);
			do_allpass(&x, ap6->buf, ap6->size, &ap6->index, ddif2i);
			temp1 = temp2 = x;	/* n_out_3 */
			do_delay(&temp1, od7l->buf, od7l->size, &od7l->index);
			outl -= temp1;	/* left output 7 */
			do_delay(&temp2, od4r->buf, od4r->size, &od4r->index);
			outr += temp2;	/* right output 4 */
			do_delay(&x, td2->buf, td2->size, &td2->index);
			t1 = x;

			xd += imuldiv24(t1, decayi);
			val = do_lfo(lfo1d);
			do_mod_allpass(&x, ap5d->buf, ap5d->size, &ap5d->rindex, &ap5d->windex,
				ap5d->ndelay, ap5d->depth, val, &ap5d->hist, ddif1i);
			temp1 = temp2 = temp3 = xd;	/* n_out_4 */
			do_delay(&temp1, od1l->buf, od1l->size, &od1l->index);
			outl += temp1;	/* left output 1 */
			do_delay(&temp2, od2l->buf, od2l->size, &od2l->index);
			outl += temp2;	/* left output 2 */
			do_delay(&temp3, od6r->buf, od6r->size, &od6r->index);
			outr -= temp3;	/* right output 6 */
			do_delay(&xd, td1d->buf, td1d->size, &td1d->index);
			sample_filter_right(lpf2, &xd);
			temp1 = temp2 = xd;	/* n_out_5 */
			do_delay(&temp1, od3l->buf, od3l->size, &od3l->index);
			outl -= temp1;	/* left output 3 */
			do_delay(&temp2, od6r->buf, od6r->size, &od6r->index);
			outr -= temp2;	/* right output 6 */
			xd = imuldiv24(xd, decayi);
			do_allpass(&xd, ap6d->buf, ap6d->size, &ap6d->index, ddif2i);
			temp1 = temp2 = xd;	/* n_out_6 */
			do_delay(&temp1, od4l->buf, od4l->size, &od4l->index);
			outl += temp1;	/* left output 4 */
			do_delay(&temp2, od7r->buf, od7r->size, &od7r->index);
			outr -= temp2;	/* right output 7 */
			do_delay(&xd, td2d->buf, td2d->size, &td2d->index);
			t1d = xd;

			histL = outl;
			histR = outr;
			buf[i] = imuldiv24(erL, leveler) + imuldiv24(histL, levelrv);
			buf[++i] = imuldiv24(erR, leveler) + imuldiv24(histR, levelrv);
		}
		info->t1 = t1, info->t1d = t1d, info->histL = histL, info->histR = histR;
		break;
	case CH_MIX_STEREO:
		for (i = 0; i < count; i++)
		{
			outr = outl = 0;
			erL = imuldiv24(imuldiv24(buf[i] + buf[i + 1], DIV_MIX_LEVELi), wet) + imuldiv24(imuldiv24(histL + histR, DIV_MIX_LEVELi), feedback);

			do_delay(&erL, pd->buf, pd->size, &pd->index);
			sample_filter_left(lpf1, &erL);
			do_allpass(&erL, ap1->buf, ap1->size, &ap1->index, idif1i);
			do_allpass(&erL, ap2->buf, ap2->size, &ap2->index, idif1i);
			do_allpass(&erL, ap3->buf, ap3->size, &ap3->index, idif2i);
			do_allpass(&erL, ap4->buf, ap4->size, &ap4->index, idif2i);

			x = erL;
			/* tank structure */
			xd = x;
			x += imuldiv24(t1d, decayi);
			val = do_lfo(lfo1);
			do_mod_allpass(&x, ap5->buf, ap5->size, &ap5->rindex, &ap5->windex,
				ap5->ndelay, ap5->depth, val, &ap5->hist, ddif1i);
			temp1 = temp2 = temp3 = x;	/* n_out_1 */
			do_delay(&temp1, od5l->buf, od5l->size, &od5l->index);
			outl -= temp1;	/* left output 5 */
			do_delay(&temp2, od1r->buf, od1r->size, &od1r->index);
			outr += temp2;	/* right output 1 */
			do_delay(&temp3, od2r->buf, od2r->size, &od2r->index);
			outr += temp3;	/* right output 2 */
			do_delay(&x, td1->buf, td1->size, &td1->index);
			sample_filter_left(lpf2, &x);
			temp1 = temp2 = x;	/* n_out_2 */
			do_delay(&temp1, od6l->buf, od6l->size, &od6l->index);
			outl -= temp1;	/* left output 6 */
			do_delay(&temp2, od3r->buf, od3r->size, &od3r->index);
			outr -= temp2;	/* right output 3 */
			x = imuldiv24(x, decayi);
			do_allpass(&x, ap6->buf, ap6->size, &ap6->index, ddif2i);
			temp1 = temp2 = x;	/* n_out_3 */
			do_delay(&temp1, od7l->buf, od7l->size, &od7l->index);
			outl -= temp1;	/* left output 7 */
			do_delay(&temp2, od4r->buf, od4r->size, &od4r->index);
			outr += temp2;	/* right output 4 */
			do_delay(&x, td2->buf, td2->size, &td2->index);
			t1 = x;

			xd += imuldiv24(t1, decayi);
			val = do_lfo(lfo1d);
			do_mod_allpass(&x, ap5d->buf, ap5d->size, &ap5d->rindex, &ap5d->windex,
				ap5d->ndelay, ap5d->depth, val, &ap5d->hist, ddif1i);
			temp1 = temp2 = temp3 = xd;	/* n_out_4 */
			do_delay(&temp1, od1l->buf, od1l->size, &od1l->index);
			outl += temp1;	/* left output 1 */
			do_delay(&temp2, od2l->buf, od2l->size, &od2l->index);
			outl += temp2;	/* left output 2 */
			do_delay(&temp3, od6r->buf, od6r->size, &od6r->index);
			outr -= temp3;	/* right output 6 */
			do_delay(&xd, td1d->buf, td1d->size, &td1d->index);
			sample_filter_right(lpf2, &xd);
			temp1 = temp2 = xd;	/* n_out_5 */
			do_delay(&temp1, od3l->buf, od3l->size, &od3l->index);
			outl -= temp1;	/* left output 3 */
			do_delay(&temp2, od6r->buf, od6r->size, &od6r->index);
			outr -= temp2;	/* right output 6 */
			xd = imuldiv24(xd, decayi);
			do_allpass(&xd, ap6d->buf, ap6d->size, &ap6d->index, ddif2i);
			temp1 = temp2 = xd;	/* n_out_6 */
			do_delay(&temp1, od4l->buf, od4l->size, &od4l->index);
			outl += temp1;	/* left output 4 */
			do_delay(&temp2, od7r->buf, od7r->size, &od7r->index);
			outr -= temp2;	/* right output 7 */
			do_delay(&xd, td2d->buf, td2d->size, &td2d->index);
			t1d = xd;

			histL = outl;
			histR = outr;
			buf[i] = imuldiv24(erL, leveler) + imuldiv24(histL, levelrv);
			buf[++i] = imuldiv24(erL, leveler) + imuldiv24(histR, levelrv);
		}
		info->t1 = t1, info->t1d = t1d, info->histL = histL, info->histR = histR;
		break;
	case CH_MIX_MONO:
		for (i = 0; i < count; i++)
		{
			outr = outl = 0;
			erL = imuldiv24(imuldiv24(buf[i] + buf[i + 1], DIV_MIX_LEVELi), wet) + imuldiv24(histL, feedback);

			do_delay(&erL, pd->buf, pd->size, &pd->index);
			sample_filter_left(lpf1, &erL);
			do_allpass(&erL, ap1->buf, ap1->size, &ap1->index, idif1i);
			do_allpass(&erL, ap2->buf, ap2->size, &ap2->index, idif1i);
			do_allpass(&erL, ap3->buf, ap3->size, &ap3->index, idif2i);
			do_allpass(&erL, ap4->buf, ap4->size, &ap4->index, idif2i);

			x = erL;
			/* tank structure */
			xd = x;
			x += imuldiv24(t1d, decayi);
			val = do_lfo(lfo1);
			do_mod_allpass(&x, ap5->buf, ap5->size, &ap5->rindex, &ap5->windex,
				ap5->ndelay, ap5->depth, val, &ap5->hist, ddif1i);
			temp1 = temp2 = temp3 = x;	/* n_out_1 */
			do_delay(&temp1, od5l->buf, od5l->size, &od5l->index);
			outl -= temp1;	/* left output 5 */
			do_delay(&temp2, od1r->buf, od1r->size, &od1r->index);
			outr += temp2;	/* right output 1 */
			do_delay(&temp3, od2r->buf, od2r->size, &od2r->index);
			outr += temp3;	/* right output 2 */
			do_delay(&x, td1->buf, td1->size, &td1->index);
			sample_filter_left(lpf2, &x);
			temp1 = temp2 = x;	/* n_out_2 */
			do_delay(&temp1, od6l->buf, od6l->size, &od6l->index);
			outl -= temp1;	/* left output 6 */
			do_delay(&temp2, od3r->buf, od3r->size, &od3r->index);
			outr -= temp2;	/* right output 3 */
			x = imuldiv24(x, decayi);
			do_allpass(&x, ap6->buf, ap6->size, &ap6->index, ddif2i);
			temp1 = temp2 = x;	/* n_out_3 */
			do_delay(&temp1, od7l->buf, od7l->size, &od7l->index);
			outl -= temp1;	/* left output 7 */
			do_delay(&temp2, od4r->buf, od4r->size, &od4r->index);
			outr += temp2;	/* right output 4 */
			do_delay(&x, td2->buf, td2->size, &td2->index);
			t1 = x;

			xd += imuldiv24(t1, decayi);
			val = do_lfo(lfo1d);
			do_mod_allpass(&x, ap5d->buf, ap5d->size, &ap5d->rindex, &ap5d->windex,
				ap5d->ndelay, ap5d->depth, val, &ap5d->hist, ddif1i);
			temp1 = temp2 = temp3 = xd;	/* n_out_4 */
			do_delay(&temp1, od1l->buf, od1l->size, &od1l->index);
			outl += temp1;	/* left output 1 */
			do_delay(&temp2, od2l->buf, od2l->size, &od2l->index);
			outl += temp2;	/* left output 2 */
			do_delay(&temp3, od6r->buf, od6r->size, &od6r->index);
			outr -= temp3;	/* right output 6 */
			do_delay(&xd, td1d->buf, td1d->size, &td1d->index);
			sample_filter_right(lpf2, &xd);
			temp1 = temp2 = xd;	/* n_out_5 */
			do_delay(&temp1, od3l->buf, od3l->size, &od3l->index);
			outl -= temp1;	/* left output 3 */
			do_delay(&temp2, od6r->buf, od6r->size, &od6r->index);
			outr -= temp2;	/* right output 6 */
			xd = imuldiv24(xd, decayi);
			do_allpass(&xd, ap6d->buf, ap6d->size, &ap6d->index, ddif2i);
			temp1 = temp2 = xd;	/* n_out_6 */
			do_delay(&temp1, od4l->buf, od4l->size, &od4l->index);
			outl += temp1;	/* left output 4 */
			do_delay(&temp2, od7r->buf, od7r->size, &od7r->index);
			outr -= temp2;	/* right output 7 */
			do_delay(&xd, td2d->buf, td2d->size, &td2d->index);
			t1d = xd;

			histL = outl;
			buf[i] = imuldiv24(erL, leveler) + imuldiv24(histL, levelrv);
			++i;
		}
		info->t1 = t1, info->t1d = t1d, info->histL = histL;
		break;
	}
}

#else /* floating-point implementation */
static void do_plate_reverb(DATA_T *buf, int32 count, InfoPlateReverb *info)
{
	int32 i;
	DATA_T x, xd, val, outl, outr, temp1, temp2, temp3;
	simple_delay *pd = &(info->pd), *pdR = &(info->pdR), *od1l = &(info->od1l), *od2l = &(info->od2l),
		*od3l = &(info->od3l), *od4l = &(info->od4l), *od5l = &(info->od5l),
		*od6l = &(info->od6l), *od1r = &(info->od1r), *od2r = &(info->od2r),
		*od3r = &(info->od3r), *od4r = &(info->od4r), *od5r = &(info->od5r),
		*od7r = &(info->od7r), *od7l = &(info->od7l), *od6r = &(info->od6r),
		*td1 = &(info->td1), *td2 = &(info->td2), *td1d = &(info->td1d), *td2d = &(info->td2d);
	allpass *ap1 = &(info->ap1), *ap2 = &(info->ap2), *ap3 = &(info->ap3), *ap4 = &(info->ap4),
		*ap1R = &(info->ap1R), *ap2R = &(info->ap2R), *ap3R = &(info->ap3R), *ap4R = &(info->ap4R),
		*ap6 = &(info->ap6), *ap6d = &(info->ap6d);
	mod_allpass *ap5 = &(info->ap5), *ap5d = &(info->ap5d);
	lfo *lfo1 = &(info->lfo1), *lfo1d = &(info->lfo1d);
	FilterCoefficients *lpf1 = &(info->lpf1), *lpf2 = &(info->lpf2);
	FLOAT_T dt1 = info->dt1, dt1d = info->dt1d;
	FLOAT_T decay = info->decay, ddif1 = info->ddif1, ddif2 = info->ddif2,
		idif1 = info->idif1, idif2 = info->idif2;
	DATA_T erL, erR;
	DATA_T histL = info->histL, histR = info->histR;
	FLOAT_T leveler = info->leveler, levelrv = info->levelrv, feedback = info->feedback, wet = info->wet;
	double t;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		info->feedback = PLATE_WET * info->rev_feedback * PLATE_FEEDBACK;
		info->levelrv = info->rev_level * PLATE_RV_LEVEL;
		info->leveler = info->er_level * PLATE_ER_LEVEL;
		info->wet = PLATE_WET * info->rev_wet * ext_plate_reverb_level;

		init_lfo(lfo1, 1.30, LFO_SINE, 0);
		init_lfo(lfo1d, 1.30, LFO_SINE, 0);
		t = (info->rev_time_sec * ext_plate_reverb_time) / reverb_time_table[64] - 1.0;
		t = 1.0 + t / 2;
		set_delay(pd, info->er_time_ms * playmode_rate_ms);
		set_delay(pdR, info->er_time_ms * playmode_rate_ms);
		set_delay(td1, get_plate_delay(4453, t)),
		set_delay(td1d, get_plate_delay(4217, t));
		set_delay(td2, get_plate_delay(3720, t));
		set_delay(td2d, get_plate_delay(3163, t));
		set_delay(od1l, get_plate_delay(266, t));
		set_delay(od2l, get_plate_delay(2974, t));
		set_delay(od3l, get_plate_delay(1913, t));
		set_delay(od4l, get_plate_delay(1996, t));
		set_delay(od5l, get_plate_delay(1990, t));
		set_delay(od6l, get_plate_delay(187, t));
		set_delay(od7l, get_plate_delay(1066, t));
		set_delay(od1r, get_plate_delay(353, t));
		set_delay(od2r, get_plate_delay(3627, t));
		set_delay(od3r, get_plate_delay(1228, t));
		set_delay(od4r, get_plate_delay(2673, t));
		set_delay(od5r, get_plate_delay(2111, t));
		set_delay(od6r, get_plate_delay(335, t));
		set_delay(od7r, get_plate_delay(121, t));
		set_allpass(ap1, get_plate_delay(142, t), info->rev_diff * PLATE_INPUT_DIFFUSION1);
		set_allpass(ap2, get_plate_delay(107, t), info->rev_diff * PLATE_INPUT_DIFFUSION1);
		set_allpass(ap3, get_plate_delay(379, t), info->rev_diff * PLATE_INPUT_DIFFUSION2);
		set_allpass(ap4, get_plate_delay(277, t), info->rev_diff * PLATE_INPUT_DIFFUSION2);
		set_allpass(ap1R, get_plate_delay(142, t), info->rev_diff * PLATE_INPUT_DIFFUSION1);
		set_allpass(ap2R, get_plate_delay(107, t), info->rev_diff * PLATE_INPUT_DIFFUSION1);
		set_allpass(ap3R, get_plate_delay(379, t), info->rev_diff * PLATE_INPUT_DIFFUSION2);
		set_allpass(ap4R, get_plate_delay(277, t), info->rev_diff * PLATE_INPUT_DIFFUSION2);
		set_allpass(ap6, get_plate_delay(1800, t), info->rev_diff * PLATE_DECAY_DIFFUSION2);
		set_allpass(ap6d, get_plate_delay(2656, t), info->rev_diff * PLATE_DECAY_DIFFUSION2);
		set_mod_allpass(ap5, get_plate_delay(672, t), get_plate_delay(16, t), info->rev_diff * PLATE_DECAY_DIFFUSION1);
		set_mod_allpass(ap5d, get_plate_delay(908, t), get_plate_delay(16, t), info->rev_diff * PLATE_DECAY_DIFFUSION1);
///r
		init_sample_filter(lpf1, (FLOAT_T)44100.0 * PLATE_BANDWIDTH, 0, FILTER_LPF6);
		init_sample_filter(lpf2, (FLOAT_T)44100.0 * (1.0 - info->rev_damp), 0, FILTER_LPF6);
//		lpf1->a = PLATE_BANDWIDTH; lpf2->a = 1.0 - PLATE_DAMPING;
//		init_filter_lowpass1(lpf1);
//		init_filter_lowpass1(lpf2);
		//lpf1->freq = (FLOAT_T)44100.0 * PLATE_BANDWIDTH;
		//lpf2->freq = (FLOAT_T)44100.0 * (1.0 - info->rev_damp);
		//calc_filter_lowpass1(lpf1);
		//calc_filter_lowpass1(lpf1R);
		//calc_filter_lowpass1(lpf2);
		//init_filter_lowpass1(lpf1);
		//init_filter_lowpass1(lpf1R);
		//init_filter_lowpass1(lpf2);
		info->t1 = info->t1d = 0;
		info->decay = PLATE_DECAY;
		info->decayi = TIM_FSCALE(info->decay, 24);
		info->ddif1 = info->rev_diff * PLATE_DECAY_DIFFUSION1;
		info->ddif1i = TIM_FSCALE(info->ddif1, 24);
		info->ddif2 = info->rev_diff * PLATE_DECAY_DIFFUSION2;
		info->ddif2i = TIM_FSCALE(info->ddif2, 24);
		info->idif1 = info->rev_diff * PLATE_INPUT_DIFFUSION1;
		info->idif1i = TIM_FSCALE(info->idif1, 24);
		info->idif2 = info->rev_diff * PLATE_INPUT_DIFFUSION2;
		info->idif2i = TIM_FSCALE(info->idif2, 24);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_delay(pd);	free_delay(pdR);	free_delay(td1); free_delay(td1d); free_delay(td2);
		free_delay(td2d); free_delay(od1l); free_delay(od2l); free_delay(od3l);
		free_delay(od4l); free_delay(od5l); free_delay(od6l); free_delay(od7l);
		free_delay(od1r); free_delay(od2r);	free_delay(od3r); free_delay(od4r);
		free_delay(od5r); free_delay(od6r);	free_delay(od7r);
		free_allpass(ap1); free_allpass(ap2); free_allpass(ap3); free_allpass(ap4); 
		free_allpass(ap1R); free_allpass(ap2R); free_allpass(ap3R); free_allpass(ap4R);
		free_allpass(ap6); free_allpass(ap6d);	free_mod_allpass(ap5); free_mod_allpass(ap5d);
		return;
	}
	switch(info->mode){
	case CH_STEREO:
		for (i = 0; i < count; i++)
		{
			outr = outl = 0;
			erL = buf[i] * wet + histL * feedback;
			erR = buf[i + 1] * wet + histR * feedback;

			do_delay(&erL, pd->buf, pd->size, &pd->index);
			sample_filter_left(lpf1, &erL);
			do_allpass(&erL, ap1->buf, ap1->size, &ap1->index, idif1);
			do_allpass(&erL, ap2->buf, ap2->size, &ap2->index, idif1);
			do_allpass(&erL, ap3->buf, ap3->size, &ap3->index, idif2);
			do_allpass(&erL, ap4->buf, ap4->size, &ap4->index, idif2);
			do_delay(&erR, pd->buf, pd->size, &pd->index);
			sample_filter_right(lpf1, &erR);
			do_allpass(&erR, ap1R->buf, ap1R->size, &ap1R->index, idif1);
			do_allpass(&erR, ap2R->buf, ap2R->size, &ap2R->index, idif1);
			do_allpass(&erR, ap3R->buf, ap3R->size, &ap3R->index, idif2);
			do_allpass(&erR, ap4R->buf, ap4R->size, &ap4R->index, idif2);

			x = (erL + erR) * DIV_MIX_LEVEL;
			/* tank structure */
			xd = x;
			x += dt1d * decay;
			val = do_lfo(lfo1);
			do_mod_allpass(&x, ap5->buf, ap5->size, &ap5->rindex, &ap5->windex,
				ap5->ndelay, ap5->depth, val, &ap5->hist, ddif1);
			temp1 = temp2 = temp3 = x;	/* n_out_1 */
			do_delay(&temp1, od5l->buf, od5l->size, &od5l->index);
			outl -= temp1;	/* left output 5 */
			do_delay(&temp2, od1r->buf, od1r->size, &od1r->index);
			outr += temp2;	/* right output 1 */
			do_delay(&temp3, od2r->buf, od2r->size, &od2r->index);
			outr += temp3;	/* right output 2 */
			do_delay(&x, td1->buf, td1->size, &td1->index);
			sample_filter_left(lpf2, &x);
			temp1 = temp2 = x;	/* n_out_2 */
			do_delay(&temp1, od6l->buf, od6l->size, &od6l->index);
			outl -= temp1;	/* left output 6 */
			do_delay(&temp2, od3r->buf, od3r->size, &od3r->index);
			outr -= temp2;	/* right output 3 */
			x *= decay;
			do_allpass(&x, ap6->buf, ap6->size, &ap6->index, ddif2);
			temp1 = temp2 = x;	/* n_out_3 */
			do_delay(&temp1, od7l->buf, od7l->size, &od7l->index);
			outl -= temp1;	/* left output 7 */
			do_delay(&temp2, od4r->buf, od4r->size, &od4r->index);
			outr += temp2;	/* right output 4 */
			do_delay(&x, td2->buf, td2->size, &td2->index);
			dt1 = x;

			xd += dt1 * decay;
			val = do_lfo(lfo1d);
			do_mod_allpass(&x, ap5d->buf, ap5d->size, &ap5d->rindex, &ap5d->windex,
				ap5d->ndelay, ap5d->depth, val, &ap5d->hist, ddif1);
			temp1 = temp2 = temp3 = xd;	/* n_out_4 */
			do_delay(&temp1, od1l->buf, od1l->size, &od1l->index);
			outl += temp1;	/* left output 1 */
			do_delay(&temp2, od2l->buf, od2l->size, &od2l->index);
			outl += temp2;	/* left output 2 */
			do_delay(&temp3, od6r->buf, od6r->size, &od6r->index);
			outr -= temp3;	/* right output 6 */
			do_delay(&xd, td1d->buf, td1d->size, &td1d->index);
			sample_filter_right(lpf2, &xd);
			temp1 = temp2 = xd;	/* n_out_5 */
			do_delay(&temp1, od3l->buf, od3l->size, &od3l->index);
			outl -= temp1;	/* left output 3 */
			do_delay(&temp2, od6r->buf, od6r->size, &od6r->index);
			outr -= temp2;	/* right output 6 */
			xd *= decay;
			do_allpass(&xd, ap6d->buf, ap6d->size, &ap6d->index, ddif2);
			temp1 = temp2 = xd;	/* n_out_6 */
			do_delay(&temp1, od4l->buf, od4l->size, &od4l->index);
			outl += temp1;	/* left output 4 */
			do_delay(&temp2, od7r->buf, od7r->size, &od7r->index);
			outr -= temp2;	/* right output 7 */
			do_delay(&xd, td2d->buf, td2d->size, &td2d->index);
			dt1d = xd;

			histL = outl;
			histR = outr;
			buf[i] = erL * leveler + histL * levelrv;
			buf[++i] = erR * leveler + histR * levelrv;
		}
		info->dt1 = dt1, info->dt1d = dt1d, info->histL = histL, info->histR = histR;
		break;
	case CH_MIX_STEREO:
		for (i = 0; i < count; i++)
		{
			outr = outl = 0;
			erL = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL * wet + (histL + histR) * DIV_MIX_LEVEL * feedback;
			
			do_delay(&erL, pd->buf, pd->size, &pd->index);
			sample_filter_left(lpf1, &erL);
			do_allpass(&erL, ap1->buf, ap1->size, &ap1->index, idif1);
			do_allpass(&erL, ap2->buf, ap2->size, &ap2->index, idif1);
			do_allpass(&erL, ap3->buf, ap3->size, &ap3->index, idif2);
			do_allpass(&erL, ap4->buf, ap4->size, &ap4->index, idif2);

			x = erL;
			/* tank structure */
			xd = x;
			x += dt1d * decay;
			val = do_lfo(lfo1);
			do_mod_allpass(&x, ap5->buf, ap5->size, &ap5->rindex, &ap5->windex,
				ap5->ndelay, ap5->depth, val, &ap5->hist, ddif1);
			temp1 = temp2 = temp3 = x;	/* n_out_1 */
			do_delay(&temp1, od5l->buf, od5l->size, &od5l->index);
			outl -= temp1;	/* left output 5 */
			do_delay(&temp2, od1r->buf, od1r->size, &od1r->index);
			outr += temp2;	/* right output 1 */
			do_delay(&temp3, od2r->buf, od2r->size, &od2r->index);
			outr += temp3;	/* right output 2 */
			do_delay(&x, td1->buf, td1->size, &td1->index);
			sample_filter_left(lpf2, &x);
			temp1 = temp2 = x;	/* n_out_2 */
			do_delay(&temp1, od6l->buf, od6l->size, &od6l->index);
			outl -= temp1;	/* left output 6 */
			do_delay(&temp2, od3r->buf, od3r->size, &od3r->index);
			outr -= temp2;	/* right output 3 */
			x *= decay;
			do_allpass(&x, ap6->buf, ap6->size, &ap6->index, ddif2);
			temp1 = temp2 = x;	/* n_out_3 */
			do_delay(&temp1, od7l->buf, od7l->size, &od7l->index);
			outl -= temp1;	/* left output 7 */
			do_delay(&temp2, od4r->buf, od4r->size, &od4r->index);
			outr += temp2;	/* right output 4 */
			do_delay(&x, td2->buf, td2->size, &td2->index);
			dt1 = x;

			xd += dt1 * decay;
			val = do_lfo(lfo1d);
			do_mod_allpass(&x, ap5d->buf, ap5d->size, &ap5d->rindex, &ap5d->windex,
				ap5d->ndelay, ap5d->depth, val, &ap5d->hist, ddif1);
			temp1 = temp2 = temp3 = xd;	/* n_out_4 */
			do_delay(&temp1, od1l->buf, od1l->size, &od1l->index);
			outl += temp1;	/* left output 1 */
			do_delay(&temp2, od2l->buf, od2l->size, &od2l->index);
			outl += temp2;	/* left output 2 */
			do_delay(&temp3, od6r->buf, od6r->size, &od6r->index);
			outr -= temp3;	/* right output 6 */
			do_delay(&xd, td1d->buf, td1d->size, &td1d->index);
			sample_filter_right(lpf2, &xd);
			temp1 = temp2 = xd;	/* n_out_5 */
			do_delay(&temp1, od3l->buf, od3l->size, &od3l->index);
			outl -= temp1;	/* left output 3 */
			do_delay(&temp2, od6r->buf, od6r->size, &od6r->index);
			outr -= temp2;	/* right output 6 */
			xd *= decay;
			do_allpass(&xd, ap6d->buf, ap6d->size, &ap6d->index, ddif2);
			temp1 = temp2 = xd;	/* n_out_6 */
			do_delay(&temp1, od4l->buf, od4l->size, &od4l->index);
			outl += temp1;	/* left output 4 */
			do_delay(&temp2, od7r->buf, od7r->size, &od7r->index);
			outr -= temp2;	/* right output 7 */
			do_delay(&xd, td2d->buf, td2d->size, &td2d->index);
			dt1d = xd;
			
			histL = outl;
			histR = outr;
			buf[i] = erL * leveler + histL * levelrv;
			buf[++i] = erL * leveler + histR * levelrv;
		}
		info->dt1 = dt1, info->dt1d = dt1d, info->histL = histL, info->histR = histR;
		break;
	case CH_MIX_MONO:
		for (i = 0; i < count; i++)
		{
			outr = outl = 0;
			erL = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL * wet + histL * feedback;
			
			do_delay(&erL, pd->buf, pd->size, &pd->index);
			sample_filter_left(lpf1, &erL);
			do_allpass(&erL, ap1->buf, ap1->size, &ap1->index, idif1);
			do_allpass(&erL, ap2->buf, ap2->size, &ap2->index, idif1);
			do_allpass(&erL, ap3->buf, ap3->size, &ap3->index, idif2);
			do_allpass(&erL, ap4->buf, ap4->size, &ap4->index, idif2);
			
			x = erL;
			/* tank structure */
			xd = x;
			x += dt1d * decay;
			val = do_lfo(lfo1);
			do_mod_allpass(&x, ap5->buf, ap5->size, &ap5->rindex, &ap5->windex,
				ap5->ndelay, ap5->depth, val, &ap5->hist, ddif1);
			temp1 = temp2 = temp3 = x;	/* n_out_1 */
			do_delay(&temp1, od5l->buf, od5l->size, &od5l->index);
			outl -= temp1;	/* left output 5 */
			do_delay(&temp2, od1r->buf, od1r->size, &od1r->index);
			outr += temp2;	/* right output 1 */
			do_delay(&temp3, od2r->buf, od2r->size, &od2r->index);
			outr += temp3;	/* right output 2 */
			do_delay(&x, td1->buf, td1->size, &td1->index);
			sample_filter_left(lpf2, &x);
			temp1 = temp2 = x;	/* n_out_2 */
			do_delay(&temp1, od6l->buf, od6l->size, &od6l->index);
			outl -= temp1;	/* left output 6 */
			do_delay(&temp2, od3r->buf, od3r->size, &od3r->index);
			outr -= temp2;	/* right output 3 */
			x *= decay;
			do_allpass(&x, ap6->buf, ap6->size, &ap6->index, ddif2);
			temp1 = temp2 = x;	/* n_out_3 */
			do_delay(&temp1, od7l->buf, od7l->size, &od7l->index);
			outl -= temp1;	/* left output 7 */
			do_delay(&temp2, od4r->buf, od4r->size, &od4r->index);
			outr += temp2;	/* right output 4 */
			do_delay(&x, td2->buf, td2->size, &td2->index);
			dt1 = x;

			xd += dt1 * decay;
			val = do_lfo(lfo1d);
			do_mod_allpass(&x, ap5d->buf, ap5d->size, &ap5d->rindex, &ap5d->windex,
				ap5d->ndelay, ap5d->depth, val, &ap5d->hist, ddif1);
			temp1 = temp2 = temp3 = xd;	/* n_out_4 */
			do_delay(&temp1, od1l->buf, od1l->size, &od1l->index);
			outl += temp1;	/* left output 1 */
			do_delay(&temp2, od2l->buf, od2l->size, &od2l->index);
			outl += temp2;	/* left output 2 */
			do_delay(&temp3, od6r->buf, od6r->size, &od6r->index);
			outr -= temp3;	/* right output 6 */
			do_delay(&xd, td1d->buf, td1d->size, &td1d->index);
			sample_filter_right(lpf2, &xd);
			temp1 = temp2 = xd;	/* n_out_5 */
			do_delay(&temp1, od3l->buf, od3l->size, &od3l->index);
			outl -= temp1;	/* left output 3 */
			do_delay(&temp2, od6r->buf, od6r->size, &od6r->index);
			outr -= temp2;	/* right output 6 */
			xd *= decay;
			do_allpass(&xd, ap6d->buf, ap6d->size, &ap6d->index, ddif2);
			temp1 = temp2 = xd;	/* n_out_6 */
			do_delay(&temp1, od4l->buf, od4l->size, &od4l->index);
			outl += temp1;	/* left output 4 */
			do_delay(&temp2, od7r->buf, od7r->size, &od7r->index);
			outr -= temp2;	/* right output 7 */
			do_delay(&xd, td2d->buf, td2d->size, &td2d->index);
			dt1d = xd;
			
			histL = outl;
			buf[i] = erL * leveler + histL * levelrv;
			++i;
		}
		info->dt1 = dt1, info->dt1d = dt1d, info->histL = histL, info->histR = histR;
		break;
	}
}
#endif /* OPT_MODE != 0 */


/*                   */
/*   Delay Effect    */
/*                   */

// Delay3
/*
use
GS System Effect Delay
GS System Effect Reverb (RevType Normal Delay, Panning Delay)
DELAY MACRO, REVERB_MACRO のデフォルト値から数パターンのタイプに最適化
*/ 
#define DELAY3_CH_C         0 // center
#define DELAY3_CH_L         1 // left
#define DELAY3_CH_R         2 // right
#define DELAY3_TYPE_NORMAL  0
#define DELAY3_TYPE_PANNING 1
#define DELAY3_TYPE_3TAP    2
#define DELAY3_FEEDBACK (0.6783) // def 0.969

/*! initialize Delay3 Effect; this implementation is specialized for system effect. */
static void init_delay3(InfoDelay3 *info)
{
	int i;
	int32 x;

	for (i = 0; i < 3; i++) {
		info->size[i] = info->time_ms[i] * playmode_rate_ms;
	}
	x = info->size[0];	/* find maximum value */
	for (i = 1; i < 3; i++) {
		if (info->size[i] > x) {x = info->size[i];}
	}
	x += 1;	/* allowance */
	set_delay(&(info->delayL), x);
	set_delay(&(info->delayR), x);
	for (i = 0; i < 3; i++) {
		info->index[i] = (x - info->size[i]) % x;	/* set start-point */
		if(info->index[i] >= info->size[i]) {
			info->index[i] = (info->size[i] == 0) ? 0 : info->size[i] - 1;
		}
		info->leveli[i] = TIM_FSCALE(info->level[i], 24);
	}
	info->feedbackd = info->feedback * DELAY3_FEEDBACK;
	info->feedbacki = TIM_FSCALE(info->feedbackd, 24);
	info->send_reverbi = TIM_FSCALE(info->send_reverb, 24);
	if(info->delay_type == DELAY3_TYPE_PANNING){ // panning (cross
		info->ptrL = (DATA_T *)info->delayR.buf;
		info->ptrR = (DATA_T *)info->delayL.buf;
	}else{ // normal, 3tap
		info->ptrL = (DATA_T *)info->delayL.buf;
		info->ptrR = (DATA_T *)info->delayR.buf;
	}
	// optimize
	if(info->level[DELAY3_CH_C]){
		if(info->level[DELAY3_CH_L] || info->level[DELAY3_CH_R])
			info->opt_mode = 0; // 3tap all
		else
			info->opt_mode = 1; // 3tap center only
	}else{ // 3tap no center
		if(info->size[DELAY3_CH_C] != info->size[DELAY3_CH_L] || info->size[DELAY3_CH_L] != info->size[DELAY3_CH_R])
			info->opt_mode = 2; // 3tap no center diff time
		else
			info->opt_mode = 3; // 3tap no center same time // stereo LR same time
	}

}

static void free_delay3(InfoDelay3 *info)
{
	free_delay(&(info->delayL));
	free_delay(&(info->delayR));
}

/*! Delay3 Effect; this implementation is specialized for system effect. */
#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void do_delay3(int32 *buf, int32 count, InfoDelay3 *info)
{
	int32 i, x;
	simple_delay *delayL = &(info->delayL), *delayR = &(info->delayR);
	int32 *bufL = delayL->buf, *bufR = delayR->buf;
	int32 *ptrL = (int32 *)info->ptrL, *ptrR = (int32 *)info->ptrR;
	int32 buf_index = delayL->index, buf_size = delayL->size;
	int32 index0 = info->index[0], index1 = info->index[1], index2 = info->index[2];
	int32 level0i = info->leveli[0], level1i = info->leveli[1], level2i = info->leveli[2],
		feedbacki = info->feedbacki;

	if (count == MAGIC_INIT_EFFECT_INFO) {
		init_delay3(info);
		return;
	} else if (count == MAGIC_FREE_EFFECT_INFO) {
		free_delay3(info);
		return;
	} else if(count <= 0) {
		return;
	}
	switch(info->opt_mode){
	default:
	case 0: // 3tap all
		for (i = 0; i < count; i++)
		{
			int32 outC, out1L = ptrL[index0], out1R = ptrR[index0], out2L = ptrL[index1], out2R = ptrR[index2];
			// ch center
			outC = imuldiv24(imuldiv24(out1L + out1R, DIV_MIX_LEVEL), level0i); // center
			// ch left
			bufL[buf_index] = buf[i] + imuldiv24(out1L, feedbacki); // center delay feedback
			buf[i] = imuldiv24(out2L, level1i) + outC;
			// ch right
			++i;
			bufR[buf_index] = buf[i] + imuldiv24(out1R, feedbacki); // center delay feedback
			buf[i] = imuldiv24(out2R, level2i) + outC;
			// index
			if (++index0 >= buf_size) { index0 = 0; }
			if (++index1 >= buf_size) { index1 = 0; }
			if (++index2 >= buf_size) { index2 = 0; }
			if (++buf_index >= buf_size) { buf_index = 0; }
		}
		info->index[0] = index0, info->index[1] = index1, info->index[2] = index2;
		delayL->index = buf_index;
		break;
	case 1: // 3tap center only
		for (i = 0; i < count; i++)
		{
			int32 outC, out1L = ptrL[index0], out1R = ptrR[index0];
			// ch center
			outC = imuldiv24(imuldiv24(out1L + out1R, DIV_MIX_LEVEL), level0i); // center
			// ch left
			bufL[buf_index] = buf[i] + imuldiv24(out1L, feedbacki); // center delay feedback
			buf[i] = outC;
			// ch right
			++i;
			bufR[buf_index] = buf[i] + imuldiv24(out1R, feedbacki); // center delay feedback
			buf[i] = outC;
			// index
			if (++index0 >= buf_size) { index0 = 0; }
			if (++buf_index >= buf_size) { buf_index = 0; }
		}
		info->index[0] = index0;
		delayL->index = buf_index;
		break;
	case 2: // 3tap no center diff time
		for (i = 0; i < count; i++)
		{
			int32 out1L = ptrL[index0], out1R = ptrR[index0], out2L = ptrL[index1], out2R = ptrR[index2];
			// ch left
			bufL[buf_index] = buf[i] + imuldiv24(out1L, feedbacki); // center delay feedback
			buf[i] = imuldiv24(out2L, level1i);
			// ch right
			++i;
			bufR[buf_index] = buf[i] + imuldiv24(out1R, feedbacki); // center delay feedback
			buf[i] = imuldiv24(out2R, level2i);
			// index
			if (++index0 >= buf_size) { index0 = 0; }
			if (++index1 >= buf_size) { index1 = 0; }
			if (++index2 >= buf_size) { index2 = 0; }
			if (++buf_index >= buf_size) { buf_index = 0; }
		}
		info->index[0] = index0, info->index[1] = index1, info->index[2] = index2;
		delayL->index = buf_index;
		break;
	case 3: // 3tap no center same time // stereo same time
		for (i = 0; i < count; i++)
		{
			int32 out1L = ptrL[index0], out1R = ptrR[index0];
			// ch left
			bufL[buf_index] = buf[i] + imuldiv24(out1L, feedbacki); // center delay feedback
			buf[i] = imuldiv24(out1L, level1i);
			// ch right
			++i;
			bufR[buf_index] = buf[i] + imuldiv24(out1R, feedbacki); // center delay feedback
			buf[i] = imuldiv24(out1R, level2i);
			// index
			if (++index0 >= buf_size) { index0 = 0; }
			if (++buf_index >= buf_size) { buf_index = 0; }
		}
		info->index[0] = index0;
		delayL->index = buf_index;
		break;
	}
}
#else /* floating-point implementation */
static void do_delay3(DATA_T *buf, int32 count, InfoDelay3 *info)
{
	int32 i;
	simple_delay *delayL = &(info->delayL), *delayR = &(info->delayR);
	DATA_T *bufL = delayL->buf, *bufR = delayR->buf;
	DATA_T *ptrL = info->ptrL, *ptrR = info->ptrR;
	int32 buf_index = delayL->index, buf_size = delayL->size;
	int32 index0 = info->index[0], index1 = info->index[1], index2 = info->index[2];
	FLOAT_T level0 = info->level[0], level1 = info->level[1], level2 = info->level[2], feedback = info->feedback;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		init_delay3(info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_delay3(info);
		return;
	} else if(count <= 0) {
		return;
	}
	switch(info->opt_mode){
	default:
	case 0: // 3tap all
		for (i = 0; i < count; i++)
		{
			DATA_T outC, out1L = ptrL[index0], out1R = ptrR[index0], out2L = ptrL[index1], out2R = ptrR[index2];
			// ch center
			outC = (out1L + out1R) * DIV_MIX_LEVEL * level0; // center
			// ch left
			bufL[buf_index] = buf[i] + out1L * feedback; // center delay feedback
			buf[i] = out2L * level1 + outC;
			// ch right
			++i;
			bufR[buf_index] = buf[i] + out1R * feedback; // center delay feedback
			buf[i] = out2R * level2 + outC;
			// index
			if (++index0 >= buf_size) {index0 = 0;}
			if (++index1 >= buf_size) {index1 = 0;}
			if (++index2 >= buf_size) {index2 = 0;}
			if (++buf_index >= buf_size) {buf_index = 0;}
		}
		info->index[0] = index0, info->index[1] = index1, info->index[2] = index2;
		delayL->index = delayR->index = buf_index;
		break;
	case 1: // 3tap center only
		for (i = 0; i < count; i++)
		{
			DATA_T outC, out1L = ptrL[index0], out1R = ptrR[index0];
			// ch center
			outC = (out1L + out1R) * DIV_MIX_LEVEL * level0; // center
			// ch left
			bufL[buf_index] = buf[i] + out1L * feedback; // center delay feedback
			buf[i] = outC;
			// ch right
			++i;
			bufR[buf_index] = buf[i] + out1R * feedback; // center delay feedback
			buf[i] = outC;
			// index
			if (++index0 >= buf_size) {index0 = 0;}
			if (++buf_index >= buf_size) {buf_index = 0;}
		}
		info->index[0] = index0;
		delayL->index = delayR->index = buf_index;
		break;
	case 2: // 3tap no center diff time
		for (i = 0; i < count; i++)
		{
			DATA_T out1L = ptrL[index0], out1R = ptrR[index0], out2L = ptrL[index1], out2R = ptrR[index2];
			// ch left
			bufL[buf_index] = buf[i] + out1L * feedback; // center delay feedback
			buf[i] = out2L * level1;
			// ch right
			++i;
			bufR[buf_index] = buf[i] + out1R * feedback; // center delay feedback
			buf[i] = out2R * level2;
			// index
			if (++index0 >= buf_size) {index0 = 0;}
			if (++index1 >= buf_size) {index1 = 0;}
			if (++index2 >= buf_size) {index2 = 0;}
			if (++buf_index >= buf_size) {buf_index = 0;}
		}
		info->index[0] = index0, info->index[1] = index1, info->index[2] = index2;
		delayL->index = delayR->index = buf_index;
		break;
	case 3: // 3tap no center same time // stereo same time
		for (i = 0; i < count; i++)
		{
			DATA_T out1L = ptrL[index0], out1R = ptrR[index0];
			// ch left
			bufL[buf_index] = buf[i] + out1L * feedback; // center delay feedback
			buf[i] = out1L * level1;
			// ch right
			++i;
			bufR[buf_index] = buf[i] + out1R * feedback; // center delay feedback
			buf[i] = out1R * level2;
			// index
			if (++index0 >= buf_size) {index0 = 0;}
			if (++buf_index >= buf_size) {buf_index = 0;}
		}
		info->index[0] = index0;
		delayL->index = delayR->index = buf_index;
		break;
	}
}
#endif /* OPT_MODE != 0 */



/*                             */
/*        Chorus Effect        */
/*                             */

///r
double ext_chorus_level = 1.0;
double ext_chorus_feedback = 1.0;
double ext_chorus_depth = 1.0;

/*! Stereo Chorus; this implementation is specialized for system effect. */

#define CHORUS_RATE_MAX_GM2 (15.616) // Hz

static inline double calc_chorus_rate_gm2(int val)
{
	return (double)(val + 1) * DIV_128 * CHORUS_RATE_MAX_GM2; // max Hz
}

#define CHORUS_DEPTH_MAX_GM2 (20.0) // 40ms GM2
#define CHORUS_DEPTH_MAX_GS (10.0) // 10cent GS
#define CHORUS_DEPTH_MAX_XG (10.0) // 10cent XG

static inline double calc_chorus_depth_gm2(int val)
{
//	return (double)(chorus_status_gs.depth + 1) / 12.8; // [ms]
	return (double)(val + 1) * DIV_128 * CHORUS_DEPTH_MAX_GM2 * ext_chorus_depth;
}

static inline double calc_chorus_depth_gs(int val)
{
	return (double)(val + 1) * DIV_128 * CHORUS_DEPTH_MAX_GS * ext_chorus_depth;
}

static inline double calc_chorus_depth_xg(int val)
{
	return (double)(val + 1) * DIV_128 * CHORUS_DEPTH_MAX_XG * ext_chorus_depth;
}

static inline double calc_chorus_depth_cent(double depth_cent, double lfo_rate)
{
#if 0 //def _DEBUG
	// depth[cent]の場合の読み出しカウントの倍率
	double mul = pow(2.0, depth_cent * DIV_1200);
	// ピッチ変化が最大になるのは0度を中心とした1カウント分(-0.5x~+0.5x) なので 2.0*sin(0.5x) x=(lfo_rate[Hz]/sample_rate[Hz]*2pi)
	double max = 2.0 * sin(lfo_rate * div_playmode_rate * M_PI);
	// depth[multiply] = 1.0[sample_cnt] + depth[cnt] * 2.0 * sin(0.5 * lfo_rate[Hz]/sample_rate[Hz] * 2.0 * M_PI)
	// depth[cnt] = に変形
	double cnt = (mul - 1.0) / max;
	// 比較用にdepth[ms]に変換
	double ms = cnt * div_playmode_rate * 1000;
	return cnt;
#endif
	double tmp1 = pow(2.0, depth_cent * DIV_1200) - 1.0;
	double tmp2 = sin(lfo_rate * div_playmode_rate * M_PI);
	if(tmp1 && tmp2)
		return tmp1 / tmp2 * DIV_2;
	else
		return 0;
}


#define CHORUS_P1_WET_LEVEL (1.75 * 0.68)
#define CHORUS_P1_FEEDBACK  (0.9)
static void do_chorus_p1(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, f0, f1;
	FLOAT_T output, v0, v1, histL = info->histL, histR = info->histR;
	FLOAT_T wetd = info->wetd, feedbackd = info->feedbackd;
	DATA_T
		*bufL = info->delayL.buf, *bufR = info->delayR.buf;
	int32
		*lfobufL = info->lfoL.buf, *lfobufR = info->lfoR.buf;
	int32
		icycle = info->lfoL.icycle, cycle = info->lfoL.cycle, 
		depthc = info->depthc, pdelay = info->pdelayc, rpt0 = info->sptR5;
	FLOAT_T
		level = info->level, feedback = info->feedback,
		send_reverb = info->send_reverb, send_delay = info->send_delay;
	int32 wpt0 = info->sptL5, sptL0 = info->sptL0, sptR0 = info->sptR0, lfocnt = info->lfoL.count;
	
	if(count == MAGIC_INIT_EFFECT_INFO) {
		init_lfo(&(info->lfoL), info->rate, LFO_TRIANGULAR, 0);
		init_lfo(&(info->lfoR), info->rate, LFO_TRIANGULAR, 90);
		if(info->depth_type) // depth [ms] p-p
			info->depthc = info->depth_ms * DIV_2 * playmode_rate_ms; // depth_ms = pp_max , -depth/2~+depth/2
		else // depth [cent]
			info->depthc = calc_chorus_depth_cent(info->depth_cent, info->rate);
		info->pdelayc = info->pdelay_ms * playmode_rate_ms;
		info->pdelayc -= info->depthc / 2;	/* NOMINAL_DELAY to delay */
		if (info->pdelayc < 1) {info->pdelayc = 1;}
		info->sptR5 = info->pdelayc + info->depthc + 2;	/* allowance */
		set_delay(&(info->delayL), info->sptR5);
		set_delay(&(info->delayR), info->sptR5);
		info->feedbackd = info->feedback * CHORUS_P1_FEEDBACK * ext_chorus_feedback;
		info->wetd = CHORUS_P1_WET_LEVEL * ext_chorus_level;
		info->sptL5 = info->sptL0 = info->sptR0 = info->histL = info->histR = 0;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_delay(&(info->delayL));
		free_delay(&(info->delayR));
		return;
	}
	/* LFO */
	f0 = imuldiv24(lfobufL[imuldiv24(lfocnt, icycle)], depthc);
	sptL0 = wpt0 - pdelay - (f0 >> 8);	/* integral part of delay */
	f0 = 0xFF - (f0 & 0xFF);	/* (1 - frac) * 256 */
	if(sptL0 < 0) {sptL0 += rpt0;}
	f1 = imuldiv24(lfobufR[imuldiv24(lfocnt, icycle)], depthc);
	sptR0 = wpt0 - pdelay - (f1 >> 8);	/* integral part of delay */
	f1 = 0xFF - (f1 & 0xFF);	/* (1 - frac) * 256 */
	if(sptR0 < 0) {sptR0 += rpt0;}
	
	// CH_STEREO:
	for(i = 0; i < count; i++) {
		v0 = bufL[sptL0];
		v1 = bufR[sptR0];

		/* LFO */
		if(++wpt0 >= rpt0) {wpt0 = 0;}
		f0 = imuldiv24(lfobufL[imuldiv24(lfocnt, icycle)], depthc);
		sptL0 = wpt0 - pdelay - (f0 >> 8);	/* integral part of delay */
		f0 = 0xFF - (f0 & 0xFF);	/* (1 - frac) * 256 */
		if(sptL0 < 0) {sptL0 += rpt0;}
		f1 = imuldiv24(lfobufR[imuldiv24(lfocnt, icycle)], depthc);
		sptR0 = wpt0 - pdelay - (f1 >> 8);	/* integral part of delay */
		f1 = 0xFF - (f1 & 0xFF);	/* (1 - frac) * 256 */
		if(sptR0 < 0) {sptR0 += rpt0;}
		if(++lfocnt >= cycle) {lfocnt = 0;}

		/* left */
		/* delay with all-pass interpolation */
		output = histL = v0 + (bufL[sptL0] - histL) * f0 * DIV_8BIT;
		bufL[wpt0] = buf[i] + output * feedback;
		buf[i] = output * wetd;
		i++;
		/* right */
		/* delay with all-pass interpolation */
		output = histR = v1 + (bufR[sptR0] - histR) * f1 * DIV_8BIT;
		bufR[wpt0] = buf[i] + output * feedback;
		buf[i] = output * wetd;
	}
	info->sptL5 = wpt0, info->sptL0 = sptL0, info->sptR0 = sptR0,
		info->histL = histL, info->histR = histR;
	info->lfoL.count = info->lfoR.count = lfocnt;
}


// bw
//-------------------------------------------------------------------

float do_waver_chorus_calc(DATA_T *delayBuf, int delay_max_buf, int32 *now_counter, FLOAT_T in, FLOAT_T feedback, FLOAT_T delay, FLOAT_T depth, FLOAT_T rate)
{
	FLOAT_T back = 0, y_1,y0,y1,y2, x,c0,c1,c2,c3, output;
	int index0 = 0, index1 = 0, index2 = 0;
	int index_1=0;
	DATA_T *buffer = delayBuf;
	int counter = *now_counter;
	FLOAT_T crate = ((FLOAT_T)delay_max_buf / rate + 0.5);
	FLOAT_T cdepth = (1.0 - depth) + ( (1.0 + sin(counter * M_PI / crate) * DIV_PI * DIV_20) * depth );

    // calculate delay offset
    back = (FLOAT_T)counter-delay;

    if(counter >= delay_max_buf)
        counter=0;
    
    // clip lookback buffer-bound
    if(back < 0.0)
        back = delay_max_buf+back;
    
    // compute interpolation left-floor
    index0 = (int)floor(back);
    
    // compute interpolation right-floor
    index_1 = index0 - 1;
    index1 = index0 + 1;
    index2 = index0 + 2;
    
    // clip interp. buffer-bound
    if(index_1 < 0) 
		index_1 = delay_max_buf - 1;
    if(index1 >= delay_max_buf) 
		index1 = 0;
    if(index2 >= delay_max_buf) 
		index2 = 0;
    
    // get neighbourgh samples
    y_1= buffer[index_1];
    y0 = buffer[index0];
    y1 = buffer[index1];
    y2 = buffer[index2];
    
    // compute interpolation x
    x = back-index0;
    
    // calculate
    c0 = y0;
//    c1 = 0.5f*(y1-y_1);
  //  c2 = y_1 - 2.5f*y0 + 2.0f*y1 - 0.5f*y2;
    //c3 = 0.5f*(y2-y_1) + 1.5f*(y0-y1);
    
    c1 = (cdepth * 0.5f) * (y1 - y_1);
    c2 = y_1 - (cdepth * 2.5f) * y0 + (cdepth * 2.0f) * y1 - (cdepth * 0.5f) * y2;
    c3 = (cdepth * 0.5f) * (y2 - y_1) + (cdepth * 1.5f) * (y0 - y1);
    
	
	output = ((c3 * x + c2) * x + c1) * x + c0;
///r
//	output *= feedback;

    // add to delay buffer
    buffer[counter] = (in + output * feedback); // (in + output)

    // increment delay counter
    counter++;
    
    // clip delay counter
    if(counter >= delay_max_buf)
        counter = 0;

	*now_counter = counter ;

	return output;// * (1.0 - depth) + (output * (sin(r * 6.28318531) / 3.3f) * depth);
}

#define CHORUS_WV_WET_LEVEL (1.75 * 0.68)
#define CHORUS_WV_FEEDBACK  0.95
static void do_chorus_waver(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i;
	int32 depthc = info->depthc, pdelayc = info->pdelayc, rpt0 = info->sptR0;
	FLOAT_T wetd = info->wetd, feedbackd = info->feedbackd;
	FLOAT_T output=0;
	FLOAT_T frate = (double)info->rate * DIV_3 * 2.0;
    FLOAT_T fdepth = (double)info->pdelayc * DIV_2;
//	FLOAT_T frate = ( (double)((int)chorus_status_gs.rate + 1) * 6.0 * DIV_127 ) + 0.5;
//	FLOAT_T fdepth = (double)(chorus_status_gs.depth + 2) * DIV_60;
	FLOAT_T outi;

	if(count == MAGIC_INIT_EFFECT_INFO) {		
		init_lfo(&(info->lfoL), info->rate, LFO_TRIANGULAR, 0);
		init_lfo(&(info->lfoR), info->rate, LFO_TRIANGULAR, 90);
		if(info->depth_type) // depth [ms] p-p
			info->depthc = info->depth_ms * DIV_2 * playmode_rate_ms; // depth_ms = pp_max , -depth/2~+depth/2
		else // depth [cent]
			info->depthc = calc_chorus_depth_cent(info->depth_cent, info->rate);
		info->pdelayc = info->pdelay_ms * playmode_rate_ms;
//		info->pdelay -= info->depth * DIV_2;
		if (info->pdelayc < 1) {info->pdelayc = 1;}
		info->sptR0 = info->pdelayc + info->depthc;	/* allowance */
		set_delay(&(info->delayL), info->sptR0+2);
		set_delay(&(info->delayR), info->sptR0+2);
		info->feedbackd = info->feedback * CHORUS_WV_FEEDBACK * ext_chorus_feedback;
		info->wetd = CHORUS_WV_WET_LEVEL * ext_chorus_level;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_delay(&(info->delayL));
		free_delay(&(info->delayR));
		return;
	}
	// CH_STEREO:
	for (i = 0; i < count; i++) {
#ifdef EFFECT_LEVEL_FLOAT // level float
		output = do_waver_chorus_calc(info->delayL.buf, info->rpt0, &info->delayL.index,
			buf[i], feedbackd, info->pdelay, fdepth, frate );
		buf[i] = output * level;
		i++;
		output = do_waver_chorus_calc(info->delayR.buf, info->rpt0, &info->delayR.index,
			buf[i], feedbackd, info->pdelay, fdepth, frate );
		buf[i] = output * wetd;
#else // level int
		output = do_waver_chorus_calc(info->delayL.buf, info->sptR0, &info->delayL.index,
			(FLOAT_T)buf[i] / (FLOAT_T)INT_MAX, feedbackd, info->pdelayc, fdepth, frate );
		buf[i] = (output * wetd * (FLOAT_T)INT_MAX);
		i++;
		output = do_waver_chorus_calc(info->delayR.buf, info->sptR0, &info->delayR.index,
			(FLOAT_T)buf[i] / (FLOAT_T)INT_MAX, feedbackd, info->pdelayc, fdepth, frate );
		buf[i] = (output * wetd * (FLOAT_T)INT_MAX);
#endif
	}
}


#define CHORUS_P2_WET_LEVEL (2.0 * 0.68)
#define CHORUS_P2_FEEDBACK  0.5
#define CHORUS_P2_DEPTH_DEV (1.0 / (20.0 + 1.0))
#define CHORUS_P2_DELAY_DEV (1.0 / (20.0 * 3.0))
static void do_chorus_p2(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	lfo *lfoL = &(info->lfoL),  *lfoR = &(info->lfoR);
	simple_delay *delayL = &(info->delayL), *delayR = &(info->delayR);
	DATA_T *ebufL = delayL->buf, *ebufR = delayR->buf;
	DATA_T vl0, vl3, vr0, vr3;
	int32 sizeL = delayL->size, indexL = delayL->index, sizeR = delayR->size, indexR = delayR->index;
	int32 sptL0 = info->sptL0, sptL3 = info->sptL3;
	int32 sptR0 = info->sptR0, sptR3 = info->sptR3;
	FLOAT_T wetd = info->wetd, feedbackd = info->feedbackd;
	int32 depthc = info->depthc, pdelayc = info->pdelayc;
	int32 i, lfo_val, fl0, fl3, fr0, fr3;	
	int32 depth0 = info->depth0, depth3 = info->depth3,
		pdelay0 = info->pdelay0, pdelay3 = info->pdelay3;
	FLOAT_T outputL, outputR, tmpL, tmpR, tmpL2, tmpR2;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		if(info->depth_type) // depth [ms] p-p
			info->depthc = info->depth_ms * DIV_2 * playmode_rate_ms; // depth_ms = pp_max , -depth/2~+depth/2
		else // depth [cent]
			info->depthc = calc_chorus_depth_cent(info->depth_cent, info->rate);
		info->pdelayc = info->pdelay_ms * playmode_rate_ms;
		info->pdelayc -= info->depthc / 2;
		if(info->pdelayc <= 1) {info->pdelayc = 1;}
		vl0 = info->depthc * ((double)info->depth_dev * CHORUS_P2_DEPTH_DEV);
		info->depth0 = info->depthc - vl0;
		info->depth3 = info->depthc + vl0;
		vl0 = info->pdelayc * ((double)info->pdelay_dev * CHORUS_P2_DELAY_DEV);
		info->pdelay0 = info->pdelayc + vl0;
		info->pdelay3 = info->pdelayc + vl0 * 3;
		info->pan0 = 64 - info->pan_dev * 3;
		info->pan3 = 64 + info->pan_dev * 3;
		init_lfo(lfoL, info->rate, LFO_TRIANGULAR, 0);
		init_lfo(lfoR, info->rate, LFO_TRIANGULAR, info->phase_diff);
		set_delay(delayL, (int32)(9600.0 * play_mode->rate / 44100.0));
		set_delay(delayR, (int32)(9600.0 * play_mode->rate / 44100.0));
		info->feedbackd = info->feedback * CHORUS_P2_FEEDBACK * ext_chorus_feedback;
		info->wetd = CHORUS_P2_WET_LEVEL * ext_chorus_level;
		info->histL = info->histR = 0;
		info->sptL0 = info->sptL3 = 0;
		info->sptR0 = info->sptR3 = 0;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_delay(delayL);
		free_delay(delayR);
		return;
	}
	switch(info->mode){
	case CH_STEREO:
		/* LFO */
		lfo_val = lfoL->buf[imuldiv24(lfoL->count, lfoL->icycle)];
		fl0 = imuldiv24(lfo_val, depthc);
		sptL0 = indexL - pdelayc - (fl0 >> 8);	/* integral part of delay */
		if(sptL0 < 0) {sptL0 += sizeL;}
		fl3 = imuldiv24(lfo_val, depthc);
		sptL3 = indexL - pdelayc - (fl3 >> 8);	/* integral part of delay */
		if(sptL3 < 0) {sptL3 += sizeL;}
		lfo_val = lfoR->buf[imuldiv24(lfoR->count, lfoR->icycle)];
		fr0 = imuldiv24(lfo_val, depthc);
		sptR0 = indexR - pdelayc - (fr0 >> 8);	/* integral part of delay */
		if(sptR0 < 0) {sptR0 += sizeR;}
		fr3 = imuldiv24(lfo_val, depthc);
		sptR3 = indexR - pdelayc - (fr3 >> 8);	/* integral part of delay */
		if(sptR3 < 0) {sptR3 += sizeR;}
		for(i = 0; i < count; i++) {
			/* LFO */
			if(++indexL >= sizeL) {indexL = 0;}
			lfo_val = do_lfo(lfoL);
			fl0 = imuldiv24(lfo_val, depth0);
			sptL0 = indexL - pdelay0 - (fl0 >> 8);	/* integral part of delay */
			fl0 = 0xFF - (fl0 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL0 < 0) {sptL0 += sizeL;}
			fl3 = imuldiv24(lfo_val, depth3);
			sptL3 = indexL - pdelay3 - (fl3 >> 8);	/* integral part of delay */
			fl3 = 0xFF - (fl3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL3 < 0) {sptL3 += sizeL;}
			if(++indexR >= sizeR) {indexR = 0;}
			lfo_val = do_lfo(lfoR);
			fr0 = imuldiv24(lfo_val, depth0);
			sptR0 = indexR - pdelay0 - (fr0 >> 8);	/* integral part of delay */
			fr0 = 0xFF - (fr0 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR0 < 0) {sptR0 += sizeR;}
			fr3 = imuldiv24(lfo_val, depth3);
			sptR3 = indexR - pdelay3 - (fr3 >> 8);	/* integral part of delay */
			fr3 = 0xFF - (fr3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR3 < 0) {sptR3 += sizeR;}
			/* chorus effect */
			/* left */
			tmpL2 = buf[i];
			ebufL[indexL] = tmpL2 + info->histL * feedbackd;
			tmpL = ebufL[sptL0] * fl0 * DIV_8BIT
				+ ebufL[sptL3] * fl3 * DIV_8BIT;
		//	info->histL = (info->histL + tmpL * DIV_2) * DIV_2;  // linear intp
			info->histL = tmpL * DIV_2;  // no intp
			buf[i] = info->histL * wetd;
			/* right */
			++i;
			tmpR2 = buf[i];
			ebufR[indexR] = tmpR2 + info->histR * feedbackd;
			tmpR = ebufR[sptR0] * fr0 * DIV_8BIT
				+ ebufR[sptR3] * fr3 * DIV_8BIT;
			info->histR = (info->histR + tmpR * DIV_2) * DIV_2;  // linear intp
		//	info->histR = tmpR * DIV_2;  // no intp
			buf[i] = info->histR * wetd;
		}
		delayL->size = sizeL, delayL->index = indexL, delayR->size = sizeR, delayR->index = indexR;
		info->sptL0 = sptL0, info->sptL3 = sptL3, info->sptR0 = sptR0, info->sptR3 = sptR3;
		break;
#if 0
	case CH_MIX_STEREO:
		/* LFO */
		lfo_val = lfoL->buf[imuldiv24(lfoL->count, lfoL->icycle)];
		fl0 = imuldiv24(lfo_val, depthc);
		sptL0 = indexL - pdelayc - (fl0 >> 8);	/* integral part of delay */
		if(sptL0 < 0) {sptL0 += sizeL;}
		fl3 = imuldiv24(lfo_val, depthc);
		sptL3 = indexL - pdelayc - (fl3 >> 8);	/* integral part of delay */
		if(sptL3 < 0) {sptL3 += sizeL;}
		for(i = 0; i < count; i++) {
			/* LFO */
			if(++indexL >= sizeL) {indexL = 0;}
			lfo_val = do_lfo(lfoL);
			fl0 = imuldiv24(lfo_val, depth0);
			sptL0 = indexL - pdelay0 - (fl0 >> 8);	/* integral part of delay */
			fl0 = 0xFF - (fl0 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL0 < 0) {sptL0 += sizeL;}
			fl3 = imuldiv24(lfo_val, depth3);
			sptL3 = indexL - pdelay3 - (fl3 >> 8);	/* integral part of delay */
			fl3 = 0xFF - (fl3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL3 < 0) {sptL3 += sizeL;}
			/* chorus effect */
			/* mix */
			tmpL2 = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			ebufL[indexL] = tmpL2 + (info->histL + info->histR) * feedbackd;
			vl0 = ebufL[sptL0] * fl0 * DIV_8BIT;
			vl3 = ebufL[sptL3] * fl3 * DIV_8BIT;
			tmpL = do_left_panning(vl0, info->pan0)	+ do_left_panning(vl3, info->pan3);
			tmpR = do_right_panning(vl0, info->pan0) + do_right_panning(vl3, info->pan3);
		//	info->histL = (info->histL + tmpL * DIV_2) * DIV_2;  // linear intp
		//	info->histR = (info->histR + tmpR * DIV_2) * DIV_2;  // linear intp
			info->histL = tmpL * DIV_2;  // no intp
			info->histR = tmpR * DIV_2;  // no intp
			buf[i] = info->histL * wetd;
			++i;
			buf[i] = info->histR * wetd;
		}
		delayL->size = sizeL, delayL->index = indexL, delayR->size = sizeR, delayR->index = indexR;
		info->sptL0 = sptL0, info->sptL3 = sptL3, info->sptR0 = sptR0, info->sptR3 = sptR3;
		break;
#endif
	}
}


#define CHORUS_P3_WET_LEVEL (2.125 * 0.68)
#define CHORUS_P3_FEEDBACK  0.6
#define CHORUS_P3_DEPTH_DEV (1.0 / (20.0 + 1.0))
#define CHORUS_P3_DELAY_DEV (1.0 / (20.0 * 3.0))
static void do_chorus_p3(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	lfo *lfoL = &(info->lfoL),  *lfoR = &(info->lfoR);
	simple_delay *delayL = &(info->delayL), *delayR = &(info->delayR);
	DATA_T *ebufL = delayL->buf, *ebufR = delayR->buf;
	DATA_T vl1, vl3, vl5, vr1, vr3, vr5;
	int32 sizeL = delayL->size, indexL = delayL->index, sizeR = delayR->size, indexR = delayR->index;
	int32 sptL1 = info->sptL1, sptL3 = info->sptL3, sptL5 = info->sptL5;
	int32 sptR1 = info->sptR1, sptR3 = info->sptR3, sptR5 = info->sptR5;
	FLOAT_T wetd = info->wetd, feedbackd = info->feedbackd;
	int32 depthc = info->depthc, pdelayc = info->pdelayc;
	int32 i, lfo_val, fl1, fl3, fl5, fr1, fr3, fr5;	
	int32 depth1 = info->depth1, depth3 = info->depth3, depth5 = info->depth5;
	int32 pdelay1 = info->pdelay1, pdelay3 = info->pdelay3, pdelay5 = info->pdelay5;
	FLOAT_T tmp, tmpL, tmpR, tmpL2, tmpR2;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		if(info->depth_type) // depth [ms] p-p
			info->depthc = info->depth_ms * DIV_2 * playmode_rate_ms; // depth_ms = pp_max , -depth/2~+depth/2
		else // depth [cent]
			info->depthc = calc_chorus_depth_cent(info->depth_cent, info->rate);
		info->pdelayc = info->pdelay_ms * (double)playmode_rate_ms;
		info->pdelayc -= info->depthc / 2;
		if(info->pdelayc <= 1) {info->pdelayc = 1;}
		vl1 = info->depthc * ((double)info->depth_dev * CHORUS_P3_DEPTH_DEV);
		info->depth1 = info->depthc;
		info->depth3 = info->depthc + vl1;
		info->depth5 = info->depthc - vl1;
		vl1 = info->pdelayc * ((double)info->pdelay_dev * CHORUS_P3_DELAY_DEV);
		info->pdelay1 = info->pdelayc + vl1 * 2;
		info->pdelay3 = info->pdelayc + vl1 * 3;
		info->pdelay5 = info->pdelayc + vl1;
		info->pan1 = 64 - info->pan_dev * 3;
		info->pan3 = 64;
		info->pan5 = 64 + info->pan_dev * 3;
		init_lfo(lfoL, info->rate, LFO_TRIANGULAR, 0);
		init_lfo(lfoR, info->rate, LFO_TRIANGULAR, info->phase_diff);
		set_delay(delayL, (int32)(9600.0 * play_mode->rate / 44100.0));
		set_delay(delayR, (int32)(9600.0 * play_mode->rate / 44100.0));
		info->feedbackd = info->feedback * CHORUS_P3_FEEDBACK * ext_chorus_feedback;
		info->wetd = CHORUS_P3_WET_LEVEL * ext_chorus_level;
		info->histL = info->histR = 0;
		info->sptL0 = info->sptL1 = info->sptL2 = info->sptL3 = info->sptL4 = info->sptL5 = 0;
		info->sptR0 = info->sptR1 = info->sptR2 = info->sptR3 = info->sptR4 = info->sptR5 = 0;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_delay(delayL);
		free_delay(delayR);
		return;
	}
	switch(info->mode){
	case CH_STEREO:
		/* LFO */
		lfo_val = lfoL->buf[imuldiv24(lfoL->count, lfoL->icycle)];
		fl1 = imuldiv24(lfo_val, depthc);
		sptL1 = indexL - pdelayc - (fl1 >> 8);	/* integral part of delay */
		if(sptL1 < 0) {sptL1 += sizeL;}
		fl3 = imuldiv24(lfo_val, depthc);
		sptL3 = indexL - pdelayc - (fl3 >> 8);	/* integral part of delay */
		if(sptL3 < 0) {sptL3 += sizeL;}
		fl5 = imuldiv24(lfo_val, depthc);
		sptL5 = indexL - pdelayc - (fl5 >> 8);	/* integral part of delay */
		if(sptL5 < 0) {sptL5 += sizeL;}	
		lfo_val = lfoR->buf[imuldiv24(lfoR->count, lfoR->icycle)];
		fr1 = imuldiv24(lfo_val, depthc);
		sptR1 = indexR - pdelayc - (fr1 >> 8);	/* integral part of delay */
		if(sptR1 < 0) {sptR1 += sizeR;}
		fr3 = imuldiv24(lfo_val, depthc);
		sptR3 = indexR - pdelayc - (fr3 >> 8);	/* integral part of delay */
		if(sptR3 < 0) {sptR3 += sizeR;}
		fr5 = imuldiv24(lfo_val, depthc);
		sptR5 = indexR - pdelayc - (fr5 >> 8);	/* integral part of delay */
		if(sptR5 < 0) {sptR5 += sizeR;}
		for(i = 0; i < count; i++) {
			/* LFO */
			if(++indexL >= sizeL) {indexL = 0;}
			lfo_val = do_lfo(lfoL);
			fl1 = imuldiv24(lfo_val, depth1);
			sptL1 = indexL - pdelay1 - (fl1 >> 8);	/* integral part of delay */
			fl1 = 0xFF - (fl1 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL1 < 0) {sptL1 += sizeL;}
			fl3 = imuldiv24(lfo_val, depth3);
			sptL3 = indexL - pdelay3 - (fl3 >> 8);	/* integral part of delay */
			fl3 = 0xFF - (fl3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL3 < 0) {sptL3 += sizeL;}
			fl5 = imuldiv24(lfo_val, depth5);
			sptL5 = indexL - pdelay5 - (fl5 >> 8);	/* integral part of delay */
			fl5 = 0xFF - (fl5 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL5 < 0) {sptL5 += sizeL;}
			if(++indexR >= sizeR) {indexR = 0;}
			lfo_val = do_lfo(lfoR);
			fr1 = imuldiv24(lfo_val, depth1);
			sptR1 = indexR - pdelay1 - (fr1 >> 8);	/* integral part of delay */
			fr1 = 0xFF - (fr1 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR1 < 0) {sptR1 += sizeR;}
			fr3 = imuldiv24(lfo_val, depth3);
			sptR3 = indexR - pdelay3 - (fr3 >> 8);	/* integral part of delay */
			fr3 = 0xFF - (fr3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR3 < 0) {sptR3 += sizeR;}
			fr5 = imuldiv24(lfo_val, depth5);
			sptR5 = indexR - pdelay5 - (fr5 >> 8);	/* integral part of delay */
			fr5 = 0xFF - (fr5 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR5 < 0) {sptR5 += sizeR;}
			/* chorus effect */
			/* left */
			tmpL2 = buf[i];
			ebufL[indexL] = tmpL2 + info->histL * feedbackd;
			tmpL = ebufL[sptL1] * fl1 * DIV_8BIT
				+ ebufL[sptL3] * fl3 * DIV_8BIT
				+ ebufL[sptL5] * fl5 * DIV_8BIT;
		//	info->histL = (info->histL + tmpL * DIV_3) * DIV_2;  // linear intp
			info->histL = tmpL * DIV_3;  // no intp
			buf[i] = info->histL * wetd;
			/* right */
			++i;
			tmpR2 = buf[i];
			ebufR[indexR] = tmpR2 + info->histR * feedbackd;
			tmpR = ebufR[sptR1] * fr1 * DIV_8BIT
				+ ebufR[sptR3] * fr3 * DIV_8BIT
				+ ebufR[sptR5] * fr5 * DIV_8BIT;		
		//	info->histR = (info->histR + tmpR * DIV_3) * DIV_2;  // linear intp
			info->histR = tmpR * DIV_3;  // no intp
			buf[i] = info->histR * wetd;
		}
		delayL->size = sizeL, delayL->index = indexL, delayR->size = sizeR, delayR->index = indexR;
		info->sptL1 = sptL1, info->sptL3 = sptL3, info->sptL5 = sptL5,
		info->sptR1 = sptR1, info->sptR3 = sptR3, info->sptR5 = sptR5;
		break;
	case CH_MIX_STEREO:
		/* LFO */
		lfo_val = lfoL->buf[imuldiv24(lfoL->count, lfoL->icycle)];
		fl1 = imuldiv24(lfo_val, depthc);
		sptL1 = indexL - pdelayc - (fl1 >> 8);	/* integral part of delay */
		if(sptL1 < 0) {sptL1 += sizeL;}
		fl3 = imuldiv24(lfo_val, depthc);
		sptL3 = indexL - pdelayc - (fl3 >> 8);	/* integral part of delay */
		if(sptL3 < 0) {sptL3 += sizeL;}
		fl5 = imuldiv24(lfo_val, depthc);
		sptL5 = indexL - pdelayc - (fl5 >> 8);	/* integral part of delay */
		if(sptL5 < 0) {sptL5 += sizeL;}	
		for(i = 0; i < count; i++) {
			/* LFO */
			if(++indexL >= sizeL) {indexL = 0;}
			lfo_val = do_lfo(lfoL);
			fl1 = imuldiv24(lfo_val, depth1);
			sptL1 = indexL - pdelay1 - (fl1 >> 8);	/* integral part of delay */
			fl1 = 0xFF - (fl1 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL1 < 0) {sptL1 += sizeL;}
			fl3 = imuldiv24(lfo_val, depth3);
			sptL3 = indexL - pdelay3 - (fl3 >> 8);	/* integral part of delay */
			fl3 = 0xFF - (fl3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL3 < 0) {sptL3 += sizeL;}
			fl5 = imuldiv24(lfo_val, depth5);
			sptL5 = indexL - pdelay5 - (fl5 >> 8);	/* integral part of delay */
			fl5 = 0xFF - (fl5 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL5 < 0) {sptL5 += sizeL;}
			/* chorus effect */
			/* mix */
			tmpL2 = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			ebufL[indexL] = tmpL2 + (info->histL + info->histR) * feedbackd;			
			vl1 = ebufL[sptL1] * fl1 * DIV_8BIT;
			vl3 = ebufL[sptL3] * fl3 * DIV_8BIT;
			vl5 = ebufL[sptL5] * fl5 * DIV_8BIT;
			tmpL = do_left_panning(vl1, info->pan1)
				+ do_left_panning(vl3, info->pan3)
				+ do_left_panning(vl5, info->pan5);
			tmpR = do_right_panning(vl1, info->pan1)
				+ do_right_panning(vl3, info->pan3)
				+ do_right_panning(vl5, info->pan5);
		//	info->histL = (info->histL + tmpL * DIV_3) * DIV_2;  // linear intp
		//	info->histR = (info->histR + tmpR * DIV_3) * DIV_2;  // linear intp
			info->histL = tmpL * DIV_3;  // no intp
			info->histR = tmpR * DIV_3;  // no intp
			buf[i] = info->histL * wetd;
			++i;
			buf[i] = info->histR * wetd;
		}
		delayL->size = sizeL, delayL->index = indexL;
		info->sptL1 = sptL1, info->sptL3 = sptL3, info->sptL5 = sptL5;
		break;
#if 0
	case CH_MONO_STEREO:
		/* LFO */
		lfo_val = lfoL->buf[imuldiv24(lfoL->count, lfoL->icycle)];
		fl1 = imuldiv24(lfo_val, depthc);
		sptL1 = indexL - pdelayc - (fl1 >> 8);	/* integral part of delay */
		if(sptL1 < 0) {sptL1 += sizeL;}
		fl3 = imuldiv24(lfo_val, depthc);
		sptL3 = indexL - pdelayc - (fl3 >> 8);	/* integral part of delay */
		if(sptL3 < 0) {sptL3 += sizeL;}
		fl5 = imuldiv24(lfo_val, depthc);
		sptL5 = indexL - pdelayc - (fl5 >> 8);	/* integral part of delay */
		if(sptL5 < 0) {sptL5 += sizeL;}	
		for(i = 0; i < count; i++) {
			/* LFO */
			if(++indexL >= sizeL) {indexL = 0;}
			lfo_val = do_lfo(lfoL);
			fl1 = imuldiv24(lfo_val, depth1);
			sptL1 = indexL - pdelay1 - (fl1 >> 8);	/* integral part of delay */
			fl1 = 0xFF - (fl1 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL1 < 0) {sptL1 += sizeL;}
			fl3 = imuldiv24(lfo_val, depth3);
			sptL3 = indexL - pdelay3 - (fl3 >> 8);	/* integral part of delay */
			fl3 = 0xFF - (fl3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL3 < 0) {sptL3 += sizeL;}
			fl5 = imuldiv24(lfo_val, depth5);
			sptL5 = indexL - pdelay5 - (fl5 >> 8);	/* integral part of delay */
			fl5 = 0xFF - (fl5 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL5 < 0) {sptL5 += sizeL;}
			/* chorus effect */
			/* mix */
			tmp = tmpL2 = buf[i];
			ebufL[indexL] = tmpL2 + (info->histL + info->histR) * feedbackd;			
			vl1 = ebufL[sptL1] * fl1 * DIV_8BIT;
			vl3 = ebufL[sptL3] * fl3 * DIV_8BIT;
			vl5 = ebufL[sptL5] * fl5 * DIV_8BIT;
			tmpL = do_left_panning(vl1, info->pan1)
				+ do_left_panning(vl3, info->pan3)
				+ do_left_panning(vl5, info->pan5);
			tmpR = do_right_panning(vl1, info->pan1)
				+ do_right_panning(vl3, info->pan3)
				+ do_right_panning(vl5, info->pan5);
		//	info->histL = (info->histL + tmpL * DIV_3) * DIV_2;  // linear intp
		//	info->histR = (info->histR + tmpR * DIV_3) * DIV_2;  // linear intp
			info->histL = tmpL * DIV_3;  // no intp
			info->histR = tmpR * DIV_3;  // no intp
			buf[i] = info->histL * wetd;
			++i;
			buf[i] = info->histR * wetd;
		}
		delayL->size = sizeL, delayL->index = indexL;
		info->sptL1 = sptL1, info->sptL3 = sptL3, info->sptL5 = sptL5;
		break;
	case CH_MIX_MONO:
		/* LFO */
		lfo_val = lfoL->buf[imuldiv24(lfoL->count, lfoL->icycle)];
		fl1 = imuldiv24(lfo_val, depthc);
		sptL1 = indexL - pdelayc - (fl1 >> 8);	/* integral part of delay */
		if(sptL1 < 0) {sptL1 += sizeL;}
		fl3 = imuldiv24(lfo_val, depthc);
		sptL3 = indexL - pdelayc - (fl3 >> 8);	/* integral part of delay */
		if(sptL3 < 0) {sptL3 += sizeL;}
		fl5 = imuldiv24(lfo_val, depthc);
		sptL5 = indexL - pdelayc - (fl5 >> 8);	/* integral part of delay */
		if(sptL5 < 0) {sptL5 += sizeL;}	
		for(i = 0; i < count; i++) {
			/* LFO */
			if(++indexL >= sizeL) {indexL = 0;}
			lfo_val = do_lfo(lfoL);
			fl1 = imuldiv24(lfo_val, depth1);
			sptL1 = indexL - pdelay1 - (fl1 >> 8);	/* integral part of delay */
			fl1 = 0xFF - (fl1 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL1 < 0) {sptL1 += sizeL;}
			fl3 = imuldiv24(lfo_val, depth3);
			sptL3 = indexL - pdelay3 - (fl3 >> 8);	/* integral part of delay */
			fl3 = 0xFF - (fl3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL3 < 0) {sptL3 += sizeL;}
			fl5 = imuldiv24(lfo_val, depth5);
			sptL5 = indexL - pdelay5 - (fl5 >> 8);	/* integral part of delay */
			fl5 = 0xFF - (fl5 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL5 < 0) {sptL5 += sizeL;}
			/* chorus effect */
			/* mix */
			tmp = tmpL2 = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			ebufL[indexL] = tmpL2 + info->histL * feedbackd;
			tmpL = ebufL[sptL1] * fl1 * DIV_8BIT
				+ ebufL[sptL3] * fl3 * DIV_8BIT
				+ ebufL[sptL5] * fl5 * DIV_8BIT;
		//	info->histL = (info->histL + tmpL * DIV_3) * DIV_2;  // linear intp
			info->histL = tmpL * DIV_3;  // no intp
			tmpL = info->histL * wetd;
			/* output */
			buf[i] = tmpL;
			++i;
			buf[i] = tmpL;
		}
		delayL->size = sizeL, delayL->index = indexL;
		info->sptL1 = sptL1, info->sptL3 = sptL3, info->sptL5 = sptL5;
		break;
	case CH_MONO:
		/* LFO */
		lfo_val = lfoL->buf[imuldiv24(lfoL->count, lfoL->icycle)];
		fl1 = imuldiv24(lfo_val, depthc);
		sptL1 = indexL - pdelayc - (fl1 >> 8);	/* integral part of delay */
		if(sptL1 < 0) {sptL1 += sizeL;}
		fl3 = imuldiv24(lfo_val, depthc);
		sptL3 = indexL - pdelayc - (fl3 >> 8);	/* integral part of delay */
		if(sptL3 < 0) {sptL3 += sizeL;}
		fl5 = imuldiv24(lfo_val, depthc);
		sptL5 = indexL - pdelayc - (fl5 >> 8);	/* integral part of delay */
		if(sptL5 < 0) {sptL5 += sizeL;}	
		for(i = 0; i < count; i++) {
			/* LFO */
			if(++indexL >= sizeL) {indexL = 0;}
			lfo_val = do_lfo(lfoL);
			fl1 = imuldiv24(lfo_val, depth1);
			sptL1 = indexL - pdelay1 - (fl1 >> 8);	/* integral part of delay */
			fl1 = 0xFF - (fl1 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL1 < 0) {sptL1 += sizeL;}
			fl3 = imuldiv24(lfo_val, depth3);
			sptL3 = indexL - pdelay3 - (fl3 >> 8);	/* integral part of delay */
			fl3 = 0xFF - (fl3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL3 < 0) {sptL3 += sizeL;}
			fl5 = imuldiv24(lfo_val, depth5);
			sptL5 = indexL - pdelay5 - (fl5 >> 8);	/* integral part of delay */
			fl5 = 0xFF - (fl5 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL5 < 0) {sptL5 += sizeL;}
			/* chorus effect */
			/* left */
			tmpL2 = buf[i];
			ebufL[indexL] = tmpL2 + info->histL * feedbackd;
			tmpL = ebufL[sptL1] * fl1 * DIV_8BIT
				+ ebufL[sptL3] * fl3 * DIV_8BIT
				+ ebufL[sptL5] * fl5 * DIV_8BIT;
		//	info->histL = (info->histL + tmpL * DIV_3) * DIV_2;  // linear intp
			info->histL = tmpL * DIV_3;  // no intp
			tmpL = info->histL * wetd;
			buf[i] = tmpL;
			/* right */
			++i;
			buf[i] = tmpL;
		}
		delayL->size = sizeL, delayL->index = indexL;
		info->sptL1 = sptL1, info->sptL3 = sptL3, info->sptL5 = sptL5;
		break;
	case CH_LEFT:
		/* LFO */
		lfo_val = lfoL->buf[imuldiv24(lfoL->count, lfoL->icycle)];
		fl1 = imuldiv24(lfo_val, depthc);
		sptL1 = indexL - pdelayc - (fl1 >> 8);	/* integral part of delay */
		if(sptL1 < 0) {sptL1 += sizeL;}
		fl3 = imuldiv24(lfo_val, depthc);
		sptL3 = indexL - pdelayc - (fl3 >> 8);	/* integral part of delay */
		if(sptL3 < 0) {sptL3 += sizeL;}
		fl5 = imuldiv24(lfo_val, depthc);
		sptL5 = indexL - pdelayc - (fl5 >> 8);	/* integral part of delay */
		if(sptL5 < 0) {sptL5 += sizeL;}	
		for(i = 0; i < count; i++) {
			/* LFO */
			if(++indexL >= sizeL) {indexL = 0;}
			lfo_val = do_lfo(lfoL);
			fl1 = imuldiv24(lfo_val, depth1);
			sptL1 = indexL - pdelay1 - (fl1 >> 8);	/* integral part of delay */
			fl1 = 0xFF - (fl1 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL1 < 0) {sptL1 += sizeL;}
			fl3 = imuldiv24(lfo_val, depth3);
			sptL3 = indexL - pdelay3 - (fl3 >> 8);	/* integral part of delay */
			fl3 = 0xFF - (fl3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL3 < 0) {sptL3 += sizeL;}
			fl5 = imuldiv24(lfo_val, depth5);
			sptL5 = indexL - pdelay5 - (fl5 >> 8);	/* integral part of delay */
			fl5 = 0xFF - (fl5 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL5 < 0) {sptL5 += sizeL;}
			/* chorus effect */
			/* left */
			tmpL2 = buf[i];
			do_fltl(&tmpL2, bwl);
			ebufL[indexL] = tmpL2 + info->histL * feedbackd;
			tmpL = ebufL[sptL1] * fl1 * DIV_8BIT
				+ ebufL[sptL3] * fl3 * DIV_8BIT
				+ ebufL[sptL5] * fl5 * DIV_8BIT;
		//	info->histL = (info->histL + tmpL * DIV_3) * DIV_2;  // linear intp
			info->histL = tmpL * DIV_3;  // no intp
			buf[i] = info->histL * wetd;
			/* right */
			++i;
		}
		delayL->size = sizeL, delayL->index = indexL;
		info->sptL1 = sptL1, info->sptL3 = sptL3, info->sptL5 = sptL5;
		break;
	case CH_RIGHT:
		/* LFO */
		lfo_val = lfoR->buf[imuldiv24(lfoR->count, lfoR->icycle)];
		fr1 = imuldiv24(lfo_val, depthc);
		sptR1 = indexR - pdelayc - (fr1 >> 8);	/* integral part of delay */
		if(sptR1 < 0) {sptR1 += sizeR;}
		fr3 = imuldiv24(lfo_val, depthc);
		sptR3 = indexR - pdelayc - (fr3 >> 8);	/* integral part of delay */
		if(sptR3 < 0) {sptR3 += sizeR;}
		fr5 = imuldiv24(lfo_val, depthc);
		sptR5 = indexR - pdelayc - (fr5 >> 8);	/* integral part of delay */
		if(sptR5 < 0) {sptR5 += sizeR;}
		for(i = 0; i < count; i++) {
			/* LFO */
			if(++indexR >= sizeR) {indexR = 0;}
			lfo_val = do_lfo(lfoR);
			fr1 = imuldiv24(lfo_val, depth1);
			sptR1 = indexR - pdelay1 - (fr1 >> 8);	/* integral part of delay */
			fr1 = 0xFF - (fr1 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR1 < 0) {sptR1 += sizeR;}
			fr3 = imuldiv24(lfo_val, depth3);
			sptR3 = indexR - pdelay3 - (fr3 >> 8);	/* integral part of delay */
			fr3 = 0xFF - (fr3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR3 < 0) {sptR3 += sizeR;}
			fr5 = imuldiv24(lfo_val, depth5);
			sptR5 = indexR - pdelay5 - (fr5 >> 8);	/* integral part of delay */
			fr5 = 0xFF - (fr5 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR5 < 0) {sptR5 += sizeR;}
			/* chorus effect */
			/* left */
			/* right */
			++i;
			tmpR2 = buf[i];
			ebufR[indexR] = tmpR2 + info->histR * feedbackd;
			tmpR = ebufR[sptR1] * fr1 * DIV_8BIT
				+ ebufR[sptR3] * fr3 * DIV_8BIT
				+ ebufR[sptR5] * fr5 * DIV_8BIT;		
		//	info->histR = (info->histR + tmpR * DIV_3) * DIV_2;  // linear intp
			info->histR = tmpR * DIV_3;  // no intp
			buf[i] = info->histR * wetd;
		}
		delayR->size = sizeR, delayR->index = indexR;
		info->sptR1 = sptR1, info->sptR3 = sptR3, info->sptR5 = sptR5;
		break;
#endif
	}
}


#define CHORUS_P6_WET_LEVEL (2.25 * 0.56)
#define CHORUS_P6_FEEDBACK  0.7
#define CHORUS_P6_DEPTH_DEV (1.0 / (20.0 + 1.0))
#define CHORUS_P6_DELAY_DEV (1.0 / (20.0 * 3.0))
static void do_chorus_p6(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	lfo *lfoL = &(info->lfoL),  *lfoR = &(info->lfoR);
	simple_delay *delayL = &(info->delayL), *delayR = &(info->delayR);
	DATA_T *ebufL = delayL->buf, *ebufR = delayR->buf;
	DATA_T vl0, vl1, vl2, vl3, vl4, vl5, vr0, vr1, vr2, vr3, vr4, vr5;
	int32 sizeL = delayL->size, indexL = delayL->index, sizeR = delayR->size, indexR = delayR->index;
	int32 sptL0 = info->sptL0, sptL1 = info->sptL1, sptL2 = info->sptL2, sptL3 = info->sptL3, sptL4 = info->sptL4, sptL5 = info->sptL5;
	int32 sptR0 = info->sptR0, sptR1 = info->sptR1, sptR2 = info->sptR2, sptR3 = info->sptR3, sptR4 = info->sptR4, sptR5 = info->sptR5;
	FLOAT_T wetd = info->wetd, feedbackd = info->feedbackd;
	int32 depthc = info->depthc, pdelayc = info->pdelayc;
	int32 i, lfo_val, fl0, fl1, fl2, fl3, fl4, fl5, fr0, fr1, fr2, fr3, fr4, fr5;	
	int32 depth0 = info->depth0, depth1 = info->depth1, depth2 = info->depth2, depth3 = info->depth3, depth4 = info->depth4, depth5 = info->depth5,
		pdelay0 = info->pdelay0, pdelay1 = info->pdelay1, pdelay2 = info->pdelay2, pdelay3 = info->pdelay3, pdelay4 = info->pdelay4, pdelay5 = info->pdelay5;
	FLOAT_T tmpL, tmpR, tmpL2, tmpR2;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		if(info->depth_type) // depth [ms] p-p
			info->depthc = info->depth_ms * DIV_2 * playmode_rate_ms; // depth_ms = pp_max , -depth/2~+depth/2
		else // depth [cent]
			info->depthc = calc_chorus_depth_cent(info->depth_cent, info->rate);
		info->pdelayc = info->pdelay_ms * (double)playmode_rate_ms;
		info->pdelayc -= info->depthc / 2;
		if(info->pdelayc <= 1) {info->pdelayc = 1;}
		vl0 = info->depthc * ((double)info->depth_dev * CHORUS_P6_DEPTH_DEV);
		info->depth0 = info->depthc - vl0;
		info->depth1 = info->depthc;
		info->depth2 = info->depthc + vl0;
		info->depth3 = info->depthc + vl0;
		info->depth4 = info->depthc;
		info->depth5 = info->depthc - vl0;
		vl0 = info->pdelayc * ((double)info->pdelay_dev * CHORUS_P6_DELAY_DEV);
		info->pdelay0 = info->pdelayc + vl0;
		info->pdelay1 = info->pdelayc + vl0 * 2;
		info->pdelay2 = info->pdelayc + vl0 * 3;
		info->pdelay3 = info->pdelayc + vl0 * 3;
		info->pdelay4 = info->pdelayc + vl0 * 2;
		info->pdelay5 = info->pdelayc + vl0;
		info->pan0 = 64 - info->pan_dev * 3;
		info->pan1 = 64 - info->pan_dev * 2;
		info->pan2 = 64 - info->pan_dev;
		info->pan3 = 64 + info->pan_dev;
		info->pan4 = 64 + info->pan_dev * 2;
		info->pan5 = 64 + info->pan_dev * 3;
		init_lfo(lfoL, info->rate, LFO_TRIANGULAR, 0);
		init_lfo(lfoR, info->rate, LFO_TRIANGULAR, info->phase_diff);
		set_delay(delayL, (int32)(9600.0 * play_mode->rate / 44100.0));
		set_delay(delayR, (int32)(9600.0 * play_mode->rate / 44100.0));
		info->feedbackd = info->feedback * CHORUS_P6_FEEDBACK * ext_chorus_feedback;
		info->wetd = CHORUS_P6_WET_LEVEL * ext_chorus_level;
		info->histL = info->histR = 0;
		info->sptL0 = info->sptL1 = info->sptL2 = info->sptL3 = info->sptL4 = info->sptL5 = 0;
		info->sptR0 = info->sptR1 = info->sptR2 = info->sptR3 = info->sptR4 = info->sptR5 = 0;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_delay(delayL);
		free_delay(delayR);
		return;
	}
	switch(info->mode){
	case CH_STEREO:
		/* LFO */
		lfo_val = lfoL->buf[imuldiv24(lfoL->count, lfoL->icycle)];
		fl0 = imuldiv24(lfo_val, depthc);
		sptL0 = indexL - pdelayc - (fl0 >> 8);	/* integral part of delay */
		if(sptL0 < 0) {sptL0 += sizeL;}
		fl1 = imuldiv24(lfo_val, depthc);
		sptL1 = indexL - pdelayc - (fl1 >> 8);	/* integral part of delay */
		if(sptL1 < 0) {sptL1 += sizeL;}
		fl2 = imuldiv24(lfo_val, depthc);
		sptL2 = indexL - pdelayc - (fl2 >> 8);	/* integral part of delay */
		if(sptL2 < 0) {sptL2 += sizeL;}
		fl3 = imuldiv24(lfo_val, depthc);
		sptL3 = indexL - pdelayc - (fl3 >> 8);	/* integral part of delay */
		if(sptL3 < 0) {sptL3 += sizeL;}
		fl4 = imuldiv24(lfo_val, depthc);
		sptL4 = indexL - pdelayc - (fl4 >> 8);	/* integral part of delay */
		if(sptL4 < 0) {sptL4 += sizeL;}
		fl5 = imuldiv24(lfo_val, depthc);
		sptL5 = indexL - pdelayc - (fl5 >> 8);	/* integral part of delay */
		if(sptL5 < 0) {sptL5 += sizeL;}	
		lfo_val = lfoR->buf[imuldiv24(lfoR->count, lfoR->icycle)];
		fr0 = imuldiv24(lfo_val, depthc);
		sptR0 = indexR - pdelayc - (fr0 >> 8);	/* integral part of delay */
		if(sptR0 < 0) {sptR0 += sizeR;}
		fr1 = imuldiv24(lfo_val, depthc);
		sptR1 = indexR - pdelayc - (fr1 >> 8);	/* integral part of delay */
		if(sptR1 < 0) {sptR1 += sizeR;}
		fr2 = imuldiv24(lfo_val, depthc);
		sptR2 = indexR - pdelayc - (fr2 >> 8);	/* integral part of delay */
		if(sptR2 < 0) {sptR2 += sizeR;}
		fr3 = imuldiv24(lfo_val, depthc);
		sptR3 = indexR - pdelayc - (fr3 >> 8);	/* integral part of delay */
		if(sptR3 < 0) {sptR3 += sizeR;}
		fr4 = imuldiv24(lfo_val, depthc);
		sptR4 = indexR - pdelayc - (fr4 >> 8);	/* integral part of delay */
		if(sptR4 < 0) {sptR4 += sizeR;}
		fr5 = imuldiv24(lfo_val, depthc);
		sptR5 = indexR - pdelayc - (fr5 >> 8);	/* integral part of delay */
		if(sptR5 < 0) {sptR5 += sizeR;}
		for(i = 0; i < count; i++) {
			/* LFO */
			if(++indexL >= sizeL) {indexL = 0;}
			lfo_val = do_lfo(lfoL);
			fl0 = imuldiv24(lfo_val, depth0);
			sptL0 = indexL - pdelay0 - (fl0 >> 8);	/* integral part of delay */
			fl0 = 0xFF - (fl0 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL0 < 0) {sptL0 += sizeL;}
			fl1 = imuldiv24(lfo_val, depth1);
			sptL1 = indexL - pdelay1 - (fl1 >> 8);	/* integral part of delay */
			fl1 = 0xFF - (fl1 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL1 < 0) {sptL1 += sizeL;}
			fl2 = imuldiv24(lfo_val, depth2);
			sptL2 = indexL - pdelay2 - (fl2 >> 8);	/* integral part of delay */
			fl2 = 0xFF - (fl2 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL2 < 0) {sptL2 += sizeL;}
			fl3 = imuldiv24(lfo_val, depth3);
			sptL3 = indexL - pdelay3 - (fl3 >> 8);	/* integral part of delay */
			fl3 = 0xFF - (fl3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL3 < 0) {sptL3 += sizeL;}
			fl4 = imuldiv24(lfo_val, depth4);
			sptL4 = indexL - pdelay4 - (fl4 >> 8);	/* integral part of delay */
			fl4 = 0xFF - (fl4 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL4 < 0) {sptL4 += sizeL;}
			fl5 = imuldiv24(lfo_val, depth5);
			sptL5 = indexL - pdelay5 - (fl5 >> 8);	/* integral part of delay */
			fl5 = 0xFF - (fl5 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL5 < 0) {sptL5 += sizeL;}
			if(++indexR >= sizeR) {indexR = 0;}
			lfo_val = do_lfo(lfoR);
			fr0 = imuldiv24(lfo_val, depth0);
			sptR0 = indexR - pdelay0 - (fr0 >> 8);	/* integral part of delay */
			fr0 = 0xFF - (fr0 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR0 < 0) {sptR0 += sizeR;}
			fr1 = imuldiv24(lfo_val, depth1);
			sptR1 = indexR - pdelay1 - (fr1 >> 8);	/* integral part of delay */
			fr1 = 0xFF - (fr1 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR1 < 0) {sptR1 += sizeR;}
			fr2 = imuldiv24(lfo_val, depth2);
			sptR2 = indexR - pdelay2 - (fr2 >> 8);	/* integral part of delay */
			fr2 = 0xFF - (fr2 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR2 < 0) {sptR2 += sizeR;}
			fr3 = imuldiv24(lfo_val, depth3);
			sptR3 = indexR - pdelay3 - (fr3 >> 8);	/* integral part of delay */
			fr3 = 0xFF - (fr3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR3 < 0) {sptR3 += sizeR;}
			fr4 = imuldiv24(lfo_val, depth4);
			sptR4 = indexR - pdelay4 - (fr4 >> 8);	/* integral part of delay */
			fr4 = 0xFF - (fr4 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR4 < 0) {sptR4 += sizeR;}
			fr5 = imuldiv24(lfo_val, depth5);
			sptR5 = indexR - pdelay5 - (fr5 >> 8);	/* integral part of delay */
			fr5 = 0xFF - (fr5 & 0xFF);	/* (1 - frac) * 256 */
			if(sptR5 < 0) {sptR5 += sizeR;}
			/* chorus effect */
			/* left */
			tmpL2 = buf[i];
			ebufL[indexL] = tmpL2 + info->histL * feedbackd;
			tmpL = ebufL[sptL0] * fl0 * DIV_8BIT
				+ ebufL[sptL1] * fl1 * DIV_8BIT
				+ ebufL[sptL2] * fl2 * DIV_8BIT
				+ ebufL[sptL3] * fl3 * DIV_8BIT
				+ ebufL[sptL4] * fl4 * DIV_8BIT
				+ ebufL[sptL5] * fl5 * DIV_8BIT;
		//	info->histL = (info->histL + tmpL * DIV_6) * DIV_2;  // linear intp
			info->histL = tmpL * DIV_6;  // no intp
			buf[i] = info->histL * wetd;
			/* right */
			++i;
			tmpR2 = buf[i];
			ebufR[indexR] = tmpR2 + info->histR * feedbackd;
			tmpR = ebufR[sptR0] * fr0 * DIV_8BIT
				+ ebufR[sptR1] * fr1 * DIV_8BIT
				+ ebufR[sptR2] * fr2 * DIV_8BIT
				+ ebufR[sptR3] * fr3 * DIV_8BIT
				+ ebufR[sptR4] * fr4 * DIV_8BIT
				+ ebufR[sptR5] * fr5 * DIV_8BIT;
		//	info->histR = (info->histR + tmpR * DIV_6) * DIV_2;  // linear intp
			info->histR = tmpR * DIV_6;  // no intp
			buf[i] = info->histR * wetd;
		}
		delayL->size = sizeL, delayL->index = indexL, delayR->size = sizeR, delayR->index = indexR;
		info->sptL0 = sptL0, info->sptL1 = sptL1, info->sptL2 = sptL2, info->sptL3 = sptL3, info->sptL4 = sptL4, info->sptL5 = sptL5,
		info->sptR0 = sptR0, info->sptR1 = sptR1, info->sptR2 = sptR2, info->sptR3 = sptR3, info->sptR4 = sptR4, info->sptR5 = sptR5;
		break;
#if 0
	case CH_MIX_STEREO:
		/* LFO */
		lfo_val = lfoL->buf[imuldiv24(lfoL->count, lfoL->icycle)];
		fl0 = imuldiv24(lfo_val, depthc);
		sptL0 = indexL - pdelayc - (fl0 >> 8);	/* integral part of delay */
		if(sptL0 < 0) {sptL0 += sizeL;}
		fl1 = imuldiv24(lfo_val, depthc);
		sptL1 = indexL - pdelayc - (fl1 >> 8);	/* integral part of delay */
		if(sptL1 < 0) {sptL1 += sizeL;}
		fl2 = imuldiv24(lfo_val, depthc);
		sptL2 = indexL - pdelayc - (fl2 >> 8);	/* integral part of delay */
		if(sptL2 < 0) {sptL2 += sizeL;}
		fl3 = imuldiv24(lfo_val, depthc);
		sptL3 = indexL - pdelayc - (fl3 >> 8);	/* integral part of delay */
		if(sptL3 < 0) {sptL3 += sizeL;}
		fl4 = imuldiv24(lfo_val, depthc);
		sptL4 = indexL - pdelayc - (fl4 >> 8);	/* integral part of delay */
		if(sptL4 < 0) {sptL4 += sizeL;}
		fl5 = imuldiv24(lfo_val, depthc);
		sptL5 = indexL - pdelayc - (fl5 >> 8);	/* integral part of delay */
		if(sptL5 < 0) {sptL5 += sizeL;}	
		for(i = 0; i < count; i++) {
			/* LFO */
			if(++indexL >= sizeL) {indexL = 0;}
			lfo_val = do_lfo(lfoL);
			fl0 = imuldiv24(lfo_val, depth0);
			sptL0 = indexL - pdelay0 - (fl0 >> 8);	/* integral part of delay */
			fl0 = 0xFF - (fl0 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL0 < 0) {sptL0 += sizeL;}
			fl1 = imuldiv24(lfo_val, depth1);
			sptL1 = indexL - pdelay1 - (fl1 >> 8);	/* integral part of delay */
			fl1 = 0xFF - (fl1 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL1 < 0) {sptL1 += sizeL;}
			fl2 = imuldiv24(lfo_val, depth2);
			sptL2 = indexL - pdelay2 - (fl2 >> 8);	/* integral part of delay */
			fl2 = 0xFF - (fl2 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL2 < 0) {sptL2 += sizeL;}
			fl3 = imuldiv24(lfo_val, depth3);
			sptL3 = indexL - pdelay3 - (fl3 >> 8);	/* integral part of delay */
			fl3 = 0xFF - (fl3 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL3 < 0) {sptL3 += sizeL;}
			fl4 = imuldiv24(lfo_val, depth4);
			sptL4 = indexL - pdelay4 - (fl4 >> 8);	/* integral part of delay */
			fl4 = 0xFF - (fl4 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL4 < 0) {sptL4 += sizeL;}
			fl5 = imuldiv24(lfo_val, depth5);
			sptL5 = indexL - pdelay5 - (fl5 >> 8);	/* integral part of delay */
			fl5 = 0xFF - (fl5 & 0xFF);	/* (1 - frac) * 256 */
			if(sptL5 < 0) {sptL5 += sizeL;}
			/* chorus effect */
			/* mix */
			tmpL2 = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			ebufL[indexL] = tmpL2 + (info->histL + info->histR) * feedbackd;
			vl0 = ebufL[sptL0] * fl0 * DIV_8BIT;
			vl1 = ebufL[sptL1] * fl1 * DIV_8BIT;
			vl2 = ebufL[sptL2] * fl2 * DIV_8BIT;
			vl3 = ebufL[sptL3] * fl3 * DIV_8BIT;
			vl4 = ebufL[sptL4] * fl4 * DIV_8BIT;
			vl5 = ebufL[sptL5] * fl5 * DIV_8BIT;
			tmpL = do_left_panning(vl0, info->pan0)
				+ do_left_panning(vl1, info->pan1)
				+ do_left_panning(vl2, info->pan2)
				+ do_left_panning(vl3, info->pan3)
				+ do_left_panning(vl4, info->pan4)
				+ do_left_panning(vl5, info->pan5);
			tmpR = do_right_panning(vl0, info->pan0)
				+ do_right_panning(vl1, info->pan1)
				+ do_right_panning(vl2, info->pan2)
				+ do_right_panning(vl3, info->pan3)
				+ do_right_panning(vl4, info->pan4)
				+ do_right_panning(vl5, info->pan5);
		//	info->histL = (info->histL + tmpL * DIV_6) * DIV_2;  // linear intp
		//	info->histR = (info->histR + tmpR * DIV_6) * DIV_2;  // linear intp
			info->histL = tmpL * DIV_6;  // no intp
			info->histR = tmpR * DIV_6;  // no intp
			buf[i] = info->histL * wetd;
			++i;
			buf[i] = info->histR * wetd;
		}
		delayL->size = sizeL, delayL->index = indexL, delayR->size = sizeR, delayR->index = indexR;
		info->sptL0 = sptL0, info->sptL1 = sptL1, info->sptL2 = sptL2, info->sptL3 = sptL3, info->sptL4 = sptL4, info->sptL5 = sptL5,
		info->sptR0 = sptR0, info->sptR1 = sptR1, info->sptR2 = sptR2, info->sptR3 = sptR3, info->sptR4 = sptR4, info->sptR5 = sptR5;
		break;
#endif
	}
}

#define CHORUS_EX_LEVEL 0.5
#define CHORUS_EX_FEEDBACK  0.6
int ext_chorus_ex_phase = 3;
int ext_chorus_ex_lite = 0;
int ext_chorus_ex_ov = 0;

static void do_chorus_ex_none(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode0_chST(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode0_chMXST(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode0_chMNST(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode0_chMXMN(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode0_chMN(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode0_chL(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode0_chR(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode1_chST(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode1_chMXST(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode1_chMNST(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode1_chMXMN(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode1_chMN(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode1_chL(DATA_T *buf, int32 count, InfoStereoChorus *info);
static void do_chorus_ex_mode1_chR(DATA_T *buf, int32 count, InfoStereoChorus *info);

static void init_chorus_ex(InfoStereoChorus *info)
{
	int i;
	int32 size, byte;
	FLOAT_T div_phase, ch_diff, depth_cnt, pdelay_cnt, depth2;
	if(!info->init){
		// 1000ms : pre_delay(GSmax=100ms XGmax=50ms) + depth max 40ms + safety
		size = 1000 * playmode_rate_ms;
		byte = sizeof(DATA_T) * (size + 1) * 2; // +1 interp, * 2ch
#ifdef ALIGN_SIZE
		info->buf = (DATA_T*)aligned_malloc(byte, ALIGN_SIZE);
#else
		info->buf = (DATA_T*)safe_malloc(byte);
#endif
		if(!info->buf){
			info->do_chorus_mode = do_chorus_ex_none;
			return;
		}
		memset(info->buf, 0, byte);
		info->sptR0 = size;
		info->sptL0 = 0; // delay_count
		info->hist[0] = info->hist[1] = 0;
		info->init = 1;
	}
	div_phase = 1.0 / (FLOAT_T)info->phase; // phase > 0
	info->feedbackd = info->feedback * CHORUS_EX_FEEDBACK * ext_chorus_feedback;
	if(info->mode == CH_MIX_STEREO || info->mode == CH_MONO_STEREO)
		info->div_out = pow(1.0 / sqrt((FLOAT_T)info->phase), 0.666666666);
	else
		info->div_out = pow((FLOAT_T)div_phase, 0.666666666);
	info->wetd = CHORUS_EX_LEVEL * ext_chorus_level;
	pdelay_cnt = info->pdelay_ms * playmode_rate_ms;
	if(pdelay_cnt <= 1.0) {pdelay_cnt = 1.0;}
	if(info->depth_type) // depth [ms] p-p
		depth_cnt = info->depth_ms * playmode_rate_ms; // depth_ms = pp_max , -depth
	else // depth [cent]
		depth_cnt = calc_chorus_depth_cent(info->depth_cent, info->rate);
	info->lfo_rate = info->rate * div_playmode_rate;
	ch_diff = info->phase_diff * DIV_360; // deg 0 ~ 360
	if(info->phase == 1){
		info->pan[0] = 0x40;
		info->lfo_phase[0][0] = info->lfo_phase[0][1] = 0;
		info->delay[0] = pdelay_cnt;
		info->depth[0] = depth_cnt;
	}else{
		FLOAT_T phase_d2 = (FLOAT_T)info->phase * DIV_2;
		for (i = 0; i < info->phase; i++) {
			int sign = (i & 0x1) ? (-1) : (1);
			FLOAT_T add_diff = (FLOAT_T)i * div_phase;
			FLOAT_T delay_diff = (FLOAT_T)info->pdelay_dev * DIV_20 * add_diff * DIV_4; // 25%
			FLOAT_T depth_diff = (FLOAT_T)info->depth_dev * DIV_20 * add_diff * DIV_4; // 25%
			FLOAT_T pan_diff;
			if(i < phase_d2){
				info->delay[i] = pdelay_cnt * (1.0 + sign * delay_diff);
				info->depth[i] = depth_cnt * (1.0 + sign * depth_diff);
			}else{
				info->delay[i] = pdelay_cnt * (1.0 - sign * delay_diff);
				info->depth[i] = depth_cnt * (1.0 - sign * depth_diff);
			}
			info->lfo_phase[i][0] = (add_diff);
			info->lfo_phase[i][1] = (add_diff + ch_diff);
			pan_diff = (FLOAT_T)i / (FLOAT_T)(info->phase - 1); // 0.0 ~ 1.0
			pan_diff -= 0.5; // -0.5 ~ 0.5
			pan_diff *= info->pan_dev * DIV_20; // 0% = all center , 100% = full panning
			pan_diff += 0.5; // max case 0.0 ~ 1.0
			pan_diff *= 127; // 0.0 ~ 127.0
			pan_diff += 0.5; // for round
			info->pan[i] = ((int32)pan_diff) & 0x7F;				
		}
	}
	switch(info->filter_type){
	default:
	case 0:
		init_sample_filter(&info->fc, info->filter_cutoff, 0, FILTER_NONE);
		break;
	case 1:
		init_sample_filter(&info->fc, info->filter_cutoff, 0, FILTER_LPF6);
		break;
	case 2:
		init_sample_filter(&info->fc, info->filter_cutoff, 0, FILTER_HPF6);
		break;
	}
	switch(info->mode){
	case CH_STEREO:	
		info->do_chorus_mode = ext_chorus_ex_ov ? do_chorus_ex_mode1_chST : do_chorus_ex_mode0_chST;
		break;
	case CH_MIX_STEREO:
		info->do_chorus_mode = ext_chorus_ex_ov ? do_chorus_ex_mode1_chMXST : do_chorus_ex_mode0_chMXST;
		break;
	case CH_MONO_STEREO:
		info->do_chorus_mode = ext_chorus_ex_ov ? do_chorus_ex_mode1_chMNST : do_chorus_ex_mode0_chMNST;
		break;
	case CH_MIX_MONO:
		info->do_chorus_mode = ext_chorus_ex_ov ? do_chorus_ex_mode1_chMXMN : do_chorus_ex_mode0_chMXMN;
		break;
	case CH_MONO:
		info->do_chorus_mode = ext_chorus_ex_ov ? do_chorus_ex_mode1_chMN : do_chorus_ex_mode0_chMN;
		break;
	case CH_LEFT:
		info->do_chorus_mode = ext_chorus_ex_ov ? do_chorus_ex_mode1_chL : do_chorus_ex_mode0_chL;
		break;
	case CH_RIGHT:
		info->do_chorus_mode = ext_chorus_ex_ov ? do_chorus_ex_mode1_chR : do_chorus_ex_mode0_chR;
		break;
	}
}

static void free_chorus_ex(InfoStereoChorus *info)
{
	if(!info->init)
		return;
	if(!info->buf)
		return;	
#ifdef ALIGN_SIZE
	aligned_free(info->buf);	
#else
	safe_free(info->buf);	
#endif
	info->buf = NULL;
	info->init = 0;
}


static void do_chorus_ex_none(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	memset(info->buf, 0, sizeof(DATA_T) * count);
}


#if (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE) && defined(FLOAT_T_DOUBLE)
static void do_chorus_ex_mode0_chST(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j;
	uint8 phase = info->phase;
	int32 size = info->sptR0, delay_count = info->sptL0;
	DATA_T *ebufL = &info->buf[0], *ebufR = &info->buf[size + 1];
	FLOAT_T *delay = info->delay, *depth = info->depth, lfo_count = info->lfo_count, lfo_rate = info->lfo_rate;
	__m128d vec_sizef = _mm_set1_pd((double)size);
	__m128d vec_feedback = MM_LOAD1_PD(&info->feedbackd);
	__m128d vec_div_out = MM_LOAD1_PD(&info->div_out);
	__m128d vec_wet = MM_LOAD1_PD(&info->wetd);
	__m128d vec_input, vec_tmp1, vec_hist = _mm_loadu_pd(info->hist);
	__m128d vec_delay_ccf;
	ALIGN DATA_T input[2];	
	// CH_STEREO		
	for (i = 0; i < count; i += 2) {
		if(!delay_count){
			ebufL[size] = ebufL[0]; // for linear interpolation
			ebufR[size] = ebufR[0]; // for linear interpolation
		}
		if(++delay_count >= size) {delay_count = 0;}
		lfo_count += lfo_rate;
		lfo_count = lfo_count - floor(lfo_count);
		vec_input = _mm_load_pd(&buf[i]);
		sample_filter_stereo2(&info->fc, (DATA_T *)&vec_input);
		vec_input = _mm_add_pd(vec_input, _mm_mul_pd(vec_hist, vec_feedback));
		_mm_storel_pd(&ebufL[delay_count], vec_input);
		_mm_storeh_pd(&ebufR[delay_count], vec_input);
		vec_delay_ccf = _mm_cvtepi32_pd(_mm_set1_epi32(delay_count));
		vec_tmp1 = _mm_setzero_pd();
		for (j = 0; j < phase; j++) {
			__m128d vec_v1, vec_v2, vec_fp, vec_fp2, vec_add_size, vin1, vin2;
			__m128i vec_index;
			__m128d vec_depth = _mm_loadu_pd(&depth[j]);
			__m128d vec_delay = _mm_loadu_pd(&delay[j]);
			ALIGN int32 tmpi[4];			
			vec_fp = _mm_set_pd(
				lookup2_sine_p(lfo_count + info->lfo_phase[j][1]), 
				lookup2_sine_p(lfo_count + info->lfo_phase[j][0]) );
			vec_fp = _mm_sub_pd(_mm_sub_pd(vec_delay_ccf, vec_delay), _mm_mul_pd(vec_depth, vec_fp));
			vec_fp = _mm_add_pd(vec_fp, _mm_and_pd(vec_sizef, _mm_cmplt_pd(vec_fp, _mm_setzero_pd())));		
			vec_index = _mm_cvttpd_epi32(vec_fp);	
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1 floor
			vec_fp = _mm_sub_pd(vec_fp, _mm_floor_pd(vec_fp));
#else
			vec_fp = _mm_sub_pd(vec_fp, _mm_cvtepi32_pd(vec_index));
#endif
			vin1 = _mm_loadu_pd(&ebufL[_mm_cvtsi128_si32(vec_index)]); // L, L+1
			vin2 = _mm_loadu_pd(&ebufR[MM_EXTRACT_EPI32(vec_index, 0x1)]); // R, R+1
			vec_v1 = _mm_shuffle_pd(vin1, vin2, 0x0); //  L, R
			vec_v2 = _mm_shuffle_pd(vin1, vin2, 0x3); //  L+1, R+1
			vec_v2 = _mm_sub_pd(vec_v2, vec_v1);
			vec_tmp1 = _mm_add_pd(vec_tmp1, MM_FMA_PD(vec_v2, vec_fp, vec_v1)); // linear interpolation
		}
		vec_tmp1 = MM_MSUB_PD(vec_tmp1, vec_div_out, vec_input);
		vec_hist = _mm_mul_pd(vec_tmp1, vec_div_out);
		_mm_store_pd(&buf[i], _mm_mul_pd(vec_hist, vec_wet));
	}
	_mm_storeu_pd(info->hist, vec_hist);
	info->sptL0 = delay_count, info->lfo_count = lfo_count;
}

#else
static void do_chorus_ex_mode0_chST(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j;
	uint8 phase = info->phase;
	int32 size = info->sptR0, delay_count = info->sptL0;
	DATA_T *ebufL = &info->buf[0], *ebufR = &info->buf[size + 1], histL = info->hist[0], histR = info->hist[1];
	int32 *pan = info->pan;
	FLOAT_T *delay = info->delay, *depth = info->depth, 
		lfo_count = info->lfo_count, lfo_rate = info->lfo_rate;
	FLOAT_T feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmpL, tmpR, inputL, inputR;

	// CH_STEREO		
	for (i = 0; i < count; i++) {
		if(!delay_count){
			ebufL[size] = ebufL[0]; // for linear interpolation
			ebufR[size] = ebufR[0]; // for linear interpolation
		}
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		inputL = buf[i];	
		inputR = buf[i + 1];
		sample_filter_stereo(&info->fc, &inputL, &inputR);
		ebufL[delay_count] = inputL + histL * feedbackd;
		ebufR[delay_count] = inputR + histR * feedbackd;
		tmpL = 0;	tmpR = 0;
		for (j = 0; j < phase; j++) {
			int32 indexL, indexR;
			DATA_T v1L, v2L, v1R, v2R;
			FLOAT_T fp1L, fp2L, fp1R, fp2R;		
			fp1L = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p(lfo_count + info->lfo_phase[j][0]);	
			fp1R = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p(lfo_count + info->lfo_phase[j][1]);	
			if(fp1L < 0) {fp1L += size;}
			if(fp1R < 0) {fp1R += size;}				
			fp2L = floor(fp1L); fp2R = floor(fp1R);
			indexL = fp2L; indexR = fp2R;
			v1L = ebufL[indexL]; v2L = ebufL[indexL + 1];
			v1R = ebufR[indexR]; v2R = ebufR[indexR + 1];
			tmpL += v1L + (v2L - v1L) * (fp1L - fp2L); // linear interpolation
			tmpR += v1R + (v2R - v1R) * (fp1R - fp2R); // linear interpolation
		}
		histL = tmpL * div_out; histR = tmpR * div_out;		
		buf[i] = histL * wetd; buf[++i] = histR * wetd;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[0] = histL, info->hist[1] = histR;
}
#endif

static void do_chorus_ex_mode0_chMXST(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j, phase = info->phase, size = info->sptR0, delay_count = info->sptL0, *pan = info->pan;
	DATA_T *ebufL = info->buf, histL = info->hist[0];
	FLOAT_T *delay = info->delay, *depth = info->depth, lfo_count = info->lfo_count, lfo_rate = info->lfo_rate,
		feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmp, tmpL, tmpR, inputL;

	// CH_MIX_STEREO:
	for (i = 0; i < count; i++) {
		if(!delay_count) {ebufL[size] = ebufL[0];} // for linear interpolation
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		inputL = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
		sample_filter_left(&info->fc, &inputL);
		ebufL[delay_count] = inputL + histL * feedbackd;
		tmpL = tmpR = tmp = 0;
		for (j = 0; j < phase; j++) {
			int32 index;
			DATA_T v1, v2, v3;
			FLOAT_T fp1, fp2;				
			fp1 = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p(lfo_count + info->lfo_phase[j][0]);	
			if(fp1 < 0) {fp1 += size;}				
			fp2 = floor(fp1);	
			index = fp2;
			v1 = ebufL[index];
			v2 = ebufL[index + 1];
			v3 = v1 + (v2 - v1) * (fp1 - fp2); // linear interpolation
			tmp += v3;
			tmpL += do_left_panning(v3, pan[j]);
			tmpR += do_right_panning(v3, pan[j]);
		}
		histL = tmp * div_out;
		tmpL *= wetd; tmpR *= wetd;
		buf[i] = tmpL; buf[++i] = tmpR;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[0] = histL;
}

static void do_chorus_ex_mode0_chMNST(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j, phase = info->phase, size = info->sptR0, delay_count = info->sptL0, *pan = info->pan;
	DATA_T *ebufL = info->buf, histL = info->hist[0];
	FLOAT_T *delay = info->delay, *depth = info->depth, lfo_count = info->lfo_count, lfo_rate = info->lfo_rate,
		feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmp, tmpL, tmpR, outL, inputL;

	// CH_MONO_STEREO:
	for (i = 0; i < count; i++) {
		if(!delay_count) {ebufL[size] = ebufL[0];} // for linear interpolation
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		inputL = buf[i];
		sample_filter_left(&info->fc, &inputL);
		ebufL[delay_count] = inputL + histL * feedbackd;
		tmpL = tmpR = tmp = 0;
		for (j = 0; j < phase; j++) {
			int32 index;
			DATA_T v1, v2, v3;
			FLOAT_T fp1, fp2;	
			fp1 = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p((lfo_count + info->lfo_phase[j][0]));	
			if(fp1 < 0) {fp1 += size;}					
			fp2 = floor(fp1);	
			index = fp2;
			v1 = ebufL[index];
			v2 = ebufL[index + 1];
			v3 = v1 + (v2 - v1) * (fp1 - fp2); // linear interpolation
			tmp += v3;
			tmpL += do_left_panning(v3, pan[j]);
			tmpR += do_right_panning(v3, pan[j]);
		}
		histL = tmp * div_out;
		tmpL *= wetd; tmpR *= wetd;
		buf[i] = tmpL; buf[++i] = tmpR;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[0] = histL;
}

static void do_chorus_ex_mode0_chMXMN(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j, phase = info->phase, size = info->sptR0, delay_count = info->sptL0, *pan = info->pan;
	DATA_T *ebufL = info->buf, histL = info->hist[0];
	FLOAT_T *delay = info->delay, *depth = info->depth, lfo_count = info->lfo_count, lfo_rate = info->lfo_rate,
		feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmp, tmpL, inputL;

	//  CH_MIX_MONO:
	for (i = 0; i < count; i++) {
		if(!delay_count) {ebufL[size] = ebufL[0];} // for linear interpolation
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}		
		inputL = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
		sample_filter_left(&info->fc, &inputL);
		ebufL[delay_count] = inputL + histL * feedbackd;
		tmpL = 0;
		for (j = 0; j < phase; j++) {
			int32 index;
			DATA_T v1, v2;
			FLOAT_T fp1, fp2;	
			fp1 = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p((lfo_count + info->lfo_phase[j][0]));	
			if(fp1 < 0) {fp1 += size;}					
			fp2 = floor(fp1);	
			index = fp2;
			v1 = ebufL[index];
			v2 = ebufL[index + 1];
			tmpL += v1 + (v2 - v1) * (fp1 - fp2); // linear interpolation
		}
		histL = tmpL * div_out;	
		tmpL = histL * wetd;
		buf[i] = tmpL; buf[++i] = tmpL;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[0] = histL;
}

static void do_chorus_ex_mode0_chMN(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j, phase = info->phase, size = info->sptR0, delay_count = info->sptL0, *pan = info->pan;
	DATA_T *ebufL = info->buf, histL = info->hist[0];
	FLOAT_T *delay = info->delay, *depth = info->depth, lfo_count = info->lfo_count, lfo_rate = info->lfo_rate,
		feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmpL, inputL;

	//  CH_MONO:
	for (i = 0; i < count; i++) {
		if(!delay_count) {ebufL[size] = ebufL[0];} // for linear interpolation
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}				
		inputL = buf[i];		
		sample_filter_left(&info->fc, &inputL);
		ebufL[delay_count] = inputL + histL * feedbackd;
		tmpL = 0;
		for (j = 0; j < phase; j++) {
			int32 index;
			DATA_T v1, v2;
			FLOAT_T fp1, fp2;	
			fp1 = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p((lfo_count + info->lfo_phase[j][0]));	
			if(fp1 < 0) {fp1 += size;}					
			fp2 = floor(fp1);	
			index = fp2;
			v1 = ebufL[index];
			v2 = ebufL[index + 1];
			tmpL += v1 + (v2 - v1) * (fp1 - fp2); // linear interpolation
		}
		histL = tmpL * div_out;	
		tmpL = histL * wetd;
		buf[i] = tmpL; buf[++i] = tmpL;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[0] = histL;
}

static void do_chorus_ex_mode0_chL(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j;
	uint8 phase = info->phase;
	int32 size = info->sptR0, delay_count = info->sptL0;
	DATA_T *ebufL = info->buf, histL = info->hist[0];
	int32 *pan = info->pan;
	FLOAT_T *delay = info->delay, *depth = info->depth,
		lfo_count = info->lfo_count, lfo_rate = info->lfo_rate;
	FLOAT_T feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmpL, inputL;

	//  CH_LEFT:
	for (i = 0; i < count; i++) {	
		if(!delay_count) {ebufL[size] = ebufL[0];} // for linear interpolation
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		inputL = buf[i];
		sample_filter_left(&info->fc, &inputL);
		ebufL[delay_count] = inputL + histL * feedbackd;
		tmpL = 0;
		for (j = 0; j < phase; j++) {
			int32 index;
			DATA_T v1, v2;
			FLOAT_T fp1, fp2;	
			fp1 = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p((lfo_count + info->lfo_phase[j][0]));	
			if(fp1 < 0) {fp1 += size;}					
			fp2 = floor(fp1);	
			index = fp2;
			v1 = ebufL[index];
			v2 = ebufL[index + 1];
			tmpL += v1 + (v2 - v1) * (fp1 - fp2); // linear interpolation
		}
		histL = tmpL * div_out;
		buf[i++] = histL * wetd;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[0] = histL;
}

static void do_chorus_ex_mode0_chR(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j;
	uint8 phase = info->phase;
	int32 size = info->sptR0, delay_count = info->sptL0;
	DATA_T *ebufR = info->buf, histR = info->hist[1];
	int32 *pan = info->pan;
	FLOAT_T *delay = info->delay, *depth = info->depth,	
		lfo_count = info->lfo_count, lfo_rate = info->lfo_rate;
	FLOAT_T feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmpR, inputR;

	//  CH_RIGHT:
	for (i = 0; i < count; i++) {	
		if(!delay_count) {ebufR[size] = ebufR[0];} // for linear interpolation
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		inputR = buf[++i];
		sample_filter_right(&info->fc, &inputR);
		ebufR[delay_count] = inputR + histR * feedbackd;
		tmpR = 0;
		for (j = 0; j < phase; j++) {
			int32 index;
			DATA_T v1, v2;
			FLOAT_T fp1, fp2;	
			fp1 = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p((lfo_count + info->lfo_phase[j][1]));	
			if(fp1 < 0) {fp1 += size;}					
			fp2 = floor(fp1);	
			index = fp2;
			v1 = ebufR[index];
			v2 = ebufR[index + 1];
			tmpR += v1 + (v2 - v1) * (fp1 - fp2); // linear interpolation
		}
		histR = tmpR * div_out;
		buf[i] = histR * wetd;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[1] = histR;
}


// chorus_ex over sampling mod
#if (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE) && defined(FLOAT_T_DOUBLE)
static void do_chorus_ex_mode1_chST(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j;
	uint8 phase = info->phase;
	int32 size = info->sptR0, delay_count = info->sptL0;
	DATA_T *ebufL = &info->buf[0], *ebufR = &info->buf[size + 1];
	FLOAT_T *delay = info->delay, *depth = info->depth, lfo_count = info->lfo_count, lfo_rate = info->lfo_rate * DIV_2;
	__m128d vec_sizef = _mm_set1_pd((double)size);
	__m128d vec_feedback = MM_LOAD1_PD(&info->feedbackd);
	__m128d vec_div_out = MM_LOAD1_PD(&info->div_out);
	__m128d vec_wet = MM_LOAD1_PD(&info->wetd);
	__m128d vec_input, vec_tmp1, vec_hist = _mm_loadu_pd(info->hist);
	__m128d vec_delay_ccf;
	ALIGN DATA_T input[2];	
	FLOAT_T lfoc1, lfoc2;
	const __m128d vec_div2 = _mm_set1_pd((double)DIV_2);
	// CH_STEREO		
	for (i = 0; i < count; i += 2) {
		if(!delay_count){
			ebufL[size] = ebufL[0]; // for linear interpolation
			ebufR[size] = ebufR[0]; // for linear interpolation
		}
		if(++delay_count >= size) {delay_count = 0;}
		lfo_count += lfo_rate;
		lfoc1 = lfo_count = lfo_count - floor(lfo_count);
		lfo_count += lfo_rate;
		lfoc2 = lfo_count = lfo_count - floor(lfo_count);
		vec_input = _mm_load_pd(&buf[i]);
		sample_filter_stereo2(&info->fc, (DATA_T *)&vec_input);
		vec_input = _mm_add_pd(vec_input, _mm_mul_pd(vec_hist, vec_feedback));
		_mm_storel_pd(&ebufL[delay_count], vec_input);
		_mm_storeh_pd(&ebufR[delay_count], vec_input);
		vec_delay_ccf = _mm_cvtepi32_pd(_mm_set1_epi32(delay_count));
		vec_tmp1 = _mm_setzero_pd();
		for (j = 0; j < phase; j++) {
			__m128d vec_v11, vec_v21, vec_fp11, vec_fp21, vec_add_size1, vin11, vin21;
			__m128d vec_v12, vec_v22, vec_fp12, vec_fp22, vec_add_size2, vin12, vin22;
			__m128i vec_index1, vec_index2;
			__m128d vec_depth = _mm_loadu_pd(&depth[j]);
			__m128d vec_delay = _mm_loadu_pd(&delay[j]);
			__m128d vec_mix = _mm_setzero_pd();
			ALIGN int32 tmpi[4];			
			vec_fp11 = _mm_set_pd(
				lookup2_sine_p(lfoc1 + info->lfo_phase[j][1]), 
				lookup2_sine_p(lfoc1 + info->lfo_phase[j][0]) );
			vec_fp12 = _mm_set_pd(
				lookup2_sine_p(lfoc2 + info->lfo_phase[j][1]), 
				lookup2_sine_p(lfoc2 + info->lfo_phase[j][0]) );
			vec_fp11 = _mm_sub_pd(_mm_sub_pd(vec_delay_ccf, vec_delay), _mm_mul_pd(vec_depth, vec_fp11));
			vec_fp11 = _mm_add_pd(vec_fp11, _mm_and_pd(vec_sizef, _mm_cmplt_pd(vec_fp11, _mm_setzero_pd())));	
			vec_fp12 = _mm_sub_pd(_mm_sub_pd(_mm_add_pd(vec_delay_ccf, vec_div2), vec_delay), _mm_mul_pd(vec_depth, vec_fp12));
			vec_fp12 = _mm_add_pd(vec_fp12, _mm_and_pd(vec_sizef, _mm_cmplt_pd(vec_fp12, _mm_setzero_pd())));		
			vec_index1 = _mm_cvttpd_epi32(vec_fp11);		
			vec_index2 = _mm_cvttpd_epi32(vec_fp12);	
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1 floor
			vec_fp11 = _mm_sub_pd(vec_fp11, _mm_floor_pd(vec_fp11));
			vec_fp12 = _mm_sub_pd(vec_fp12, _mm_floor_pd(vec_fp12));
#else
			vec_fp11 = _mm_sub_pd(vec_fp11, _mm_cvtepi32_pd(vec_index1));
			vec_fp12 = _mm_sub_pd(vec_fp12, _mm_cvtepi32_pd(vec_index2));
#endif
			vin11 = _mm_loadu_pd(&ebufL[_mm_cvtsi128_si32(vec_index1)]); // L, L+1
			vin21 = _mm_loadu_pd(&ebufR[MM_EXTRACT_EPI32(vec_index1, 0x1)]); // R, R+1
			vin12 = _mm_loadu_pd(&ebufL[_mm_cvtsi128_si32(vec_index2)]); // L, L+1
			vin22 = _mm_loadu_pd(&ebufR[MM_EXTRACT_EPI32(vec_index2, 0x1)]); // R, R+1
			vec_v11 = _mm_shuffle_pd(vin11, vin21, 0x0); //  L, R
			vec_v21 = _mm_shuffle_pd(vin11, vin21, 0x3); //  L+1, R+1
			vec_v12 = _mm_shuffle_pd(vin12, vin22, 0x0); //  L, R
			vec_v22 = _mm_shuffle_pd(vin12, vin22, 0x3); //  L+1, R+1
			vec_v21 = _mm_sub_pd(vec_v21, vec_v11);
			vec_v22 = _mm_sub_pd(vec_v22, vec_v12);
			vec_mix = _mm_add_pd(vec_mix, MM_FMA_PD(vec_v21, vec_fp11, vec_v11));
			vec_mix = _mm_add_pd(vec_mix, MM_FMA_PD(vec_v22, vec_fp12, vec_v12));
			vec_mix = _mm_mul_pd(vec_mix, vec_div2);
			vec_tmp1 = _mm_add_pd(vec_tmp1, vec_mix); // linear interpolation
		}
		vec_tmp1 = MM_MSUB_PD(vec_tmp1, vec_div_out, vec_input);
		vec_hist = _mm_mul_pd(vec_tmp1, vec_div_out);
		_mm_store_pd(&buf[i], _mm_mul_pd(vec_hist, vec_wet));
	}
	_mm_storeu_pd(info->hist, vec_hist);
	info->sptL0 = delay_count, info->lfo_count = lfo_count;
}

#else
static void do_chorus_ex_mode1_chST(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j;
	uint8 phase = info->phase;
	int32 size = info->sptR0, delay_count = info->sptL0;
	DATA_T *ebufL = &info->buf[0], *ebufR = &info->buf[size + 1], histL = info->hist[0], histR = info->hist[1];
	int32 *pan = info->pan;
	FLOAT_T *delay = info->delay, *depth = info->depth, 
		lfo_count = info->lfo_count, lfo_rate = info->lfo_rate * DIV_2;
	FLOAT_T feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmpL, tmpR, inputL, inputR;
	FLOAT_T lfoc1, lfoc2;

	// CH_STEREO		
	for (i = 0; i < count; i++) {
		if(!delay_count){
			ebufL[size] = ebufL[0]; // for linear interpolation
			ebufR[size] = ebufR[0]; // for linear interpolation
		}
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc1 = lfo_count;
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc2 = lfo_count;
		inputL = buf[i];	
		inputR = buf[i + 1];
		sample_filter_stereo(&info->fc, &inputL, &inputR);
		ebufL[delay_count] = inputL + histL * feedbackd;
		ebufR[delay_count] = inputR + histR * feedbackd;
		tmpL = 0;	tmpR = 0;
		for (j = 0; j < phase; j++) {
			int32 indexL1, indexR1, indexL2, indexR2;
			DATA_T v1L1, v2L1, v1R1, v2R1, v1L2, v2L2, v1R2, v2R2;
			FLOAT_T fp1L1, fp2L1, fp1R1, fp2R1, fp1L2, fp2L2, fp1R2, fp2R2;
			FLOAT_T mixL = 0, mixR = 0;
			fp1L1= (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p(lfoc1 + info->lfo_phase[j][0]);	
			fp1R1= (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p(lfoc1 + info->lfo_phase[j][1]);	
			if(fp1L1 < 0) {fp1L1 += size;}
			if(fp1R1 < 0) {fp1R1 += size;}
			fp1L2 = (FLOAT_T)delay_count + 0.5 - delay[j] - depth[j] * lookup2_sine_p(lfoc2 + info->lfo_phase[j][0]);	
			fp1R2 = (FLOAT_T)delay_count + 0.5 - delay[j] - depth[j] * lookup2_sine_p(lfoc2 + info->lfo_phase[j][1]);	
			if(fp1L2 < 0) {fp1L2 += size;}
			if(fp1R2 < 0) {fp1R2 += size;}				
			fp2L1 = floor(fp1L1); fp2R1 = floor(fp1R1);
			fp2L2 = floor(fp1L2); fp2R2 = floor(fp1R2);
			indexL1 = fp2L1; indexR1 = fp2R1;
			indexL2 = fp2L2; indexR2 = fp2R2;
			v1L1 = ebufL[indexL1]; v2L1 = ebufL[indexL1 + 1];
			v1R1 = ebufR[indexR1]; v2R1 = ebufR[indexR1 + 1];
			v1L2 = ebufL[indexL2]; v2L2 = ebufL[indexL2 + 1];
			v1R2 = ebufR[indexR2]; v2R2 = ebufR[indexR2 + 1];
			mixL += v1L1 + (v2L1 - v1L1) * (fp1L1 - fp2L1); // linear interpolation
			mixR += v1R1 + (v2R1 - v1R1) * (fp1R1 - fp2R1); // linear interpolation
			mixL += v1L2 + (v2L2 - v1L2) * (fp1L2 - fp2L2); // linear interpolation
			mixR += v1R2 + (v2R2 - v1R2) * (fp1R2 - fp2R2); // linear interpolation			
			tmpL += mixL * DIV_2; // down samplerate
			tmpR += mixR * DIV_2; // down samplerate
		}
		histL = tmpL * div_out; histR = tmpR * div_out;		
		buf[i] = histL * wetd; buf[++i] = histR * wetd;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[0] = histL, info->hist[1] = histR;
}
#endif

static void do_chorus_ex_mode1_chMXST(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j, phase = info->phase, size = info->sptR0, delay_count = info->sptL0, *pan = info->pan;
	DATA_T *ebufL = info->buf, histL = info->hist[0];
	FLOAT_T *delay = info->delay, *depth = info->depth, lfo_count = info->lfo_count, lfo_rate = info->lfo_rate * DIV_2,
		feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmp, tmpL, tmpR, inputL;
	FLOAT_T lfoc1, lfoc2;

	// CH_MIX_STEREO:
	for (i = 0; i < count; i++) {
		if(!delay_count) {ebufL[size] = ebufL[0];} // for linear interpolation
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc1 = lfo_count;
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc2 = lfo_count;
		inputL = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
		sample_filter_left(&info->fc, &inputL);
		ebufL[delay_count] = inputL + histL * feedbackd;
		tmpL = tmpR = tmp = 0;
		for (j = 0; j < phase; j++) {
			int32 index1, index2;
			DATA_T v11, v21, v12, v22, v3 = 0;
			FLOAT_T fp11, fp21, fp12, fp22;				
			fp11 = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p(lfoc1 + info->lfo_phase[j][0]);	
			if(fp11 < 0) {fp11 += size;}		
			fp12 = (FLOAT_T)delay_count + 0.5 - delay[j] - depth[j] * lookup2_sine_p(lfoc2 + info->lfo_phase[j][0]);	
			if(fp12 < 0) {fp12 += size;}			
			fp21 = floor(fp11);	
			fp22 = floor(fp12);	
			index1 = fp21;
			index2 = fp22;
			v11 = ebufL[index1];
			v21 = ebufL[index1 + 1];
			v12 = ebufL[index2];
			v22 = ebufL[index2 + 1];
			v3 += v11 + (v21 - v11) * (fp11 - fp21); // linear interpolation
			v3 += v12 + (v22 - v12) * (fp12 - fp22); // linear interpolation
			v3 *= DIV_2; // down samplerate
			tmp += v3;
			tmpL += do_left_panning(v3, pan[j]);
			tmpR += do_right_panning(v3, pan[j]);
		}
		histL = tmp * div_out;
		tmpL *= wetd; tmpR *= wetd;
		buf[i] = tmpL; buf[++i] = tmpR;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[0] = histL;
}

static void do_chorus_ex_mode1_chMNST(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j, phase = info->phase, size = info->sptR0, delay_count = info->sptL0, *pan = info->pan;
	DATA_T *ebufL = info->buf, histL = info->hist[0];
	FLOAT_T *delay = info->delay, *depth = info->depth, lfo_count = info->lfo_count, lfo_rate = info->lfo_rate * DIV_2,
		feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmp, tmpL, tmpR, outL, inputL;
	FLOAT_T lfoc1, lfoc2;

	// CH_MONO_STEREO:
	for (i = 0; i < count; i++) {
		if(!delay_count) {ebufL[size] = ebufL[0];} // for linear interpolation
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc1 = lfo_count;
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc2 = lfo_count;
		inputL = buf[i];
		sample_filter_left(&info->fc, &inputL);
		ebufL[delay_count] = inputL + histL * feedbackd;
		tmpL = tmpR = tmp = 0;
		for (j = 0; j < phase; j++) {
			int32 index1, index2;
			DATA_T v11, v21, v12, v22, v3 = 0;
			FLOAT_T fp11, fp21, fp12, fp22;				
			fp11 = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p(lfoc1 + info->lfo_phase[j][0]);	
			if(fp11 < 0) {fp11 += size;}		
			fp12 = (FLOAT_T)delay_count + 0.5 - delay[j] - depth[j] * lookup2_sine_p(lfoc2 + info->lfo_phase[j][0]);	
			if(fp12 < 0) {fp12 += size;}			
			fp21 = floor(fp11);	
			fp22 = floor(fp12);	
			index1 = fp21;
			index2 = fp22;
			v11 = ebufL[index1];
			v21 = ebufL[index1 + 1];
			v12 = ebufL[index2];
			v22 = ebufL[index2 + 1];
			v3 += v11 + (v21 - v11) * (fp11 - fp21); // linear interpolation
			v3 += v12 + (v22 - v12) * (fp12 - fp22); // linear interpolation
			v3 *= DIV_2; // down samplerate
			tmp += v3;
			tmpL += do_left_panning(v3, pan[j]);
			tmpR += do_right_panning(v3, pan[j]);
		}
		histL = tmp * div_out;
		tmpL *= wetd; tmpR *= wetd;
		buf[i] = tmpL; buf[++i] = tmpR;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[0] = histL;
}

static void do_chorus_ex_mode1_chMXMN(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j, phase = info->phase, size = info->sptR0, delay_count = info->sptL0, *pan = info->pan;
	DATA_T *ebufL = info->buf, histL = info->hist[0];
	FLOAT_T *delay = info->delay, *depth = info->depth, lfo_count = info->lfo_count, lfo_rate = info->lfo_rate * DIV_2,
		feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmp, tmpL, inputL;
	FLOAT_T lfoc1, lfoc2;

	//  CH_MIX_MONO:
	for (i = 0; i < count; i++) {
		if(!delay_count) {ebufL[size] = ebufL[0];} // for linear interpolation
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc1 = lfo_count;
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc2 = lfo_count;		
		inputL = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
		sample_filter_left(&info->fc, &inputL);
		ebufL[delay_count] = inputL + histL * feedbackd;
		tmpL = 0;
		for (j = 0; j < phase; j++) {
			int32 index1, index2;
			DATA_T v11, v21, v12, v22, v3 = 0;
			FLOAT_T fp11, fp21, fp12, fp22;				
			fp11 = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p(lfoc1 + info->lfo_phase[j][0]);	
			if(fp11 < 0) {fp11 += size;}		
			fp12 = (FLOAT_T)delay_count + 0.5 - delay[j] - depth[j] * lookup2_sine_p(lfoc2 + info->lfo_phase[j][0]);	
			if(fp12 < 0) {fp12 += size;}			
			fp21 = floor(fp11);	
			fp22 = floor(fp12);	
			index1 = fp21;
			index2 = fp22;
			v11 = ebufL[index1];
			v21 = ebufL[index1 + 1];
			v12 = ebufL[index2];
			v22 = ebufL[index2 + 1];
			v3 += v11 + (v21 - v11) * (fp11 - fp21); // linear interpolation
			v3 += v12 + (v22 - v12) * (fp12 - fp22); // linear interpolation
			tmpL += v3 * DIV_2; // down samplerate
		}
		histL = tmpL * div_out;	
		tmpL = histL * wetd;
		buf[i] = tmpL; buf[++i] = tmpL;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[0] = histL;
}

static void do_chorus_ex_mode1_chMN(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j, phase = info->phase, size = info->sptR0, delay_count = info->sptL0, *pan = info->pan;
	DATA_T *ebufL = info->buf, histL = info->hist[0];
	FLOAT_T *delay = info->delay, *depth = info->depth, lfo_count = info->lfo_count, lfo_rate = info->lfo_rate * DIV_2,
		feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmpL, inputL;
	FLOAT_T lfoc1, lfoc2;

	//  CH_MONO:
	for (i = 0; i < count; i++) {
		if(!delay_count) {ebufL[size] = ebufL[0];} // for linear interpolation
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc1 = lfo_count;
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc2 = lfo_count;			
		inputL = buf[i];		
		sample_filter_left(&info->fc, &inputL);
		ebufL[delay_count] = inputL + histL * feedbackd;
		tmpL = 0;
		for (j = 0; j < phase; j++) {
			int32 index1, index2;
			DATA_T v11, v21, v12, v22, v3 = 0;
			FLOAT_T fp11, fp21, fp12, fp22;				
			fp11 = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p(lfoc1 + info->lfo_phase[j][0]);	
			if(fp11 < 0) {fp11 += size;}		
			fp12 = (FLOAT_T)delay_count + 0.5 - delay[j] - depth[j] * lookup2_sine_p(lfoc2 + info->lfo_phase[j][0]);	
			if(fp12 < 0) {fp12 += size;}			
			fp21 = floor(fp11);	
			fp22 = floor(fp12);	
			index1 = fp21;
			index2 = fp22;
			v11 = ebufL[index1];
			v21 = ebufL[index1 + 1];
			v12 = ebufL[index2];
			v22 = ebufL[index2 + 1];
			v3 += v11 + (v21 - v11) * (fp11 - fp21); // linear interpolation
			v3 += v12 + (v22 - v12) * (fp12 - fp22); // linear interpolation
			tmpL += v3 * DIV_2; // down samplerate
		}
		histL = tmpL * div_out;	
		tmpL = histL * wetd;
		buf[i] = tmpL; buf[++i] = tmpL;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[0] = histL;
}

static void do_chorus_ex_mode1_chL(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j;
	uint8 phase = info->phase;
	int32 size = info->sptR0, delay_count = info->sptL0;
	DATA_T *ebufL = info->buf, histL = info->hist[0];
	int32 *pan = info->pan;
	FLOAT_T *delay = info->delay, *depth = info->depth,
		lfo_count = info->lfo_count, lfo_rate = info->lfo_rate * DIV_2;
	FLOAT_T feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmpL, inputL;
	FLOAT_T lfoc1, lfoc2;

	//  CH_LEFT:
	for (i = 0; i < count; i++) {	
		if(!delay_count) {ebufL[size] = ebufL[0];} // for linear interpolation
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc1 = lfo_count;
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc2 = lfo_count;	
		inputL = buf[i];
		sample_filter_left(&info->fc, &inputL);
		ebufL[delay_count] = inputL + histL * feedbackd;
		tmpL = 0;
		for (j = 0; j < phase; j++) {
			int32 index1, index2;
			DATA_T v11, v21, v12, v22, v3 = 0;
			FLOAT_T fp11, fp21, fp12, fp22;				
			fp11 = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p(lfoc1 + info->lfo_phase[j][0]);	
			if(fp11 < 0) {fp11 += size;}		
			fp12 = (FLOAT_T)delay_count + 0.5 - delay[j] - depth[j] * lookup2_sine_p(lfoc2 + info->lfo_phase[j][0]);	
			if(fp12 < 0) {fp12 += size;}			
			fp21 = floor(fp11);	
			fp22 = floor(fp12);	
			index1 = fp21;
			index2 = fp22;
			v11 = ebufL[index1];
			v21 = ebufL[index1 + 1];
			v12 = ebufL[index2];
			v22 = ebufL[index2 + 1];
			v3 += v11 + (v21 - v11) * (fp11 - fp21); // linear interpolation
			v3 += v12 + (v22 - v12) * (fp12 - fp22); // linear interpolation
			tmpL += v3 * DIV_2; // down samplerate
		}
		histL = tmpL * div_out;
		buf[i++] = histL * wetd;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[0] = histL;
}

static void do_chorus_ex_mode1_chR(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i, j;
	uint8 phase = info->phase;
	int32 size = info->sptR0, delay_count = info->sptL0;
	DATA_T *ebufR = info->buf, histR = info->hist[1];
	int32 *pan = info->pan;
	FLOAT_T *delay = info->delay, *depth = info->depth,	
		lfo_count = info->lfo_count, lfo_rate = info->lfo_rate * DIV_2;
	FLOAT_T feedbackd = info->feedbackd, div_out = info->div_out, wetd = info->wetd;
	DATA_T tmpR, inputR;
	FLOAT_T lfoc1, lfoc2;

	//  CH_RIGHT:
	for (i = 0; i < count; i++) {	
		if(!delay_count) {ebufR[size] = ebufR[0];} // for linear interpolation
		if(++delay_count >= size) {delay_count = 0;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc1 = lfo_count;
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
		lfoc2 = lfo_count;	
		inputR = buf[++i];
		sample_filter_right(&info->fc, &inputR);
		ebufR[delay_count] = inputR + histR * feedbackd;
		tmpR = 0;
		for (j = 0; j < phase; j++) {
			int32 index1, index2;
			DATA_T v11, v21, v12, v22, v3 = 0;
			FLOAT_T fp11, fp21, fp12, fp22;				
			fp11 = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p(lfoc1 + info->lfo_phase[j][1]);	
			if(fp11 < 0) {fp11 += size;}		
			fp12 = (FLOAT_T)delay_count + 0.5 - delay[j] - depth[j] * lookup2_sine_p(lfoc2 + info->lfo_phase[j][1]);	
			if(fp12 < 0) {fp12 += size;}			
			fp21 = floor(fp11);	
			fp22 = floor(fp12);	
			index1 = fp21;
			index2 = fp22;
			v11 = ebufR[index1];
			v21 = ebufR[index1 + 1];
			v12 = ebufR[index2];
			v22 = ebufR[index2 + 1];
			v3 += v11 + (v21 - v11) * (fp11 - fp21); // linear interpolation
			v3 += v12 + (v22 - v12) * (fp12 - fp22); // linear interpolation
			tmpR += v3 * DIV_2; // down samplerate
		}
		histR = tmpR * div_out;
		buf[i] = histR * wetd;
	}
	info->sptL0 = delay_count, info->lfo_count = lfo_count, info->hist[1] = histR;
}

static void do_chorus_ex(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	if(count == MAGIC_INIT_EFFECT_INFO) {
		init_chorus_ex(info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_chorus_ex(info);
		return;
	} else if(count <= 0) {
		return;
	}
	info->do_chorus_mode(buf, count, info);
}


#define CHORUS_3D_LEVEL (1.85)
#define CHORUS_3D_FEEDBACK (0.6)

static void do_3d_chorus(DATA_T *buf, int32 count, Info3DChorus *info)
{
	int32 i;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		int32 size, byte;
		FLOAT_T div_phase, ch_diff, depth_cnt, pdelay_cnt, depth2;
		if(!info->init){
			// 1000ms : pre_delay(GSmax=100ms XGmax=50ms) + depth max 40ms + safety
			size = 1000 * playmode_rate_ms;
			byte = sizeof(DATA_T) * (size + 1) * 2; // +1 interp, * 2ch
			info->buf = (DATA_T*)safe_malloc(byte);
			memset(info->buf, 0, byte);
			info->size = size;
			info->delay_count = 0; // delay_count
			info->hist = 0;
			info->init = 1;
		}
		div_phase = 1.0 / (FLOAT_T)info->phase; // phase > 0
		info->feedbackd = info->feedback * CHORUS_3D_FEEDBACK;
		info->div_out = pow(1.0 / sqrt((FLOAT_T)info->phase), 0.666666666);
		info->wetd = CHORUS_3D_LEVEL;
		pdelay_cnt = info->pdelay_ms * playmode_rate_ms;
		if(pdelay_cnt <= 1.0) {pdelay_cnt = 1.0;}
		if(info->depth_type) // depth [ms] p-p
			depth_cnt = info->depth_ms * playmode_rate_ms; // depth_ms = pp_max , -depth
		else // depth [cent]
			depth_cnt = calc_chorus_depth_cent(info->depth_cent, info->rate);
		info->lfo_rate = info->rate * div_playmode_rate;
		ch_diff = info->phase_diff * DIV_360; // deg 0 ~ 360
		if(info->phase == 1){
			info->azimuth[0] = 0.0;
			info->lfo_phase[0][0] = info->lfo_phase[0][1] = 0;
			info->delay[0] = pdelay_cnt;
			info->depth[0] = depth_cnt;
		}else{
			FLOAT_T phase_d2 = (FLOAT_T)info->phase * DIV_2;
			for (i = 0; i < info->phase; i++) {
				int sign = (i & 0x1) ? (-1) : (1);
				FLOAT_T add_diff = (FLOAT_T)i * div_phase;
				FLOAT_T delay_diff = (FLOAT_T)info->pdelay_dev * DIV_20 * add_diff * DIV_4; // 25%
				FLOAT_T depth_diff = (FLOAT_T)info->depth_dev * DIV_20 * add_diff * DIV_4; // 25%
				FLOAT_T pan_diff;
				if(i < phase_d2){
					info->delay[i] = pdelay_cnt * (1.0 + sign * delay_diff);
					info->depth[i] = depth_cnt * (1.0 + sign * depth_diff);
				}else{
					info->delay[i] = pdelay_cnt * (1.0 - sign * delay_diff);
					info->depth[i] = depth_cnt * (1.0 - sign * depth_diff);
				}
				info->lfo_phase[i][0] = (add_diff);
				info->lfo_phase[i][1] = (add_diff + ch_diff);
				pan_diff = (FLOAT_T)i / (FLOAT_T)(info->phase - 1); // 0.0 ~ 1.0
				pan_diff -= 0.5; // -0.5 ~ 0.5
				pan_diff *= info->pan_dev * DIV_20; // 0% = all center , 100% = full panning
				info->azimuth[i] = pan_diff;
			}
		}
		switch(info->filter_type){
		default:
		case 0:
			init_sample_filter(&info->fc, info->filter_cutoff, 0, FILTER_NONE);
			break;
		case 1:
			init_sample_filter(&info->fc, info->filter_cutoff, 0, FILTER_LPF6);
			break;
		case 2:
			init_sample_filter(&info->fc, info->filter_cutoff, 0, FILTER_HPF6);
			break;
		}
		for (i = 0; i < CHORUS_PHASE_MAX; i++) {
			info->locate[i].out = info->out;
			init_3d_locate(&info->locate[i]);
		}

		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		if(!info->init)
			return;
		if(!info->buf)
			return;	
		safe_free(info->buf);	
		info->buf = NULL;
		info->init = 0;
		for (i = 0; i < CHORUS_PHASE_MAX; i++) {
			uninit_3d_locate(&info->locate[i]);
		}
		return;
	} else if(count <= 0) {
		return;
	}	
	{	
		int32 j, phase = info->phase, size = info->size, delay_count = info->delay_count;
		DATA_T *ebuf = info->buf, hist = info->hist;
		FLOAT_T *delay = info->delay, *depth = info->depth, lfo_count = info->lfo_count, lfo_rate = info->lfo_rate,
			feedbackd = info->feedbackd;
		DATA_T fb, mix[2], input;
		// CH_MIX_STEREO:
		for (i = 0; i < count; i++) {
			if(!delay_count) {ebuf[size] = ebuf[0];} // for linear interpolation
			if(++delay_count >= size) {delay_count = 0;}
			if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}	
			input = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			sample_filter_left(&info->fc, &input);
			ebuf[delay_count] = input + hist * feedbackd;
			mix[0] = mix[1] = fb = 0;
			for (j = 0; j < phase; j++) {
				int32 index;
				DATA_T v1, v2, inout[2];
				FLOAT_T fp1, fp2;				
				fp1 = (FLOAT_T)delay_count - delay[j] - depth[j] * lookup2_sine_p(lfo_count + info->lfo_phase[j][0]);	
				if(fp1 < 0) {fp1 += size;}				
				fp2 = floor(fp1);	
				index = fp2;
				v1 = ebuf[index];
				v2 = ebuf[index + 1];
				inout[0] = v1 + (v2 - v1) * (fp1 - fp2); // linear interpolation
				fb += inout[0];
				do_3d_locate(&info->locate[j], inout, info->azimuth[j]);
				mix[0] += inout[0];
				mix[1] += inout[1];
			}
			hist = fb * info->div_out;
			mix[0] *= info->wetd; mix[1] *= info->wetd;
			buf[i] = mix[0]; buf[++i] = mix[1];
		}
		info->delay_count = delay_count, info->lfo_count = lfo_count, info->hist = hist;
	}
}




/********************************** GS EFFECT core **********************************/

void do_eq2_multi(DATA_T *buf, int32 count, InfoEQ2 *eq)
{
	int i;
	if(count == MAGIC_INIT_EFFECT_INFO) {
		init_sample_filter2(&(eq->lsf), eq->low_freq, eq->low_gain, 0, FILTER_SHELVING_LOW);
		init_sample_filter2(&(eq->hsf), eq->high_freq, eq->high_gain, 0, FILTER_SHELVING_HI);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		return;
	}
	switch(eq->mode){
	case CH_STEREO:
		if(eq->low_gain != 0)
			buffer_filter_stereo(&(eq->lsf), buf, count);
		if(eq->high_gain != 0)
			buffer_filter_stereo(&(eq->hsf), buf, count);
		break;
	case CH_MIX_STEREO:
	case CH_MIX_MONO:
		break;
	case CH_MONO:
		if(eq->low_gain != 0)
			buffer_filter_left(&(eq->lsf), buf, count);
		if(eq->high_gain != 0)
			buffer_filter_left(&(eq->hsf), buf, count);
		for (i = 0; i < count; i++){
			DATA_T tmp = buf[i]; // left to right
			buf[++i] = tmp;
		}
		break;
	case CH_LEFT:
		if(eq->low_gain != 0)
			buffer_filter_left(&(eq->lsf), buf, count);
		if(eq->high_gain != 0)
			buffer_filter_left(&(eq->hsf), buf, count);
		break;
	case CH_RIGHT:
		if(eq->low_gain != 0)
			buffer_filter_right(&(eq->lsf), buf, count);
		if(eq->high_gain != 0)
			buffer_filter_right(&(eq->hsf), buf, count);
		break;
	}
}

static void do_eq3_multi(DATA_T *buf, int32 count, InfoEQ3 *eq)
{
	int i;
	if (count == MAGIC_INIT_EFFECT_INFO) {
		init_sample_filter2(&(eq->lsf), eq->low_freq, eq->low_gain, 0, FILTER_SHELVING_LOW);
		init_sample_filter2(&(eq->hsf), eq->high_freq, eq->high_gain, 0, FILTER_SHELVING_HI);
		init_sample_filter2(&(eq->peak), eq->mid_freq, eq->mid_gain, eq->mid_width, FILTER_PEAKING);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		return;
	}
	switch(eq->mode){
	case CH_STEREO:
		if(eq->low_gain != 0)
			buffer_filter_stereo(&(eq->lsf), buf, count);
		if(eq->high_gain != 0)
			buffer_filter_stereo(&(eq->hsf), buf, count);
		if (eq->mid_gain != 0)
			buffer_filter_stereo(&(eq->peak), buf, count);
		break;
	case CH_MIX_STEREO:
	case CH_MIX_MONO:
		break;
	case CH_MONO:
		if(eq->low_gain != 0)
			buffer_filter_left(&(eq->lsf), buf, count);
		if(eq->high_gain != 0)
			buffer_filter_left(&(eq->hsf), buf, count);
		if (eq->mid_gain != 0)
			buffer_filter_left(&(eq->peak), buf, count);
		for (i = 0; i < count; i++){
			DATA_T tmp = buf[i]; // left to right
			buf[++i] = tmp;
		}
		break;
	case CH_LEFT:
		if(eq->low_gain != 0)
			buffer_filter_left(&(eq->lsf), buf, count);
		if(eq->high_gain != 0)
			buffer_filter_left(&(eq->hsf), buf, count);
		if (eq->mid_gain != 0)
			buffer_filter_left(&(eq->peak), buf, count);
		break;
	case CH_RIGHT:
		if(eq->low_gain != 0)
			buffer_filter_right(&(eq->lsf), buf, count);
		if(eq->high_gain != 0)
			buffer_filter_right(&(eq->hsf), buf, count);
		if (eq->mid_gain != 0)
			buffer_filter_right(&(eq->peak), buf, count);
		break;
	}
}


static inline FLOAT_T do_rm_osc_sine(FLOAT_T in)
{
	return sin(in * M_PI2); // math
//	return lookup2_sine(in); // table2
}

static inline FLOAT_T do_rm_osc_triangular(FLOAT_T in)
{
	if(in < 0.25)
		return in * 4.0; // (in - 0.0) * 4.0;
	else if(in < 0.75)
		return (in - 0.5) * -4.0;
	else // if(in < 1.25)
		return (in - 1.0) * 4.0;
}

#define RING_MOD_LEVEL (1.0)

static void do_ring_modulator_multi(DATA_T *buf, int32 count, InfoRingModulator *info)
{
	int i;
	double osc_freq = info->osc_freq;

	if (count == MAGIC_INIT_EFFECT_INFO) {
		info->osc_freq = info->freq * div_playmode_rate;
		info->osc_rate = 0.0;
		if(info->lfo_sw){
			if(info->wave == LFO_TRIANGULAR)
				info->do_lfo = do_rm_osc_triangular;
			else // sin LFO_SINE
				info->do_lfo = do_rm_osc_sine;
			info->lfo_freq = info->rate * div_playmode_rate;			
			info->lfo_rate = 0.0;
		}
		info->leveld = otd.efx_CustomRMLvOut;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		return;
	} else if(count == 0) {
		return;
	}
	// lfo
	if(info->lfo_sw){
		if((info->lfo_rate += (info->lfo_freq * count * DIV_2)) >= 1.0)
			info->lfo_rate -= floor(info->lfo_rate);
		osc_freq = info->osc_freq * pow(2.0, info->do_lfo(info->lfo_rate) * info->depth);
	}
	switch(info->mode){
	case CH_STEREO:
#if (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE) && defined(FLOAT_T_DOUBLE)
		for (i = 0; i < count; i += 2)
		{
			if((info->osc_rate += osc_freq) >= 1.0)
				info->osc_rate -= floor(info->osc_rate);
			MM_LSU_MUL_PD(&buf[i], _mm_set1_pd(sin(info->osc_rate * M_PI2) * info->leveld));
		}
#else
		for (i = 0; i < count; i++)
		{
			FLOAT_T osc_out;
			if((info->osc_rate += osc_freq) >= 1.0)
				info->osc_rate -= floor(info->osc_rate);
			osc_out = sin(info->osc_rate * M_PI2) * info->leveld;
			buf[i] *= osc_out;
			i++;
			buf[i] *= osc_out;
		}
#endif
		break;
	case CH_LEFT:
		for (i = 0; i < count; i++)
		{
			if((info->osc_rate += osc_freq) >= 1.0)
				info->osc_rate -= floor(info->osc_rate);
			buf[i] *= sin(info->osc_rate * M_PI2) * info->leveld;
			i++;
		}
		break;
	case CH_RIGHT:
		for (i = 0; i < count; i++)
		{
			i++;
			if((info->osc_rate += osc_freq) >= 1.0)
				info->osc_rate -= floor(info->osc_rate);
			buf[i] *= sin(info->osc_rate * M_PI2) * info->leveld;
		}
		break;
	}
}

#define PITCH_SHIFTER_LEVEL (1.0)

static void init_pitch_shifter_core(InfoPitchShifter_core *info)
{
	const FLOAT_T div_phase = 1.0 / (FLOAT_T)PS_CF_PHASE;
	int bytes, i;
	FLOAT_T delay;
	
//	info->feedback = (FLOAT_T)fb * DIV_100; // feedback
	if(info->init_flg && info->pre_delay_ms == info->pre_delay_ms_p && info->ps_delay_ms == info->ps_delay_ms_p){
		if(info->fade_flg == 0){
			if(info->pitch_cent == info->pitch_cent_p)
				return;
			info->fade_flg = 1; // fade out
			init_envelope3(&info->env, 1.0, 5.0 * playmode_rate_ms); // 5ms
			reset_envelope3(&info->env, 0.0, ENVELOPE_KEEP);
		}else if(info->fade_flg == 1){
			info->fade_flg = 2; // fade in
			reset_envelope3(&info->env, 1.0, ENVELOPE_KEEP);
			info->rate = pow((FLOAT_T)2.0, (FLOAT_T)info->pitch_cent * DIV_1200) - 1.0; // pitch_cent
			info->pitch_cent_p = info->pitch_cent;
		}else if(info->fade_flg == 2){
			info->fade_flg = 0; // finish
		}
		return;
	}
	if(!info->init_flg)
		info->fade_flg = 0;
	if(info->ptr != NULL){
		safe_free(info->ptr);
		info->ptr = NULL;
	}		
	info->wdelay = 500 * playmode_rate_ms; // 500ms = pre_delay max100ms + ps_delay max30ms * 2 + safty
	bytes = sizeof(FLOAT_T) * (info->wdelay + 1); // (+1 for linear interpolation
	info->ptr = (FLOAT_T *)safe_malloc(bytes);
	if(info->ptr != NULL)
		memset(info->ptr, 0, bytes);
	info->rate = pow((FLOAT_T)2.0, (FLOAT_T)info->pitch_cent * DIV_1200) - 1.0; // pitch_cent
	delay = info->ps_delay_ms * playmode_rate_ms;
	if(delay < 1.0)
		delay = 1.0; 		
	info->wcount = 0; // write count
	info->wcycle = 0;
	info->rsdelay = delay;
	for(i = 0; i < PS_CF_PHASE; i++){
		info->rscount[i] = info->rsdelay * (FLOAT_T)i * div_phase; // start offset
		info->rcount[i] = info->wcount - info->pdelay - info->rsdelay + info->rscount[i]; // read count
		if(info->rcount[i] < 0)
			info->rcount[i] += info->wdelay;	
	}
	info->div_cf = 1.0 / (FLOAT_T)info->rsdelay; // cross fade
	delay = info->pre_delay_ms * playmode_rate_ms - info->rsdelay; // pre_delay - ps_delay
	if(delay < 1.0)
		delay = 1.0; 	
	info->pdelay = delay;
	if(info->ptr == NULL)
		info->init_flg = 0;
	else
		info->init_flg = 1;
	info->leveld = PITCH_SHIFTER_LEVEL * otd.efx_CustomPSLvOut;
	// 
	info->pitch_cent_p = info->pitch_cent;
	info->pre_delay_ms_p = info->pre_delay_ms; 
	info->ps_delay_ms_p = info->ps_delay_ms;
}

static void uninit_pitch_shifter_core(InfoPitchShifter_core *info)
{
	if(info->ptr != NULL) {
		safe_free(info->ptr);
		info->ptr = NULL;
	}
}

#if 1 // x4ov
#if (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE) && defined(FLOAT_T_DOUBLE)
static inline void do_pitch_shifter_core(DATA_T *buf, InfoPitchShifter_core *info)
{
	int32 i;
	FLOAT_T out = 0;
	FLOAT_T rate = info->rate * DIV_4; // x4ov
	FLOAT_T wdelay = info->wdelay; // cast
	FLOAT_T delay = info->wcount - info->pdelay - info->rsdelay;
	__m128d vout = _mm_setzero_pd();
	__m128d vrate = _mm_load1_pd(&rate), vdelay = _mm_load1_pd(&delay), vdivcf = _mm_load1_pd(&info->div_cf);
	__m128d vrate1 = _mm_mul_pd(vrate, _mm_set_pd(1.0, 0.0)), vrate2 = _mm_mul_pd(vrate, _mm_set_pd(3.0, 2.0));
	__m128d vrsd = _mm_load1_pd(&info->rsdelay), vrsd_n = _mm_set1_pd(-info->rsdelay);
	__m128d vwd = _mm_set1_pd(info->wdelay), vwd_n = _mm_set1_pd(-info->wdelay);
	const __m128d var1 = _mm_set1_pd(1.0), var2 = _mm_set1_pd(2.0), vdiv2 = _mm_set1_pd(DIV_2), vdiv4 = _mm_set1_pd(DIV_4);
	const __m128d vradd1 = _mm_set_pd(1.0, 0.0), vradd2 = _mm_set_pd(3.0, 2.0);

	for(i = 0; i < PS_CF_PHASE; i++){
		ALIGN FLOAT_T fp1[4], cf[4], tmp;
		__m128i vindex[2];
		__m128d vfp[2], vv1[2], vv2[2], vcf[2], vtmp1[2], vtmp2[2], vin[4];
		// rscount
		vtmp1[0] = _mm_load1_pd(&info->rscount[i]);
		info->rscount[i] += info->rate; // info->rate * DIV_4 * 4
		if (info->rscount[i] >= info->rsdelay)
			info->rscount[i] -= info->rsdelay;
		else if (info->rscount[i] < -info->rsdelay)
			info->rscount[i] += info->rsdelay;
		vcf[0] = _mm_add_pd(vtmp1[0], vrate1); // cf[0] = info->rscount[i]; cf[1] = info->rscount[i] + rate;
		vcf[1] = _mm_add_pd(vtmp1[0], vrate2); // cf[2] = info->rscount[i] + rate * 2; cf[3] = info->rscount[i] + rate * 3;		
		vtmp1[0] = _mm_and_pd(vrsd_n, _mm_cmpge_pd(vcf[0], vrsd)); // cf>=rsd ? -rsd : 0; (マスクで通す通さない
		vtmp1[1] = _mm_and_pd(vrsd_n, _mm_cmpge_pd(vcf[1], vrsd)); // cf>=rsd ? -rsd : 0; (マスクで通す通さない
		vtmp2[0] = _mm_and_pd(vrsd, _mm_cmplt_pd(vcf[0], vrsd_n)); // cf<-rsd ? -rsd : 0; (マスクで通す通さない
		vtmp2[1] = _mm_and_pd(vrsd, _mm_cmplt_pd(vcf[1], vrsd_n)); // cf<-rsd ? -rsd : 0; (マスクで通す通さない
		vcf[0] = _mm_add_pd(_mm_add_pd(vcf[0], vtmp1[0]), vtmp2[0]); // mix vcf+= (-rsd or rsd or 0.0);
		vcf[1] = _mm_add_pd(_mm_add_pd(vcf[1], vtmp1[1]), vtmp2[1]); // mix vcf+= (-rsd or rsd or 0.0);
		// rcount
		info->rcount[i] = delay + info->rscount[i];
		if(info->rcount[i] < 0)
			info->rcount[i] += wdelay;	
		else if (info->rcount[i] >= wdelay)
			info->rcount[i] -= wdelay;
		vfp[0] = _mm_add_pd(vdelay, vcf[0]);
		vfp[1] = _mm_add_pd(vdelay, vcf[1]);
		vtmp1[0] = _mm_and_pd(vwd_n, _mm_cmpge_pd(vfp[0], vwd)); // cf>=wd ? -wd : 0; (マスクで通す通さない
		vtmp1[1] = _mm_and_pd(vwd_n, _mm_cmpge_pd(vfp[1], vwd)); // cf>=wd ? -wd : 0; (マスクで通す通さない
		vtmp2[0] = _mm_and_pd(vwd, _mm_cmplt_pd(vfp[0], _mm_setzero_pd())); // cf<0 ? wd : 0; (マスクで通す通さない
		vtmp2[1] = _mm_and_pd(vwd, _mm_cmplt_pd(vfp[1], _mm_setzero_pd())); // cf<0 ? wd : 0; (マスクで通す通さない
		vfp[0] = _mm_add_pd(_mm_add_pd(vfp[0], vtmp1[0]), vtmp2[0]); // mix vfp+= (-wd or wd or 0.0);
		vfp[1] = _mm_add_pd(_mm_add_pd(vfp[1], vtmp1[1]), vtmp2[1]); // mix vfp+= (-wd or wd or 0.0);
		//interpolation
		vindex[0] = _mm_cvttpd_epi32(vfp[0]); // (int)floor(fp)
		vindex[1] = _mm_cvttpd_epi32(vfp[1]); // (int)floor(fp)
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1 floor
		vfp[0] = _mm_sub_pd(vfp[0], _mm_floor_pd(vfp[0])); // fp-floor(fp)
		vfp[1] = _mm_sub_pd(vfp[1], _mm_floor_pd(vfp[1])); // fp-floor(fp)
#else
		vfp[0] = _mm_sub_pd(vfp[0], _mm_cvtepi32_pd(vindex[0])); // fp-vindex
		vfp[1] = _mm_sub_pd(vfp[1], _mm_cvtepi32_pd(vindex[1])); // fp-vindex
#endif
		vin[0] = _mm_loadu_pd(&info->ptr[MM_EXTRACT_I32(vindex[0],0)]); // v1v2
		vin[1] = _mm_loadu_pd(&info->ptr[MM_EXTRACT_I32(vindex[0],1)]); // v1v2
		vin[2] = _mm_loadu_pd(&info->ptr[MM_EXTRACT_I32(vindex[1],0)]); // v1v2
		vin[3] = _mm_loadu_pd(&info->ptr[MM_EXTRACT_I32(vindex[1],1)]); // v1v2
		vv1[0] = _mm_shuffle_pd(vin[0], vin[1], 0x0); // v1v1
		vv1[1] = _mm_shuffle_pd(vin[2], vin[3], 0x0); // v1v1
		vv2[0] = _mm_shuffle_pd(vin[0], vin[1], 0x3); // v2v2
		vv2[1] = _mm_shuffle_pd(vin[2], vin[3], 0x3); // v2v2
		// linear interpolation
		vv1[0] = MM_FMA_PD(_mm_sub_pd(vv2[0], vv1[0]), vfp[0], vv1[0]);
		vv1[1] = MM_FMA_PD(_mm_sub_pd(vv2[1], vv1[1]), vfp[1], vv1[1]);
		// cross fade ratio // read_delayサイズを1周期とする三角半波 カウントリセット部分が0になる
		vcf[0] = _mm_mul_pd(vcf[0], vdivcf);
		vcf[1] = _mm_mul_pd(vcf[1], vdivcf);
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1 floor
		// vcf-=floor(fp)
		vcf[0] = _mm_sub_pd(vcf[0], _mm_floor_pd(vcf[0])); // fp-floor(fp)
		vcf[1] = _mm_sub_pd(vcf[1], _mm_floor_pd(vcf[1])); // fp-floor(fp)
#else
		// if(vcf<0) vcf+=1.0;
		vtmp1[0] = _mm_and_pd(var1, _mm_cmplt_pd(vcf[0], _mm_setzero_pd())); // cf<0 ? 1.0 : 0; (マスクで通す通さない
		vtmp1[1] = _mm_and_pd(var1, _mm_cmplt_pd(vcf[1], _mm_setzero_pd())); // cf<0 ? 1.0 : 0; (マスクで通す通さない
		vcf[0] = _mm_add_pd(vcf[0], vtmp1[0]); // mix vcf+= (1.0 or 0.0);
		vcf[1] = _mm_add_pd(vcf[1], vtmp1[1]); // mix vcf+= (1.0 or 0.0);
#endif
		// if(cf > 0.5) cf = 2.0 - cf[0]; もっとシンプルにならんかなコレ・・
		vtmp1[0] = _mm_and_pd(vcf[0], _mm_cmple_pd(vcf[0], vdiv2)); // cf<=0.5 ? cf : 0; (マスクで通す通さない
		vtmp1[1] = _mm_and_pd(vcf[1], _mm_cmple_pd(vcf[1], vdiv2)); // cf<=0.5 ? cf : 0; (マスクで通す通さない
		vtmp2[0] = _mm_and_pd(_mm_sub_pd(var1, vcf[0]), _mm_cmpgt_pd(vcf[0], vdiv2)); // cf>0.5 ? (1.0-cf) : 0; (マスクで通す通さない
		vtmp2[1] = _mm_and_pd(_mm_sub_pd(var1, vcf[1]), _mm_cmpgt_pd(vcf[1], vdiv2)); // cf>0.5 ? (1.0-cf) : 0; (マスクで通す通さない
		vcf[0] = _mm_add_pd(vtmp1[0], vtmp2[0]); // mix
		vcf[1] = _mm_add_pd(vtmp1[1], vtmp2[1]); // mix
		// cross fade mix 
		vv1[0] = MM_FMA2_PD(vv1[0],vcf[0],vv1[1],vcf[1]);
		vout = MM_FMA_PD(vv1[0], vdiv2, vout); // cf * 2.0(ratiomax) * DIV_4(ovx4)
	}
	vout = _mm_add_pd(vout, _mm_shuffle_pd(vout, vout, 0x01));
	_mm_store_sd(&out, vout);
	// write buffer
	info->ptr[info->wcount] = *buf + out * info->feedback; // feedback
	// for linear interpolation
	if(info->wcycle){
		if(info->wcount == 0)
			info->ptr[info->wdelay] = info->ptr[0]; // read_pitch_shifter()でindex+1の値域チェックを省略
	}
	// write count // 0 ~ (wdelay-1) のリングバッファ
	if (++info->wcount >= info->wdelay){
		info->wcount = 0;
		info->wcycle++;
	}
	// output
	if(info->fade_flg){
		if(check_envelope3(&info->env) == ENV1_END_STAGE)
			init_pitch_shifter_core(info);
		compute_envelope3(&info->env, 1);
		out *= info->env.vol;
	}
	*buf = out * info->leveld;
}
#else
static inline void do_pitch_shifter_core(DATA_T *buf, InfoPitchShifter_core *info)
{
	int32 i;
	FLOAT_T out = 0;
	FLOAT_T rate = info->rate * DIV_4; // x4ov
	FLOAT_T wdelay = info->wdelay; // cast
	FLOAT_T delay = info->wcount - info->pdelay - info->rsdelay;
	
	for(i = 0; i < PS_CF_PHASE; i++){
		int32 index[4];
		FLOAT_T fp1[4], fp2[4], v1[4], v2[4], cf[4], tmp[4];
		
		// read count
		fp1[0] = info->rcount[i];
		cf[0] = info->rscount[i];
		info->rscount[i] += rate;
		if (info->rscount[i] >= info->rsdelay)
			info->rscount[i] -= info->rsdelay;
		else if (info->rscount[i] < -info->rsdelay)
			info->rscount[i] += info->rsdelay;
		info->rcount[i] = delay + info->rscount[i];
		if(info->rcount[i] < 0)
			info->rcount[i] += wdelay;	
		else if (info->rcount[i] >= wdelay)
			info->rcount[i] -= wdelay;
		// read count
		fp1[1] = info->rcount[i];
		cf[1] = info->rscount[i];
		info->rscount[i] += rate;
		if (info->rscount[i] >= info->rsdelay)
			info->rscount[i] -= info->rsdelay;
		else if (info->rscount[i] < -info->rsdelay)
			info->rscount[i] += info->rsdelay;
		info->rcount[i] = delay + info->rscount[i];
		if(info->rcount[i] < 0)
			info->rcount[i] += wdelay;	
		else if (info->rcount[i] >= wdelay)
			info->rcount[i] -= wdelay;
		// read count
		fp1[2] = info->rcount[i];
		cf[2] = info->rscount[i];
		info->rscount[i] += rate;
		if (info->rscount[i] >= info->rsdelay)
			info->rscount[i] -= info->rsdelay;
		else if (info->rscount[i] < -info->rsdelay)
			info->rscount[i] += info->rsdelay;
		info->rcount[i] = delay + info->rscount[i];
		if(info->rcount[i] < 0)
			info->rcount[i] += wdelay;	
		else if (info->rcount[i] >= wdelay)
			info->rcount[i] -= wdelay;
		// read count
		fp1[3] = info->rcount[i];
		cf[3] = info->rscount[i];
		info->rscount[i] += rate;
		if (info->rscount[i] >= info->rsdelay)
			info->rscount[i] -= info->rsdelay;
		else if (info->rscount[i] < -info->rsdelay)
			info->rscount[i] += info->rsdelay;
		info->rcount[i] = delay + info->rscount[i];
		if(info->rcount[i] < 0)
			info->rcount[i] += wdelay;	
		else if (info->rcount[i] >= wdelay)
			info->rcount[i] -= wdelay;
		//interpolation
		fp2[0] = floor(fp1[0]);
		fp2[1] = floor(fp1[1]);
		fp2[2] = floor(fp1[2]);
		fp2[3] = floor(fp1[3]);
		index[0] = fp2[0];
		index[1] = fp2[1];
		index[2] = fp2[2];
		index[3] = fp2[3];
		v1[0] = info->ptr[index[0]];
		v1[1] = info->ptr[index[1]];
		v1[2] = info->ptr[index[2]];
		v1[3] = info->ptr[index[3]];
		v2[0] = info->ptr[index[0] + 1];
		v2[1] = info->ptr[index[1] + 1];
		v2[2] = info->ptr[index[2] + 1];
		v2[3] = info->ptr[index[3] + 1];
		// linear interpolation
		tmp[0] = v1[0] + (v2[0] - v1[0]) * (fp1[0] - fp2[0]);
		tmp[1] = v1[1] + (v2[1] - v1[1]) * (fp1[1] - fp2[1]);
		tmp[2] = v1[2] + (v2[2] - v1[2]) * (fp1[2] - fp2[2]);
		tmp[3] = v1[3] + (v2[3] - v1[3]) * (fp1[3] - fp2[3]);
		// cross fade ratio // read_delayサイズを1周期とする三角半波 カウントリセット部分が0になる
		cf[0] *= info->div_cf;
		cf[1] *= info->div_cf;
		cf[2] *= info->div_cf;
		cf[3] *= info->div_cf;
		cf[0] -= floor(cf[0]);
		cf[1] -= floor(cf[1]);
		cf[2] -= floor(cf[2]);
		cf[3] -= floor(cf[3]);
		if(cf[0] > 0.5) cf[0] = 1.0 - cf[0];
		if(cf[1] > 0.5) cf[1] = 1.0 - cf[1];
		if(cf[2] > 0.5) cf[2] = 1.0 - cf[2];
		if(cf[3] > 0.5) cf[3] = 1.0 - cf[3];
		// cross fade mix 
		out += ((tmp[0] * cf[0]) + (tmp[1] * cf[1]) + (tmp[2] * cf[2]) + (tmp[3] * cf[3])) * DIV_2; // cf * 2.0(ratiomax) * DIV_4(ovx2)
	}
	// write buffer
	info->ptr[info->wcount] = *buf + out * info->feedback; // feedback
	// for linear interpolation
	if(info->wcycle){
		if(info->wcount == 0)
			info->ptr[info->wdelay] = info->ptr[0]; // read_pitch_shifter()でindex+1の値域チェックを省略
	}
	// write count // 0 ~ (wdelay-1) のリングバッファ
	if (++info->wcount >= info->wdelay){
		info->wcount = 0;
		info->wcycle++;
	}
	// output
	if(info->fade_flg){
		if(check_envelope3(&info->env) == ENV1_END_STAGE)
			init_pitch_shifter_core(info);
		compute_envelope3(&info->env, 1);
		out *= info->env.vol;
	}
	*buf = out * info->leveld;
}
#endif
#elif 1 // ov2
static inline void do_pitch_shifter_core(DATA_T *buf, InfoPitchShifter_core *info)
{
	int32 i;
	FLOAT_T out = 0;
	FLOAT_T rate = info->rate * DIV_2;
	FLOAT_T wdelay = info->wdelay; // cast
	FLOAT_T delay = info->wcount - info->pdelay - info->rsdelay;
	
	for(i = 0; i < PS_CF_PHASE; i++){
		int32 index;
		FLOAT_T fp1, fp2, v1, v2, cf, tmp;

		// read buffer
		fp1 = info->rcount[i];
		fp2 = floor(fp1);
		index = fp2;
		v1 = info->ptr[index];
		v2 = info->ptr[index + 1];
		// linear interpolation
		tmp = v1 + (v2 - v1) * (fp1 - fp2);
		// cross fade ratio // read_delayサイズを1周期とする三角半波 カウントリセット部分が0になる
		cf = info->rscount[i] * info->div_cf;
		cf -= floor(cf);
		if(cf > 0.5) cf = 1.0 - cf;
		// cross fade mix 
		out += tmp * cf; // cf * 2.0(ratiomax) * DIV_2(ovx2)
		// read count
		info->rscount[i] += rate;
		if (info->rscount[i] >= info->rsdelay)
			info->rscount[i] -= info->rsdelay;
		else if (info->rscount[i] < -info->rsdelay)
			info->rscount[i] += info->rsdelay;
		info->rcount[i] = delay + info->rscount[i];
		if(info->rcount[i] < 0)
			info->rcount[i] += wdelay;	
		else if (info->rcount[i] >= wdelay)
			info->rcount[i] -= wdelay;
		//// read count
		//if ((info->rcount[i] += rate) >= info->wdelay)
		//	info->rcount[i] -= info->wdelay;
		//// read count reflesh
		//if ((info->rscount[i] += rate) >= info->rsdelay){
		//	info->rscount[i] -= info->rsdelay;
		//	info->rcount[i] = info->wcount - info->pdelay - info->rsdelay;
		//	if(info->rcount[i] < 0)
		//		info->rcount[i] += info->wdelay;	
		//}	
		
		// read buffer
		fp1 = info->rcount[i];
		fp2 = floor(fp1);
		index = fp2;
		v1 = info->ptr[index];
		v2 = info->ptr[index + 1];
		// linear interpolation
		tmp = v1 + (v2 - v1) * (fp1 - fp2);
		// cross fade ratio // read_delayサイズを1周期とする三角半波 カウントリセット部分が0になる
		cf = info->rscount[i] * info->div_cf;
		cf -= floor(cf);
		if(cf > 0.5) cf = 1.0 - cf;
		// cross fade mix 
		out += tmp * cf; // cf * 2.0(ratiomax) * DIV_2(ovx2)
		// read count
		info->rscount[i] += rate;
		if (info->rscount[i] >= info->rsdelay)
			info->rscount[i] -= info->rsdelay;
		else if (info->rscount[i] < -info->rsdelay)
			info->rscount[i] += info->rsdelay;
		info->rcount[i] = delay + info->rscount[i];
		if(info->rcount[i] < 0)
			info->rcount[i] += wdelay;	
		else if (info->rcount[i] >= wdelay)
			info->rcount[i] -= wdelay;
		//// read count
		//if ((info->rcount[i] += rate) >= info->wdelay)
		//	info->rcount[i] -= info->wdelay;
		//// read count reflesh
		//if ((info->rscount[i] += rate) >= info->rsdelay){
		//	info->rscount[i] -= info->rsdelay;
		//	info->rcount[i] = info->wcount - info->pdelay - info->rsdelay;
		//	if(info->rcount[i] < 0)
		//		info->rcount[i] += info->wdelay;	
		//}
	}
	// write buffer
	info->ptr[info->wcount] = *buf + out * info->feedback; // feedback
	// for linear interpolation
	if(info->wcycle && info->wcount == 0){
		info->ptr[info->wdelay] = info->ptr[0]; // read_pitch_shifter()でindex+1の値域チェックを省略
	}
	// write count // 0 ~ (wdelay-1) のリングバッファ
	if (++info->wcount >= info->wdelay){
		info->wcount = 0;
		info->wcycle++;
	}
	// output
	if(info->fade_flg){
		if(check_envelope3(&info->env) == ENV1_END_STAGE)
			init_pitch_shifter_core(info);
		compute_envelope3(&info->env, 1);
		out *= info->env.vol;
	}
	*buf = out * info->leveld;
}
#else // no ov
static inline void do_pitch_shifter_core(DATA_T *buf, InfoPitchShifter_core *info)
{
	int32 i;
	FLOAT_T out = 0;
	FLOAT_T rate = info->rate;
	FLOAT_T wdelay = info->wdelay; // cast
	FLOAT_T delay = info->wcount - info->pdelay - info->rsdelay;
	
#if 0//test
	info->rcount[0] = floor(info->rcount[0]) + 1.0;
	if (info->rcount[0] >= wdelay)
		info->rcount[0] -= wdelay;
	out = info->ptr[(int)info->rcount[0]];
#else
	for(i = 0; i < PS_CF_PHASE; i++){
		int32 index;
		FLOAT_T fp1, fp2, v1, v2, cf, tmp;

		// read buffer
		fp1 = info->rcount[i];
		fp2 = floor(fp1);
		index = fp2;
		v1 = info->ptr[index];
		v2 = info->ptr[index + 1];
		// linear interpolation
		tmp = v1 + (v2 - v1) * (fp1 - fp2);
		// cross fade ratio // read_delayサイズを1周期とする三角半波 カウントリセット部分が0になる
		cf = info->rscount[i] * info->div_cf;
		cf -= floor(cf);
		if(cf > 0.5) cf = 1.0 - cf;
		// cross fade mix 
		out += tmp * cf * 2.0;
		// read count
		info->rscount[i] += rate;
		if (info->rscount[i] >= info->rsdelay)
			info->rscount[i] -= info->rsdelay;
		else if (info->rscount[i] < -info->rsdelay)
			info->rscount[i] += info->rsdelay;
		info->rcount[i] = delay + info->rscount[i];
		if(info->rcount[i] < 0)
			info->rcount[i] += wdelay;	
		else if (info->rcount[i] >= wdelay)
			info->rcount[i] -= wdelay;
		//// read count
		//if ((info->rcount[i] += rate) >= info->wdelay)
		//	info->rcount[i] -= info->wdelay;
		//// read count reflesh
		//if ((info->rscount[i] += rate) >= info->rsdelay){
		//	info->rscount[i] -= info->rsdelay;
		//	info->rcount[i] = info->wcount - info->pdelay - info->rsdelay;
		//	if(info->rcount[i] < 0)
		//		info->rcount[i] += info->wdelay;	
		//}	
	}
#endif
	// write buffer
	info->ptr[info->wcount] = *buf + out * info->feedback; // feedback
	// for linear interpolation
	if(info->wcycle && info->wcount == 0){
		info->ptr[info->wdelay] = info->ptr[0]; // read_pitch_shifter()でindex+1の値域チェックを省略
	}
	// write count // 0 ~ (wdelay-1) のリングバッファ
	if (++info->wcount >= info->wdelay){
		info->wcount = 0;
		info->wcycle++;
	}
	// output
	if(info->fade_flg){
		if(check_envelope3(&info->env) == ENV1_END_STAGE)
			init_pitch_shifter_core(info);
		compute_envelope3(&info->env, 1);
		out *= info->env.vol;
	}
	*buf = out * info->leveld;
}
#endif
static void do_pitch_shifter_multi(DATA_T *buf, int32 count, InfoPitchShifter *info)
{
	int32 i;
	DATA_T tmp1, tmp2;
	
	if (count == MAGIC_INIT_EFFECT_INFO) {
		switch(info->mode){		
		case CH_STEREO:	
		case CH_MIX_STEREO:	
		case CH_MONO_STEREO:	
			init_pitch_shifter_core(&info->psl);
			init_pitch_shifter_core(&info->psr);
			if(!info->psl.init_flg || !info->psr.init_flg)
				info->init_flg = 0;
			else
				info->init_flg = 1;
			return;
		case CH_MIX_MONO:
		case CH_MONO:
		case CH_LEFT:
			init_pitch_shifter_core(&info->psl);
			if(!info->psl.init_flg)
				info->init_flg = 0;
			else
				info->init_flg = 1;
			return;
		case CH_RIGHT:
			init_pitch_shifter_core(&info->psr);
			if(!info->psr.init_flg)
				info->init_flg = 0;
			else
				info->init_flg = 1;
			return;
		}
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		uninit_pitch_shifter_core(&info->psl);	
		uninit_pitch_shifter_core(&info->psr);	
		return;
	}
	if(!info->init_flg)
		return;
	switch(info->mode){		
	case CH_STEREO:		
		for(i = 0; i < count; i++){
			tmp1 = buf[i];
			do_pitch_shifter_core(&tmp1, &info->psl);
			buf[i] = tmp1;
			i++;
			tmp2 = buf[i];
			do_pitch_shifter_core(&tmp2, &info->psr);
			buf[i] = tmp2;
		}	
		break;
	case CH_MIX_STEREO:		
		for(i = 0; i < count; i++){
			tmp1 = tmp2 = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			do_pitch_shifter_core(&tmp1, &info->psl);
			do_pitch_shifter_core(&tmp2, &info->psr);
			buf[i] = tmp1;
			i++;
			buf[i] = tmp2;
		}
		break;
	case CH_MONO_STEREO:		
		for(i = 0; i < count; i++){
			tmp1 = tmp2 = buf[i];
			do_pitch_shifter_core(&tmp1, &info->psl);
			do_pitch_shifter_core(&tmp2, &info->psr);
			buf[i] = tmp1;
			i++;
			buf[i] = tmp2;
		}
		break;
	case CH_MIX_MONO:
		for(i = 0; i < count; i++){
			tmp1 = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			do_pitch_shifter_core(&tmp1, &info->psl);
			buf[i] = tmp1;
			i++;
			buf[i] = tmp1;		
		}
		break;
	case CH_MONO:
		for(i = 0; i < count; i++){
			tmp1 = buf[i];
			do_pitch_shifter_core(&tmp1, &info->psl);
			buf[i] = tmp1;
			i++;	
			buf[i] = tmp1;
		}
		break;
	case CH_LEFT:
		for(i = 0; i < count; i++){
			tmp1 = buf[i];
			do_pitch_shifter_core(&tmp1, &info->psl);
			buf[i] = tmp1;
			i++;	
		}
		break;
	case CH_RIGHT:
		for(i = 0; i < count; i++){
			i++;
			tmp2 = buf[i];
			do_pitch_shifter_core(&tmp2, &info->psr);
			buf[i] = tmp2;
		}
		break;
	}
}

/*! Stereo EQ */
void do_stereo_eq(DATA_T *buf, int32 count, InfoStereoEQ *eq)
{
	int32 i;

	if (count == MAGIC_INIT_EFFECT_INFO) {
		if (eq->low_gain != 0)
			init_sample_filter2(&(eq->lsf), eq->low_freq, eq->low_gain, 0, FILTER_SHELVING_LOW);
		else
			init_sample_filter2(&(eq->lsf), eq->low_freq, eq->low_gain, 0, FILTER_NONE);
		if (eq->high_gain != 0)
			init_sample_filter2(&(eq->hsf), eq->high_freq, eq->high_gain, 0, FILTER_SHELVING_HI);
		else
			init_sample_filter2(&(eq->hsf), eq->high_freq, eq->high_gain, 0, FILTER_NONE);
		if (eq->m1_gain != 0)
			init_sample_filter2(&(eq->m1), eq->m1_freq, eq->m1_gain, eq->m1_q, FILTER_PEAKING);
		else
			init_sample_filter2(&(eq->m1), eq->m1_freq, eq->m1_gain, 0, FILTER_NONE);
		if (eq->m2_gain != 0)
			init_sample_filter2(&(eq->m2), eq->m2_freq, eq->m2_gain, eq->m2_q, FILTER_PEAKING);
		else
			init_sample_filter2(&(eq->m2), eq->m2_freq, eq->m2_gain, 0, FILTER_NONE);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		return;
	}
	// CH_STEREO
	buffer_filter_stereo(&(eq->lsf), buf, count);
	buffer_filter_stereo(&(eq->hsf), buf, count);
	buffer_filter_stereo(&(eq->m1), buf, count);
	buffer_filter_stereo(&(eq->m2), buf, count);
}

/*! 8-Band EQ */
static void do_spectrum(DATA_T *buf, int32 count, InfoSpectrum *info)
{
	int i;

	if (count == MAGIC_INIT_EFFECT_INFO) {
		for(i = 0; i < 8; i++){
			if (info->gain[i] != 0)
				init_sample_filter2(&(info->peak[i]), info->freq[i], info->gain[i], info->width, FILTER_PEAKING);
			else
				init_sample_filter2(&(info->peak[i]), info->freq[i], info->gain[i], info->width, FILTER_NONE);
		}
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		info->init = 0;
		return;
	}
	switch(info->mode){
	case CH_STEREO:
		buffer_filter_stereo(&(info->peak[0]), buf, count);
		buffer_filter_stereo(&(info->peak[1]), buf, count);
		buffer_filter_stereo(&(info->peak[2]), buf, count);
		buffer_filter_stereo(&(info->peak[3]), buf, count);
		buffer_filter_stereo(&(info->peak[4]), buf, count);
		buffer_filter_stereo(&(info->peak[5]), buf, count);
		buffer_filter_stereo(&(info->peak[6]), buf, count);
		buffer_filter_stereo(&(info->peak[7]), buf, count);
		break;
	case CH_LEFT:
		buffer_filter_left(&(info->peak[0]), buf, count);
		buffer_filter_left(&(info->peak[1]), buf, count);
		buffer_filter_left(&(info->peak[2]), buf, count);
		buffer_filter_left(&(info->peak[3]), buf, count);
		buffer_filter_left(&(info->peak[4]), buf, count);
		buffer_filter_left(&(info->peak[5]), buf, count);
		buffer_filter_left(&(info->peak[6]), buf, count);
		buffer_filter_left(&(info->peak[7]), buf, count);
		break;
	}
	//for(i = 0; i < 8; i++){
	//	if (info->gain[i] != 0) {
	//		do_peaking_filter_left(buf, count, &(info->peak[i]));
	//	}
	//}
}



#ifdef EFFECT_LEVEL_FLOAT // level float
const FLOAT_T ins_enhancer_max = (double)(1.0) // ??
#else // level int
const FLOAT_T ins_enhancer_max = (double)((1<<(SAMPLE_BITS + AMP_BITS - 3))-1); // max insertion input volume = WS_AMP_VALUE
#endif

#define ENHANCER_LEVEL (1.00)
#define ENHANCER_DELAY_TIME (4.0) // ms
#define ENHANCER_DELAY_FEEDBACK (0.875)

static void do_enhancer_multi(DATA_T *buf, int32 count, InfoEnhancer *info)
{
	int i;
	//filter_shelving *hpfl1 = &info->hpfl1, *hpfl2 = &info->hpfl2, *hpfl3 = &info->hpfl3, *hpfl4 = &info->hpfl4,
	//	 *hpfr1 = &info->hpfr1, *hpfr2 = &info->hpfr2, *hpfr3 = &info->hpfr3, *hpfr4 = &info->hpfr4;
	simple_delay *delayL = &info->delayL, *delayR = &info->delayR;
	FLOAT_T feedbackd = info->feedbackd, wetd = info->wetd;
	
	if (count == MAGIC_INIT_EFFECT_INFO) {
		FLOAT_T tmp;
		//info->hpf_cutoff = 1000;
		//info->sens = 1.0;
		if(!info->init){	
			info->init = 1;
			set_delay(&info->delayL, (int32)(ENHANCER_DELAY_TIME * playmode_rate_ms));
			set_delay(&info->delayR, (int32)(ENHANCER_DELAY_TIME * playmode_rate_ms));
			init_sample_filter(&info->fc, info->hpf_cutoff, 0, FILTER_HPF_BW);
			init_sample_filter2(&info->hsh, info->hpf_cutoff * 2.0, info->sens * 12.0, 0.5, FILTER_SHELVING_HI);
		}	
		info->feedbackd = mix_double(info->sens, 0.5, ENHANCER_DELAY_FEEDBACK);
		info->wetd = ENHANCER_LEVEL * otd.efx_CustomEnhLvOut; // mix level		
		set_sample_filter_freq(&info->fc, info->hpf_cutoff);
		recalc_filter(&info->fc);
		set_sample_filter_freq(&info->hsh, info->hpf_cutoff * 2.0);
		set_sample_filter_reso(&info->hsh, info->sens * 12.0);
		set_sample_filter_q(&info->hsh, 0.5);
		recalc_filter(&info->hsh);
		//if(!info->init){	
		//	info->init = 1;
		//	init_filter_shelving(hpfl1);
		//	init_filter_shelving(hpfl2);
		//	init_filter_shelving(hpfl3);
		//	init_filter_shelving(hpfl4);
		//	init_filter_shelving(hpfr1);
		//	init_filter_shelving(hpfr2);
		//	init_filter_shelving(hpfr3);
		//	init_filter_shelving(hpfr4);
		//}
		//tmp = info->sens * 12.0; // sens 0.0~1.0
		//hpfl1->q = hpfr1->q = tmp;
		//hpfl1->freq = hpfr1->freq = 6500;
		//hpfl1->gain = hpfr1->gain = tmp;
		//hpfl2->q = hpfr2->q = tmp;
		//hpfl2->freq = hpfr2->freq = 4000;
		//hpfl2->gain = hpfr2->gain = tmp;
		//hpfl3->q = hpfr3->q = tmp;
		//hpfl3->freq = hpfr3->freq = 2500;
		//hpfl3->gain = hpfr3->gain = tmp;
		//hpfl4->q = hpfr4->q = tmp;
		//hpfl4->freq = hpfr4->freq = info->hpf_cutoff;
		//hpfl4->gain = hpfr4->gain = tmp;
		//calc_filter_shelving_high(hpfl1);
		//calc_filter_shelving_high(hpfl2);
		//calc_filter_shelving_high(hpfl3);
		//calc_filter_shelving_high(hpfl4);
		//calc_filter_shelving_high(hpfr1);
		//calc_filter_shelving_high(hpfr2);
		//calc_filter_shelving_high(hpfr3);	
		//calc_filter_shelving_high(hpfr4);	
		//info->wetd = ENHANCE_LEVEL;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		info->init = 0;
		free_delay(&info->delayL);
		free_delay(&info->delayR);
		return;
	}
	switch(info->mode){
	case CH_STEREO:
		for(i = 0; i < count; i++) {
			DATA_T input[2];
			input[0] = buf[i] * otd.efx_CustomEnhLvIn	+ delayL->buf[delayL->index] * feedbackd;
			input[1] = buf[i + 1] * otd.efx_CustomEnhLvIn + delayR->buf[delayR->index] * feedbackd;
			sample_filter_stereo2(&info->fc, input);
			delayL->buf[delayL->index] = input[0];
			delayR->buf[delayR->index] = input[1];	
			sample_filter_stereo2(&info->hsh, input);
			buf[i] = input[0] * wetd;
			i++;
			buf[i] = input[1] * wetd;		
			if(++delayL->index >= delayL->size) delayL->index = 0;
			if(++delayR->index >= delayR->size) delayR->index = 0;
		}
		//for(i = 0; i < count; i++) {
		//	DATA_T input;
		//	input = buf[i] * otd.efx_CustomEnhLvIn	+ delayL->buf[delayL->index] * feedbackd;
		//	sample_filter_left(&info->fc, &input);
		//	delayL->buf[delayL->index] = input;	
		//	sample_filter_left(&info->hsh, &input);
		//	buf[i] = input * wetd;			
		//	if(++delayL->index >= delayL->size)
		//		delayL->index = 0;
		//	i++;
		//	input = buf[i] * otd.efx_CustomEnhLvIn + delayR->buf[delayR->index] * feedbackd;
		//	sample_filter_right(&info->fc, &input);
		//	delayR->buf[delayR->index] = input;	
		//	sample_filter_right(&info->hsh, &input);
		//	buf[i] = input * wetd;	
		//	if(++delayR->index >= delayR->size)
		//		delayR->index = 0;
		//}
		//for(i = 0; i < count; i++) {
		//	DATA_T tmp, tmp1, tmp2, tmp3, tmp4;
		//	tmp1 = tmp2 = tmp3 = tmp4 = buf[i];
		//	do_shelving_filter(&tmp1, hpfl1);
		//	do_shelving_filter(&tmp2, hpfl2);
		//	do_shelving_filter(&tmp3, hpfl3);
		//	do_shelving_filter(&tmp4, hpfl4);
		//	buf[i] = (tmp1 + tmp2 + tmp3 + tmp4) * DIV_4 * wetd;
		//	i++;
		//	tmp1 = tmp2 = tmp3 = tmp4 = buf[i];
		//	do_shelving_filter(&tmp1, hpfr1);
		//	do_shelving_filter(&tmp2, hpfr2);
		//	do_shelving_filter(&tmp3, hpfr3);
		//	do_shelving_filter(&tmp4, hpfr4);
		//	buf[i] = (tmp1 + tmp2 + tmp3 + tmp4) * DIV_4 * wetd;
		//}
		break;
	}
}


#define HUMANIZER_LEVEL (0.75)
#define HUMANIZER_CUTOFF (1500.0)
#define HUMANIZER_RESO (6.0)
#define HUMANIZER_LFO_RATE (0.125)
#define HUMANIZER_LFO_DEPTH (2.0)

const double vowel_coeff[5][11] =
{
	{ 8.11044e-06, 8.943665402, -36.83889529, 92.01697887, -154.337906, 181.6233289,
		-151.8651235, 89.09614114, -35.10298511, 8.388101016, -0.923313471 },  ///A
	{ 3.33819e-06, 8.893102966, -36.49532826, 90.96543286, -152.4545478, 179.4835618,
		-150.315433, 88.43409371, -34.98612086, 8.407803364, -0.932568035 },  ///I
	{ 4.09431e-07, 8.997322763, -37.20218544, 93.11385476, -156.2530937, 183.7080141,
		-153.2631681, 89.59539726, -35.12454591, 8.338655623, -0.910251753 },  ///U
	{ 4.36215e-06, 8.90438318, -36.55179099, 91.05750846, -152.422234, 179.1170248,
		-149.6496211, 87.78352223, -34.60687431, 8.282228154, -0.914150747 },  ///E
	{ 1.13572e-06, 8.994734087, -37.2084849, 93.22900521, -156.6929844, 184.596544,
		-154.3755513, 90.49663749, -35.58964535, 8.478996281, -0.929252233 },   ///O
};

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void do_humanizer(DATA_T *buf, int32 count, InfoHumanizer *info)
{
	int i, k, cnt = count / 2;
	FLOAT_T *dc = info->dc, *vc = info->vc;
	FLOAT_T *db = info->db;

	if(count == MAGIC_INIT_EFFECT_INFO) {		
		if(!info->init){
			FLOAT_T dclevel = 0.0;
			FLOAT_T div_phase = 1.0 / (FLOAT_T)HUMANIZER_PHASE;
			info->init = 1;
			info->p_vowel = info->vowel;
			for(i = 0; i < 11; i++){
				info->dc[i] = info->vc[i] = vowel_coeff[info->vowel][i];
				dclevel += dc[i];
			}
			info->fmt_level = (dclevel > 1.0) ? (1.0 / dclevel) : 1.0;
			info->dc[11] = 0;
			memset(info->db, 0, sizeof(info->db));
			info->p_accel = info->accel;
			init_envelope3(&info->env, 1.0, info->accel * playmode_rate_ms);
			info->p_ac = info->env.vol;
			// lfo
			info->lfo_rate = HUMANIZER_LFO_RATE * div_playmode_rate * M_PI2;
			info->lfo_count = 0; // min point
			for(i = 0; i < HUMANIZER_PHASE; i++){
				info->lfo_phase[i] = (FLOAT_T)i * div_phase * M_PI2;
				init_sample_filter(&info->fc[i], HUMANIZER_CUTOFF, HUMANIZER_RESO, i & 0x1 ? FILTER_BCF12_3 : FILTER_BPF12_3);
			}
			info->flt_level = pow((FLOAT_T)div_phase, 0.666666666);
		}
		if(info->od_sw)
			init_drive(&info->drv, 4, 0.2, 0.7, info->drive * otd.efx_CustomHmnLvIn);
		else
			init_drive(&info->drv, 0, 0.0, 0.7, 1.0);
		info->leveld = info->flt_level * HUMANIZER_LEVEL * otd.efx_CustomHmnLvOut;
		info->leveli = TIM_FSCALE(info->leveld, 24);
		if(info->p_accel != info->accel){
			info->p_accel = info->accel;
			reset_envelope3(&info->env, 1.0, info->accel * playmode_rate_ms);
		}
		if(info->p_vowel != info->vowel){
			info->p_vowel = info->vowel;
			for(i = 0; i < 11; i++)
				info->vc[i] = info->dc[i];
			init_envelope3(&info->env, 0.0, info->accel * playmode_rate_ms);
			reset_envelope3(&info->env, 1.0, ENVELOPE_KEEP);
			info->p_ac = -1;
		}			
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		info->init = 0;
		return;
	} else if(count == 0) {
		return;
	}	
	// vowel interpolation
	compute_envelope3(&info->env, cnt);
	if(info->p_ac != info->env.vol){
		FLOAT_T dclevel = 0.0;
		int vn = info->vowel;
		double ac1 = info->p_ac = info->env.vol;
		double ac2 = 1.0 - ac1;
		for(i = 0; i < 11; i++){
			dc[i] = vowel_coeff[vn][i];
		//	dc[i] = vowel_coeff[vn][i] * ac1 + vc[i] * ac2;
			dclevel += dc[i];
		}
		info->fmt_level = (dclevel > 1.0) ? (1.0 / dclevel) : 1.0;
	}	
	// lfo	
	for(i = 0; i < HUMANIZER_PHASE; i++){
		set_sample_filter_freq(&info->fc[i], HUMANIZER_CUTOFF * pow(HUMANIZER_LFO_DEPTH, sin(info->lfo_count + info->lfo_phase[i])));
		recalc_filter(&info->fc[i]);
	}
	if ((info->lfo_count += (info->lfo_rate * cnt)) >= M_PI2) {info->lfo_count -= M_PI2;}
	// CH_MONO
	for (i = 0; i < count; i++)
	{
		DATA_T tmp = 0, sum = 0;
		tmp = buf[i];
		do_drive_mono(&info->drv, &tmp);
		tmp = tmp * dc[0] + db[1] * dc[1] + db[2] * dc[2] + db[3] * dc[3]
			+ db[4] * dc[4] + db[5] * dc[5] + db[6] * dc[6] + db[7] * dc[7]
			+ db[8] * dc[8] + db[9] * dc[9] + db[10] * dc[10];	
		tmp *= info->fmt_level;
		db[10] = db[9];
		db[9] = db[8];
		db[8] = db[7];
		db[7] = db[6];
		db[6] = db[5];
		db[5] = db[4];
		db[4] = db[3];
		db[3] = db[2];
		db[2] = db[1];                     
		db[1] = tmp;	
		for(k = 0; k < HUMANIZER_PHASE; k++){
			DATA_T flt = tmp;
			sample_filter(&info->fc[k], &flt);
			sum += flt;
		}
		sum = imuldiv24(sum, info->leveli);
		buf[i] = sum;
		i++;
		buf[i] = sum;
	}
}
#else /* floating-point implementation */
static void do_humanizer(DATA_T *buf, int32 count, InfoHumanizer *info)
{
	int i, k, cnt = count / 2;
	FLOAT_T *dc = info->dc, *vc = info->vc;
	FLOAT_T *db = info->db;

	if(count == MAGIC_INIT_EFFECT_INFO) {		
		if(!info->init){
			FLOAT_T dclevel = 0.0;
			FLOAT_T div_phase = 1.0 / (FLOAT_T)HUMANIZER_PHASE;
			info->init = 1;
			info->p_vowel = info->vowel;
			for(i = 0; i < 11; i++){
				info->dc[i] = info->vc[i] = vowel_coeff[info->vowel][i];
				dclevel += dc[i];
			}
			info->fmt_level = (dclevel > 1.0) ? (1.0 / dclevel) : 1.0;
			memset(info->db, 0, sizeof(info->db));
			info->p_accel = info->accel;
			init_envelope3(&info->env, 1.0, info->accel * playmode_rate_ms);
			info->p_ac = info->env.vol;
			// lfo
			info->lfo_rate = HUMANIZER_LFO_RATE * div_playmode_rate * M_PI2;
			info->lfo_count = 0; // min point
			for(i = 0; i < HUMANIZER_PHASE; i++){
				info->lfo_phase[i] = (FLOAT_T)i * div_phase * M_PI2;
				init_sample_filter(&info->fc[i], HUMANIZER_CUTOFF, HUMANIZER_RESO, i & 0x1 ? FILTER_BCF12_3 : FILTER_BPF12_3);
			}
			info->flt_level = pow((FLOAT_T)div_phase, 0.666666666);
		}
		if(info->od_sw)
			init_drive(&info->drv, 4, 0.2, 0.7, info->drive * otd.efx_CustomHmnLvIn);
		else
			init_drive(&info->drv, 0, 0.0, 0.7, 1.0);
		info->leveld = info->flt_level * HUMANIZER_LEVEL * otd.efx_CustomHmnLvOut;
		if(info->p_accel != info->accel){
			info->p_accel = info->accel;
			reset_envelope3(&info->env, 1.0, info->accel * playmode_rate_ms);
		}
		if(info->p_vowel != info->vowel){
			info->p_vowel = info->vowel;
			for(i = 0; i < 11; i++)
				info->vc[i] = info->dc[i];
			init_envelope3(&info->env, 0.0, info->accel * playmode_rate_ms);
			reset_envelope3(&info->env, 1.0, ENVELOPE_KEEP);
			info->p_ac = -1;
		}			
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		info->init = 0;
		return;
	} else if(count == 0) {
		return;
	}	
	// vowel interpolation
	compute_envelope3(&info->env, cnt);
	if(info->p_ac != info->env.vol){
		FLOAT_T dclevel = 0.0;
		int vn = info->vowel;
		double ac1 = info->p_ac = info->env.vol;
		double ac2 = 1.0 - ac1;
		for(i = 0; i < 11; i++){
			dc[i] = vowel_coeff[vn][i];
		//	dc[i] = vowel_coeff[vn][i] * ac1 + vc[i] * ac2;
			dclevel += dc[i];
		}
		info->fmt_level = (dclevel > 1.0) ? (1.0 / dclevel) : 1.0;
	}
	// lfo	
	for(i = 0; i < HUMANIZER_PHASE; i++){
		set_sample_filter_freq(&info->fc[i], HUMANIZER_CUTOFF * pow(HUMANIZER_LFO_DEPTH, sin(info->lfo_count + info->lfo_phase[i])));
		recalc_filter(&info->fc[i]);
	}
	if ((info->lfo_count += (info->lfo_rate * cnt)) >= M_PI2) {info->lfo_count -= M_PI2;}
	// CH_MONO

	for (i = 0; i < count; i++)
	{
		DATA_T tmp = 0, sum = 0;
		tmp = buf[i];
		do_drive_mono(&info->drv, &tmp);
		db[0] = tmp;
	
#if (USE_X86_EXT_INTRIN >= 3) && defined(FLOAT_T_DOUBLE) && defined(DATA_T_DOUBLE)
		{
		__m128d vdc0 = _mm_loadu_pd(&dc[0]), vdc2 = _mm_loadu_pd(&dc[2]), vdc4 = _mm_loadu_pd(&dc[4]),
			vdc6 = _mm_loadu_pd(&dc[6]), vdc8 = _mm_loadu_pd(&dc[8]), vdc10 = _mm_loadu_pd(&dc[10]);
		__m128d vdb0 = _mm_loadu_pd(&db[0]), vdb2 = _mm_loadu_pd(&db[2]), vdb4 = _mm_loadu_pd(&db[4]),
			vdb6 = _mm_loadu_pd(&db[6]), vdb8 = _mm_loadu_pd(&db[8]), vdb10 = _mm_loadu_pd(&db[10]);		
		__m128d vec_tmp = MM_FMA6_PD(vdb0, vdc0, vdb2, vdc2, vdb4, vdc4, vdb6, vdc6, vdb8, vdc8, vdb10, vdc10);
		__m128d vfmtlv = _mm_load_sd(&info->fmt_level);
		vec_tmp = _mm_add_pd(vec_tmp, _mm_shuffle_pd(vec_tmp, vec_tmp, 0x1));
		vec_tmp = _mm_mul_sd(vec_tmp, vfmtlv);
		_mm_store_sd(&tmp, vec_tmp);
		vdb0 = _mm_move_sd(vdb0, vec_tmp);
		_mm_storeu_pd(&db[9], vdb8);
		_mm_storeu_pd(&db[7], vdb6);
		_mm_storeu_pd(&db[5], vdb4);
		_mm_storeu_pd(&db[3], vdb2);
		_mm_storeu_pd(&db[1], vdb0);
		}
		
#elif (USE_X86_EXT_INTRIN >= 2) && defined(FLOAT_T_FLOAT) && defined(DATA_T_FLOAT)
		{
		__m128 vdc0 = _mm_loadu_ps(&dc[0]), vdc4 = _mm_loadu_ps(&dc[4]), vdc8 = _mm_loadu_ps(&dc[8]);
		__m128 vdb0 = _mm_loadu_ps(&db[0]), vdb4 = _mm_loadu_ps(&db[4]), vdb8 = _mm_loadu_ps(&db[8]);		
		__m128 vec_tmp = MM_FMA3_PS(vdb0, vdc0, vdb4, vdc4, vdb8, vdc8);
		__m128 vfmtlv = _mm_set1_ps(info->fmt_level);
		vec_tmp = _mm_add_ps(vec_tmp, _mm_movehl_ps(vec_tmp, vec_tmp)); // v0=v0+v1 v1=v2+v3
		vec_tmp = _mm_add_ps(vec_tmp, _mm_shuffle_ps(vec_tmp, vec_tmp, 0xe1)); // v0=v0+v1	
		vec_tmp = _mm_mul_ss(vec_tmp, vfmtlv);
		vdb0 = _mm_move_ss(vdb0, vec_tmp);
		_mm_store_ss(&tmp,  vec_tmp);
		_mm_storeu_ps(&db[9], vdb8);
		_mm_storeu_ps(&db[5], vdb4);
		_mm_storeu_ps(&db[1], vdb0);		
		}

#else
		tmp = db[0] * dc[0] + db[1] * dc[1] + db[2] * dc[2] + db[3] * dc[3]
			+ db[4] * dc[4] + db[5] * dc[5] + db[6] * dc[6] + db[7] * dc[7]
			+ db[8] * dc[8] + db[9] * dc[9] + db[10] * dc[10];	
		tmp *= info->fmt_level;
		db[10] = db[9];
		db[9] = db[8];
		db[8] = db[7];
		db[7] = db[6];
		db[6] = db[5];
		db[5] = db[4];
		db[4] = db[3];
		db[3] = db[2];
		db[2] = db[1];                     
		db[1] = tmp;	
#endif
		for(k = 0; k < HUMANIZER_PHASE; k++){
			DATA_T flt = tmp;
			sample_filter(&info->fc[k], &flt);
			sum += flt;
		}
		sum *= info->leveld;
		buf[i] = sum;
		i++;
		buf[i] = sum;
	}
}
#endif /* OPT_MODE != 0 */


///r
#define OD_GAIN 1.75
#define OD_AMP_GAIN 1.3
#define OD_CLIP_LEVEL 0.75
#define OD_LEVEL 1.000
#define OD_LEVEL_AMPN (0.50f)
#define OD_LEVEL_AMP0 (1.00f)
#define OD_LEVEL_AMP1 (1.00f)
#define OD_LEVEL_AMP2 (1.00f)
#define OD_LEVEL_AMP3 (1.00f)
#define OD_FF1_OD 125.0f
#define OD_FF1_DS 250.0f
#define OD_FF2 5000.0f
#define OD_FF3 4500.0f
#define OD_FF4_COEF (1.025)
#define OD_FF4_AMPN (5999.0f * OD_FF4_COEF)
#define OD_FF4_AMP0 (5750.0f * OD_FF4_COEF)
#define OD_FF4_AMP1 (5600.0f * OD_FF4_COEF)
#define OD_FF4_AMP2 (5450.0f * OD_FF4_COEF)
#define OD_FF4_AMP3 (5300.0f * OD_FF4_COEF)
#define OD_FF5 9800.0f
#define OD_FQ1 0.0f
#define OD_FQ2 8.0f
#define OD_FQ3 0.0f
#define OD_FQ4 0.0f
#define OD_FQ5 0.85f

static inline double calc_gs_drive_gain(int val)
{
	return ((double)val * DIV_127 * OD_GAIN + 1.0) * otd.gsefx_CustomODDrive;
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
/*! GS 0x0111~: OD DS multi */
static void do_od_ds_multi(int32 *buf, int32 count, InfoOverdrive *info)
{
	int32 i;
	int32 input, leveli = info->leveli;
	FilterCoefficients *bw1 = &(info->bw1), *bw2 = &(info->bw2), *bw3 = &(info->bw3), *bw4 = &(info->bw4);
	FilterCoefficients *bq = &(info->bq);	
	FLOAT_T bw1_freq, bw2_freq, bw3_freq, bw4_freq;
	int flt2_type, flt3_type, flt4_type;

	if (count == MAGIC_INIT_EFFECT_INFO) {
		/* overdrive distortion */
		if(info->type == 0) { // overdrive
			init_drive(&info->drv1, 4, 0.8, OD_CLIP_LEVEL, calc_gs_drive_gain(info->drive));
			init_drive(&info->drv2, 4, 0.6, OD_CLIP_LEVEL, calc_gs_drive_gain(info->drive));
			bw1_freq = OD_FF1_OD;
			flt2_type = FILTER_NONE;
			flt3_type = FILTER_LPF6;
		}else{ // distortion
			init_drive(&info->drv1, 9, 0.5, OD_CLIP_LEVEL, calc_gs_drive_gain(info->drive));
			init_drive(&info->drv2, 9, 0.2, OD_CLIP_LEVEL, calc_gs_drive_gain(info->drive));
			bw1_freq = OD_FF1_DS;
			flt2_type = FILTER_LPF_BW;
			flt3_type = FILTER_LPF6;
		}
		/* waveshaper amp simulator */
		if (info->amp_sw == 0) {
			init_drive(&info->drv3, 0, 0.0, OD_CLIP_LEVEL, 1.0);
			flt4_type = FILTER_LPF6;
			bw4_freq = OD_FF4_AMPN * otd.gsefx_CustomODFreq;
			info->leveld = info->level * otd.gsefx_CustomODLv * OD_LEVEL * OD_LEVEL_AMPN;
		}else switch(info->amp_type){
		default:
		case 0: // small
			init_drive(&info->drv3, 4, 0.5, OD_CLIP_LEVEL, OD_AMP_GAIN * otd.gsefx_CustomODDrive);
			flt4_type = FILTER_LPF_BW;
			bw4_freq = OD_FF4_AMP0 * otd.gsefx_CustomODFreq;
			info->leveld = info->level * otd.gsefx_CustomODLv * OD_LEVEL * OD_LEVEL_AMP0;
			break;
		case 1: // builtin
			init_drive(&info->drv3, 4, 0.6, OD_CLIP_LEVEL, OD_AMP_GAIN * otd.gsefx_CustomODDrive);
			flt4_type = FILTER_LPF_BW;
			bw4_freq = OD_FF4_AMP1 * otd.gsefx_CustomODFreq;
			info->leveld = info->level * otd.gsefx_CustomODLv * OD_LEVEL * OD_LEVEL_AMP1;
			break;
		case 2: // 2stack
			init_drive(&info->drv3, 4, 0.7, OD_CLIP_LEVEL, OD_AMP_GAIN * otd.gsefx_CustomODDrive);
			flt4_type = FILTER_LPF_BW;
			bw4_freq = OD_FF4_AMP2 * otd.gsefx_CustomODFreq;
			info->leveld = info->level * otd.gsefx_CustomODLv * OD_LEVEL * OD_LEVEL_AMP2;
			break;
		case 3: // 3stack
			init_drive(&info->drv3, 4, 0.8, OD_CLIP_LEVEL, OD_AMP_GAIN * otd.gsefx_CustomODDrive);
			flt4_type = FILTER_LPF_BW;
			bw4_freq = OD_FF4_AMP3 * otd.gsefx_CustomODFreq;
			info->leveld = info->level * otd.gsefx_CustomODLv * OD_LEVEL * OD_LEVEL_AMP3;
			break;
		}
		bw2_freq = OD_FF2;
		bw3_freq = OD_FF3;
		switch(info->mode){
		case CH_MIX_STEREO:
			break;
		case CH_LEFT:
			bw1_freq -= 3.0;
			bw2_freq += 20.0;
			bw3_freq -= 20.0;
			bw4_freq += 20.0;
			break;
		case CH_RIGHT:
			bw1_freq += 3.0;
			bw2_freq -= 20.0;
			bw3_freq += 20.0;
			bw4_freq -= 20.0;
			break;
		}
		init_sample_filter(bw1, bw1_freq, OD_FQ1, FILTER_HPF_BW);
		init_sample_filter(bw2, bw2_freq, OD_FQ2, flt2_type);
		init_sample_filter(bw3, bw3_freq, OD_FQ3, flt3_type);
		init_sample_filter(bw4, bw4_freq, OD_FQ4, flt4_type);
		// cutoff
		init_sample_filter2(bq, OD_FF5 * otd.gsefx_CustomODFreq, 0, OD_FQ5, FILTER_BIQUAD_LOW);
		info->leveld = otd.gsefx_CustomODLv * OD_LEVEL;
		info->leveli = TIM_FSCALE(info->leveld, 24);
		return;
	}
	switch (info->mode) {
	case CH_STEREO:
		for (i = 0; i < count; i++) {
			DATA_T input_d[2] = {buf[i], buf[i + 1]};
			/* waveshaper amp simulator anti-aliasing */
			sample_filter_stereo2(bw1, input_d);
			do_drive_stereo(&info->drv1, input_d);
			sample_filter_stereo2(bw2, input_d);
			do_drive_stereo(&info->drv2, input_d);
			sample_filter_stereo2(bw3, input_d);
			do_drive_stereo(&info->drv3, input_d);
			sample_filter_stereo2(bw4, input_d);
			sample_filter_stereo2(bq, input_d);
			/* mixing */
			buf[i] = imuldiv24(input_d[0], leveli);
			buf[i + 1] = imuldiv24(input_d[1], leveli);
			++i;
		}
		break;
	case CH_MIX_STEREO:
	case CH_MIX_MONO:
		for (i = 0; i < count; i++) {
			input = divi_2(buf[i] + buf[i + 1]);
			/* waveshaper amp simulator anti-aliasing */
			sample_filter_left(bw1, &input);
			do_drive_mono(&info->drv1, &input);
			sample_filter_left(bw2, &input);
			do_drive_mono(&info->drv2, &input);
			sample_filter_left(bw3, &input);
			do_drive_mono(&info->drv3, &input);
			sample_filter_left(bw4, &input);
			sample_filter_left(bq, &input);
			/* mixing */
			input = imuldiv24(input, leveli);
			buf[i] = input;
			buf[i + 1] = input;
			++i;
		}
		break;
	case CH_MONO:
		for (i = 0; i < count; i++) {
			input = buf[i];
			/* waveshaping amp simulation anti-aliasing */
			sample_filter_left(bw1, &input);
			do_drive_mono(&info->drv1, &input);
			sample_filter_left(bw2, &input);
			do_drive_mono(&info->drv2, &input);
			sample_filter_left(bw3, &input);
			do_drive_mono(&info->drv3, &input);
			sample_filter_left(bw4, &input);
			sample_filter_left(bq, &input);
			/* panning */
			input = imuldiv24(input, leveli);
			buf[i] = input;// + high
			i++;
			buf[i] = input;// + high
		}
		break;
	case CH_LEFT:
		for (i = 0; i < count; i++) {
			input = buf[i];
			/* waveshaping amp simulation anti-aliasing */
			sample_filter_left(bw1, &input);
			do_drive_mono(&info->drv1, &input);
			sample_filter_left(bw2, &input);
			do_drive_mono(&info->drv2, &input);
			sample_filter_left(bw3, &input);
			do_drive_mono(&info->drv3, &input);
			sample_filter_left(bw4, &input);
			sample_filter_left(bq, &input);
			/* panning */
			buf[i] = imuldiv24(input, leveli);// + high
			i++;
		}
		break;
	case CH_RIGHT:
		for (i = 0; i < count; i++) {
			i++;
			input = buf[i];
			/* waveshaping amp simulation anti-aliasing */
			sample_filter_right(bw1, &input);
			do_drive_mono(&info->drv1, &input);
			sample_filter_right(bw2, &input);
			do_drive_mono(&info->drv2, &input);
			sample_filter_right(bw3, &input);
			do_drive_mono(&info->drv3, &input);
			sample_filter_right(bw4, &input);
			sample_filter_right(bq, &input);
			/* panning */
			buf[i] = imuldiv24(input, leveli);// + high
		}
		break;
	}
}

static void do_od_ds_parallel(DATA_T *buf, int32 count, InfoOverdrive *info1, InfoOverdrive *info2)
{
	int32 i;
	DATA_T input[2];

	if(count == MAGIC_INIT_EFFECT_INFO) {
		do_od_ds_multi(buf, count, info1);
		do_od_ds_multi(buf, count, info2);
		return;
	}else if(count <= 0)
		return;
	for(i = 0; i < count; i++) {
		input[0] = buf[i]; input[1] = buf[i + 1];
		/* waveshaping amp simulation anti-aliasing */
		sample_filter_left(&info1->bw1, &input[0]);
		sample_filter_left(&info2->bw1, &input[1]);
		do_drive_mono(&info1->drv1, &input[0]);
		do_drive_mono(&info2->drv1, &input[1]);
		sample_filter_left(&info1->bw2, &input[0]);
		sample_filter_left(&info2->bw2, &input[1]);
		do_drive_mono(&info1->drv2, &input[0]);
		do_drive_mono(&info2->drv2, &input[1]);
		sample_filter_left(&info1->bw3, &input[0]);
		sample_filter_left(&info2->bw3, &input[1]);
		do_drive_mono(&info1->drv3, &input[0]);
		do_drive_mono(&info2->drv3, &input[1]);
		sample_filter_left(&info1->bw4, &input[0]);
		sample_filter_left(&info2->bw4, &input[1]);
		sample_filter_left(&info1->bq, &input[0]);
		sample_filter_left(&info2->bq, &input[1]);
		/* panning */
		buf[i] = imuldiv24(input[0], info1->leveli);
		i++;
		buf[i] = imuldiv24(input[1], info2->leveli);
	}
}

#else /* floating-point implementation */

/*! GS 0x0010~: OD DS multi */
static void do_od_ds_multi(DATA_T *buf, int32 count, InfoOverdrive *info)
{
	int32 i;
	double leveld = info->leveld;
	FilterCoefficients *bw1 = &(info->bw1), *bw2 = &(info->bw2), *bw3 = &(info->bw3), *bw4 = &(info->bw4);
	FilterCoefficients *bq = &(info->bq);	
	FLOAT_T bw1_freq, bw2_freq, bw3_freq, bw4_freq;
	int flt2_type, flt3_type, flt4_type;
	DATA_T input;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		/* overdrive distortion */
		if(info->type == 0) { // overdrive
			init_drive(&info->drv1, 4, 0.8, OD_CLIP_LEVEL, calc_gs_drive_gain(info->drive));
			init_drive(&info->drv2, 4, 0.6, OD_CLIP_LEVEL, calc_gs_drive_gain(info->drive));
			bw1_freq = OD_FF1_OD;
			flt2_type = FILTER_NONE;
			flt3_type = FILTER_LPF6;
		}else{ // distortion
			init_drive(&info->drv1, 9, 0.5, OD_CLIP_LEVEL, calc_gs_drive_gain(info->drive));
			init_drive(&info->drv2, 9, 0.2, OD_CLIP_LEVEL, calc_gs_drive_gain(info->drive));
			bw1_freq = OD_FF1_DS;
			flt2_type = FILTER_LPF_BW;
			flt3_type = FILTER_LPF6;
		}
		/* waveshaper amp simulator */
		if (info->amp_sw == 0) {
			init_drive(&info->drv3, 0, 0.0, OD_CLIP_LEVEL, 1.0);
			flt4_type = FILTER_LPF6;
			bw4_freq = OD_FF4_AMPN * otd.gsefx_CustomODFreq;
			info->leveld = info->level * otd.gsefx_CustomODLv * OD_LEVEL * OD_LEVEL_AMPN;
		}else switch(info->amp_type){
		default:
		case 0: // small
			init_drive(&info->drv3, 4, 0.5, OD_CLIP_LEVEL, OD_AMP_GAIN * otd.gsefx_CustomODDrive);
			flt4_type = FILTER_LPF_BW;
			bw4_freq = OD_FF4_AMP0 * otd.gsefx_CustomODFreq;
			info->leveld = info->level * otd.gsefx_CustomODLv * OD_LEVEL * OD_LEVEL_AMP0;
			break;
		case 1: // builtin
			init_drive(&info->drv3, 4, 0.6, OD_CLIP_LEVEL, OD_AMP_GAIN * otd.gsefx_CustomODDrive);
			flt4_type = FILTER_LPF_BW;
			bw4_freq = OD_FF4_AMP1 * otd.gsefx_CustomODFreq;
			info->leveld = info->level * otd.gsefx_CustomODLv * OD_LEVEL * OD_LEVEL_AMP1;
			break;
		case 2: // 2stack
			init_drive(&info->drv3, 4, 0.7, OD_CLIP_LEVEL, OD_AMP_GAIN * otd.gsefx_CustomODDrive);
			flt4_type = FILTER_LPF_BW;
			bw4_freq = OD_FF4_AMP2 * otd.gsefx_CustomODFreq;
			info->leveld = info->level * otd.gsefx_CustomODLv * OD_LEVEL * OD_LEVEL_AMP2;
			break;
		case 3: // 3stack
			init_drive(&info->drv3, 4, 0.8, OD_CLIP_LEVEL, OD_AMP_GAIN * otd.gsefx_CustomODDrive);
			flt4_type = FILTER_LPF_BW;
			bw4_freq = OD_FF4_AMP3 * otd.gsefx_CustomODFreq;
			info->leveld = info->level * otd.gsefx_CustomODLv * OD_LEVEL * OD_LEVEL_AMP3;
			break;
		}
		bw2_freq = OD_FF2;
		bw3_freq = OD_FF3;
		switch(info->mode){
		case CH_MIX_STEREO:
			break;
		case CH_LEFT:
			bw1_freq -= 3.0;
			bw2_freq += 20.0;
			bw3_freq -= 20.0;
			bw4_freq += 20.0;
			break;
		case CH_RIGHT:
			bw1_freq += 3.0;
			bw2_freq -= 20.0;
			bw3_freq += 20.0;
			bw4_freq -= 20.0;
			break;
		}
		init_sample_filter(bw1, bw1_freq, OD_FQ1, FILTER_HPF_BW);
		init_sample_filter(bw2, bw2_freq, OD_FQ2, flt2_type);
		init_sample_filter(bw3, bw3_freq, OD_FQ3, flt3_type);
		init_sample_filter(bw4, bw4_freq, OD_FQ4, flt4_type);
		// cutoff
		init_sample_filter2(bq, OD_FF5 * otd.gsefx_CustomODFreq, 0, OD_FQ5, FILTER_BIQUAD_LOW);
		return;
	}
	switch(info->mode){
	case CH_STEREO:
		for(i = 0; i < count; i++) {
			DATA_T input_d[2] = {buf[i], buf[i + 1]}, tmp_d[2];
			/* waveshaper amp simulator anti-aliasing */
			sample_filter_stereo2(bw1, input_d);
			do_drive_stereo(&info->drv1, input_d);
			sample_filter_stereo2(bw2, input_d);
			do_drive_stereo(&info->drv2, input_d);
			sample_filter_stereo2(bw3, input_d);
			do_drive_stereo(&info->drv3, input_d);
			sample_filter_stereo2(bw4, input_d);
			sample_filter_stereo2(bq, input_d);
			/* mixing */
			buf[i] = input_d[0] * leveld;
			++i;
			buf[i] = input_d[1] * leveld;
		}
		break;
	case CH_MIX_STEREO:
	case CH_MIX_MONO:
		for(i = 0; i < count; i++) {
			int32 indexL;
			input = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			/* waveshaper amp simulator anti-aliasing */
			sample_filter_left(bw1, &input);
			do_drive_mono(&info->drv1, &input);
			sample_filter_left(bw2, &input);
			do_drive_mono(&info->drv2, &input);
			sample_filter_left(bw3, &input);
			do_drive_mono(&info->drv3, &input);
			sample_filter_left(bw4, &input);
			sample_filter_left(bq, &input);
			/* mixing */
			input = input * leveld;
			buf[i] = input;
			++i;
			buf[i] = input;
		}
		break;
	case CH_MONO:
		for(i = 0; i < count; i++) {
			input = buf[i];
			/* waveshaping amp simulation anti-aliasing */
			sample_filter_left(bw1, &input);
			do_drive_mono(&info->drv1, &input);
			sample_filter_left(bw2, &input);
			do_drive_mono(&info->drv2, &input);
			sample_filter_left(bw3, &input);
			do_drive_mono(&info->drv3, &input);
			sample_filter_left(bw4, &input);
			sample_filter_left(bq, &input);
			/* panning */
			input = input * leveld;
			buf[i] = input;
			++i;
			buf[i] = input;
		}
		break;
	case CH_LEFT:
		for(i = 0; i < count; i++) {
			input = buf[i];
			/* waveshaping amp simulation anti-aliasing */
			sample_filter_left(bw1, &input);
			do_drive_mono(&info->drv1, &input);
			sample_filter_left(bw2, &input);
			do_drive_mono(&info->drv2, &input);
			sample_filter_left(bw3, &input);
			do_drive_mono(&info->drv3, &input);
			sample_filter_left(bw4, &input);
			sample_filter_left(bq, &input);
			/* panning */
			buf[i] = input * leveld;// + high
			i++;
		}
		break;
	case CH_RIGHT:
		for(i = 0; i < count; i++) {
			i++;
			input = buf[i];
			/* waveshaping amp simulation anti-aliasing */
			sample_filter_right(bw1, &input);
			do_drive_mono(&info->drv1, &input);
			sample_filter_right(bw2, &input);
			do_drive_mono(&info->drv2, &input);
			sample_filter_right(bw3, &input);
			do_drive_mono(&info->drv3, &input);
			sample_filter_right(bw4, &input);
			sample_filter_right(bq, &input);
			/* panning */
			buf[i] = input * leveld;// + high
		}
		break;
	}
}

static void do_od_ds_parallel(DATA_T *buf, int32 count, InfoOverdrive *info1, InfoOverdrive *info2)
{
	int32 i, j, k;
	DATA_T input[2];

	if(count == MAGIC_INIT_EFFECT_INFO) {
		do_od_ds_multi(buf, count, info1);
		do_od_ds_multi(buf, count, info2);
		return;
	}else if(count <= 0)
		return;
	for(i = 0; i < count; i++) {
		input[0] = buf[i]; input[1] = buf[i + 1];
		/* waveshaping amp simulation anti-aliasing */
		sample_filter_left(&info1->bw1, &input[0]);
		sample_filter_left(&info2->bw1, &input[1]);
		do_drive_mono(&info1->drv1, &input[0]);
		do_drive_mono(&info2->drv1, &input[1]);
		sample_filter_left(&info1->bw2, &input[0]);
		sample_filter_left(&info2->bw2, &input[1]);
		do_drive_mono(&info1->drv2, &input[0]);
		do_drive_mono(&info2->drv2, &input[1]);
		sample_filter_left(&info1->bw3, &input[0]);
		sample_filter_left(&info2->bw3, &input[1]);			
		do_drive_mono(&info1->drv3, &input[0]);
		do_drive_mono(&info2->drv3, &input[1]);
		sample_filter_left(&info1->bw4, &input[0]);
		sample_filter_left(&info2->bw4, &input[1]);
		sample_filter_left(&info1->bq, &input[0]);
		sample_filter_left(&info2->bq, &input[1]);
		/* panning */
		buf[i] = input[0] * info1->leveld;
		i++;
		buf[i] = input[1] * info2->leveld;
	}
}
#endif /* OPT_MODE != 0 */


// phaser_ex
#define PHASER_FEEDBACK (0.5)
#define PHASER_WET (1.00)

// chorus + bpf feedbak
static void do_phaser_multi(DATA_T *buf, int32 count, InfoPhaser *info)
{
	int32 i, j;
	int32 size = info->delay_size, delay_count = info->delay_count;
	DATA_T *ebufL = info->delayL.buf, *ebufR = info->delayR.buf, *hist = info->hist;
	FLOAT_T delayc = info->delaycd, depthc = info->depthcd,
		*lfo_phaseL = info->lfo_phaseL, *lfo_phaseR = info->lfo_phaseR, 
		lfo_count = info->lfo_count, lfo_rate = info->lfo_rate;
	FLOAT_T feedbackd = info->feedbackd, wetd = info->wetd, sub_count;
	DATA_T tmpL, tmpR, inputL, inputR;	

	if(count == MAGIC_INIT_EFFECT_INFO) {
		FLOAT_T ch_diff, div_phase;

		info->phase = !info->phase ? 4 : clip_int(info->phase, 2, 8);
		div_phase = 1.0 / (FLOAT_T)info->phase;
		if(!info->init){
			info->init = 1;
			// 1000ms : pre_delay(GSmax=100ms XGmax=50ms) + depth max 40ms + safety
			set_delay(&info->delayL, (int32)(1000 * playmode_rate_ms + 1));
			set_delay(&info->delayR, (int32)(1000 * playmode_rate_ms + 1));
			if(info->delayL.size < info->delayR.size) // same
				info->delay_size = info->delayL.size - 1;
			else
				info->delay_size = info->delayR.size - 1;
			info->delay_count = 0;
			info->hist[0] = info->hist[1] = 0;
		}
		info->feedbackd = info->feedback * PHASER_FEEDBACK * ext_chorus_feedback;
		info->wetd = PHASER_WET * ext_chorus_level;
		info->delaycd = info->pdelay_ms * playmode_rate_ms;
		if(info->delaycd < 1) {info->delaycd = 1;}
		if(info->depth_type) // depth [ms] p-p
			info->depthcd = info->depth_ms * playmode_rate_ms; // depth_ms = pp_max , -depth
		else // depth [cent]
			info->depthcd = calc_chorus_depth_cent(info->depth_cent, info->rate);
		info->lfo_rate = info->rate * div_playmode_rate;
		ch_diff = info->phase_diff * DIV_360; // deg 0 ~ 360
		if(info->offset <= 0)
			info->offset = 1.0 * DIV_360;
		for (i = 0; i < info->phase; i++) {
			FLOAT_T add_diff = (FLOAT_T)i * div_phase * info->offset;
			lfo_phaseL[i] = (add_diff);
			lfo_phaseR[i] = (add_diff + ch_diff);
		}
		if(info->mode == CH_MIX_STEREO || info->mode == CH_MONO_STEREO)
			info->div_out = pow(1.0 / sqrt((FLOAT_T)info->phase), 0.666666666);
		else
			info->div_out = pow((FLOAT_T)div_phase, 0.666666666);
		init_sample_filter(&info->fc, info->manual, info->reso, FILTER_BPF12_3);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		info->init = 0;
		free_delay(&(info->delayL));
		free_delay(&(info->delayR));
		return;
	}
	switch(info->mode){
	case CH_STEREO:	
#if (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE) && defined(FLOAT_T_DOUBLE)
		{
			__m128d vec_feedback = MM_LOAD1_PD(&info->feedbackd);
			__m128d vec_div_out = MM_LOAD1_PD(&info->div_out);
			__m128d vec_wet = MM_LOAD1_PD(&info->wetd);
			__m128d vec_depthc = MM_LOAD1_PD(&depthc);
			__m128d vec_sub_count;
			__m128d vec_size = _mm_set1_pd(size);
			__m128i vec_add1 = _mm_set1_epi32(1);
			for (i = 0; i < count; i += 2) {
				__m128d vec_input, vec_tmp1;
				ALIGN int32 tmpi[4];
				if(!delay_count){
					ebufL[size] = ebufL[0]; // for linear interpolation
					ebufR[size] = ebufR[0]; // for linear interpolation
				}
				if(++delay_count >= size) {delay_count -= size;}
				if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}
				vec_sub_count = _mm_set1_pd((FLOAT_T)delay_count - delayc);
				vec_input = _mm_load_pd(&buf[i]);
				vec_tmp1 = MM_FMA_PD(_mm_loadu_pd(hist), vec_feedback, vec_input);
				_mm_store_sd(&ebufL[delay_count], vec_tmp1);
				_mm_store_sd(&ebufR[delay_count], _mm_shuffle_pd(vec_tmp1, vec_tmp1, 0x1));
				vec_tmp1 = _mm_setzero_pd();
				for (j = 0; j < info->phase; j++) {
					int32 indexL, indexR;
					__m128d vec_v1, vec_v2, vec_fp, vec_fp2, vec_add_size, vin1, vin2;
					__m128i vec_index;
					vec_fp = _mm_set_pd(
						lookup2_sine_p(lfo_count + lfo_phaseR[j]), 
						lookup2_sine_p(lfo_count + lfo_phaseL[j]) );
					vec_fp = _mm_sub_pd(vec_sub_count, _mm_mul_pd(vec_depthc, vec_fp));
					vec_add_size = _mm_and_pd(vec_size, _mm_cmplt_pd(vec_fp, _mm_setzero_pd()));
					vec_fp = _mm_add_pd(vec_fp, vec_add_size);
					vec_index = _mm_cvttpd_epi32(vec_fp);
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1 floor
					vec_fp = _mm_sub_pd(vec_fp, _mm_floor_pd(vec_fp));
#else
					vec_fp = _mm_sub_pd(vec_fp, _mm_cvtepi32_pd(vec_index));
#endif
					vin1 = _mm_loadu_pd(&ebufL[_mm_cvtsi128_si32(vec_index)]); // L, L+1
					vin2 = _mm_loadu_pd(&ebufR[_mm_cvtsi128_si32(_mm_shuffle_epi32(vec_index, 0x55))]); // R, R+1
					vec_v1 = _mm_shuffle_pd(vin1, vin2, 0x0); //  L, R
					vec_v2 = _mm_shuffle_pd(vin1, vin2, 0x3); //  L+1, R+1
					vec_v2 = _mm_sub_pd(vec_v2, vec_v1);
					vec_tmp1 = _mm_add_pd(vec_tmp1, MM_FMA_PD(vec_v2, vec_fp, vec_v1)); // linear interpolation
				}
				vec_tmp1 = MM_MSUB_PD(vec_tmp1, vec_div_out, vec_input);
				_mm_storeu_pd(&buf[i], _mm_mul_pd(vec_tmp1, vec_wet));
				_mm_storeu_pd(hist, vec_tmp1);
				sample_filter_stereo2(&info->fc, hist);
			}
		}
#else
		for (i = 0; i < count; i++) {			
			if(!delay_count){
				ebufL[size] = ebufL[0]; // for linear interpolation
				ebufR[size] = ebufR[0]; // for linear interpolation
			}
			if(++delay_count >= size) {delay_count -= size;}
			if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}
			sub_count = (FLOAT_T)delay_count - delayc;
			inputL = buf[i]; inputR = buf[i + 1];	
			ebufL[delay_count] = inputL + hist[0] * feedbackd;
			ebufR[delay_count] = inputR + hist[1] * feedbackd;
			tmpL = 0; tmpR = 0;
			for (j = 0; j < info->phase; j++) {
				int32 indexL, indexR;
				DATA_T v1L, v2L, v1R, v2R;
				FLOAT_T fp1L, fp1R, fp2L, fp2R;
				fp1L = sub_count - depthc * lookup2_sine_p((lfo_count + lfo_phaseL[j]));
				fp1R = sub_count - depthc * lookup2_sine_p((lfo_count + lfo_phaseR[j]));
				if(fp1L < 0) fp1L += size;				
				if(fp1R < 0) fp1R += size;	
				fp2L = floor(fp1L); fp2R = floor(fp1R);
				indexL = fp2L; indexR = fp2R;
				v1L = ebufL[indexL]; v2L = ebufL[indexL + 1];
				v1R = ebufR[indexR]; v2R = ebufR[indexR + 1];
				tmpL += v1L + (v2L - v1L) * (fp1L - fp2L);
				tmpR += v1R + (v2R - v1R) * (fp1R - fp2R);
			}
			tmpL *= info->div_out;
			tmpR *= info->div_out;
			hist[0] = tmpL - inputL;
			hist[1] = tmpR - inputR;
			buf[i] = hist[0] * wetd;
			buf[++i] = hist[1] * wetd;
			sample_filter_stereo2(&info->fc, hist);
		}
#endif
		break;
	case CH_MIX_STEREO:
	case CH_MIX_MONO:
		for (i = 0; i < count; i++) {					
			if(!delay_count)
				ebufL[size] = ebufL[0]; // for linear interpolation
			if(++delay_count >= size) {delay_count -= size;}
			if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}
			sub_count = (FLOAT_T)delay_count - delayc;
			inputL = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			ebufL[delay_count] = inputL + hist[0] * feedbackd;
			tmpL = 0;
			for (j = 0; j < info->phase; j++) {
				int32 index;
				DATA_T v1, v2;
				FLOAT_T fp1, fp2;
				fp1 = sub_count - depthc * lookup2_sine_p((lfo_count + lfo_phaseL[j]));
				if(fp1 < 0) fp1 += size;	
				fp2 = floor(fp1);
				index = fp2;
				v1 = ebufL[index]; v2 = ebufL[index + 1];
				tmpL += v1 + (v2 - v1) * (fp1 - fp2);
			}
			tmpL *= info->div_out;
			hist[0] = tmpL - inputL;
			tmpL = hist[0] * wetd;
			buf[i] = tmpL;
			buf[++i] = tmpL;
			sample_filter_left(&info->fc, &hist[0]);
		}
		break;
	case CH_MONO_STEREO:
	case CH_MONO:
		for (i = 0; i < count; i++) {				
			if(!delay_count)
				ebufL[size] = ebufL[0]; // for linear interpolation
			if(++delay_count >= size) {delay_count -= size;}
			if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}
			sub_count = (FLOAT_T)delay_count - delayc;
			inputL = buf[i];		
			ebufL[delay_count] = inputL + hist[0] * feedbackd;
			tmpL = 0;
			for (j = 0; j < info->phase; j++) {
				int32 index;
				DATA_T v1, v2;
				FLOAT_T fp1, fp2;
				fp1 = sub_count - depthc * lookup2_sine_p((lfo_count + lfo_phaseL[j]));
				if(fp1 < 0) fp1 += size;	
				fp2 = floor(fp1);
				index = fp2;
				v1 = ebufL[index]; v2 = ebufL[index + 1];
				tmpL += v1 + (v2 - v1) * (fp1 - fp2);
			}
			tmpL *= info->div_out;
			hist[0] = tmpL - inputL;
			tmpL = hist[0] * wetd;
			buf[i] = tmpL;
			buf[++i] = tmpL;
			sample_filter_left(&info->fc, &hist[0]);
		}
		break;
	case CH_LEFT:
		for (i = 0; i < count; i++) {				
			if(!delay_count)
				ebufL[size] = ebufL[0]; // for linear interpolation
			if(++delay_count >= size) {delay_count -= size;}
			if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}
			sub_count = (FLOAT_T)delay_count - delayc;
			inputL = buf[i];
			ebufL[delay_count] = inputL + hist[0] * feedbackd;
			tmpL = 0;
			for (j = 0; j < info->phase; j++) {
				int32 index;
				DATA_T v1, v2;
				FLOAT_T fp1, fp2;
				fp1 = sub_count - depthc * lookup2_sine_p((lfo_count + lfo_phaseL[j]));
				if(fp1 < 0) fp1 += size;	
				fp2 = floor(fp1);
				index = fp2;
				v1 = ebufL[index]; v2 = ebufL[index + 1];
				tmpL += v1 + (v2 - v1) * (fp1 - fp2);
			}
			tmpL *= info->div_out;
			hist[0] = tmpL - inputL;
			buf[i++] = hist[0] * wetd;
			sample_filter_left(&info->fc, &hist[0]);
		}
		break;
	case CH_RIGHT:
		for (i = 0; i < count; i++) {				
			if(!delay_count)
				ebufR[size] = ebufR[0]; // for linear interpolation
			if(++delay_count >= size) {delay_count -= size;}
			if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}
			sub_count = (FLOAT_T)delay_count - delayc;		
			inputR = buf[++i];		
			ebufR[delay_count] = inputR + hist[1] * feedbackd;
			tmpR = 0;
			for (j = 0; j < info->phase; j++) {
				int32 index;
				DATA_T v1, v2;
				FLOAT_T fp1, fp2;
				fp1 = sub_count - depthc * lookup2_sine_p((lfo_count + lfo_phaseR[j]));
				if(fp1 < 0) fp1 += size;	
				fp2 = floor(fp1);
				index = fp2;
				v1 = ebufR[index]; v2 = ebufR[index + 1];
				tmpR += v1 + (v2 - v1) * (fp1 - fp2);
			}
			tmpR *= info->div_out;
			hist[1] = tmpR - inputR;
			buf[i] = hist[1] * wetd;
			sample_filter_right(&info->fc, &hist[1]);
		}
		break;
	}
	info->delay_count = delay_count, info->lfo_count = lfo_count;
}



#define AW_LEVEL (1.0)
#define AW_LPF_LEVEL (2.5 * AW_LEVEL)
#define AW_BPF_LEVEL (5.0 * AW_LEVEL)
#define AW_PEAK_TIME (5.0) // ms
#define AW_SENS_ATTACK_TIME (10.0) // min ms 
#define AW_SENS_RELEASE_TIME (10.0) // min ms 
#define AW_MAN_ENV_TIME (10.0) // ms
#define AW_FLT_ENV_TIME (5.0) // ms
#define AW_BPF_WIDTH (0.85)
#define AW_DEPTH_MAX (10.66666666666666666666666666666) // 128 * DIV_12 // from XG AutoWah

static FLOAT_T calc_auto_wah_sens_gs(int in){
	return (double)in * DIV_127;
}

static FLOAT_T calc_auto_wah_sens_xg(int in){
	return (double)in * DIV_127;
}

static FLOAT_T calc_auto_wah_manual_gs(int in){
	return manual_table[in]; // Hz
}

static FLOAT_T calc_auto_wah_manual_xg(int in){
	return manual_table[in]; // Hz
//	return (double)in * DIV_127 * 3900.0 + 100.0; // Hz
}

static FLOAT_T calc_auto_wah_peak_gs(int in){
	return (double)clip_int(in, 0, 127) * DIV_127 * 12.0; // dB
}

static FLOAT_T calc_auto_wah_peak_xg(int in){
	return (double)clip_int(in, 10, 120) * DIV_10; // 12dB
}

static void do_auto_wah_multi(DATA_T *buf, int32 count, InfoAutoWah *info)
{
	int32 i, cnt = count / 2;
	DATA_T tmp, tmpm;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		//info->type = 1; // 0:lpf 1:bpf
		//info->pol = 1; // 0:down 1:up
		//info->depth = 1.0; // 0.0 ~ 1.0
		//info->manual = 800; // Hz
		//info->peak = 12.0; // dB
		//info->lfo_sw = 0; // 0:off 1:on
		//info->rate = 2.0; // Hz
		//info->sens_sw = 1; // 0:off 1:on
		//info->sens = 1.0; //
		//info->release = 25.0; // ms
		if(!info->init){
			info->init = 1;
			info->peak_rate = 0.0;
			info->sens_level = 0.0;
			info->lfo_rate = 0; 
			info->env_mode = 0;
			init_envelope3(&info->sens_env, 0.0, AW_SENS_ATTACK_TIME * playmode_rate_ms);
			init_envelope3(&info->flt_env, info->manual, AW_FLT_ENV_TIME * playmode_rate_ms);
			if(info->type){
				set_sample_filter_type(&info->fc, FILTER_BPF12_3); // or BPF_BW
			}else{
				set_sample_filter_type(&info->fc, FILTER_LPF_BW);
			}
			info->ptype = info->type;
			init_envelope3(&info->man_env, info->manual, AW_SENS_ATTACK_TIME * playmode_rate_ms);
			set_sample_filter_freq(&info->fc, info->manual);
			set_sample_filter_reso(&info->fc, info->peak);
		}
		if(info->lfo_sw){
			info->lfo_freq = info->rate * div_playmode_rate;
			info->depth_mult = info->depth * AW_DEPTH_MAX;
			info->depth_mult *= info->pol ? 1.0 : (-1.0);
		}
		if(info->sens_sw){
			info->sens_mult = (0.25 + info->sens) / 1.25 * AW_DEPTH_MAX;
			info->sens_coef = 1.0 / (ins_level * DIV_4 * pow(10.0, -info->sens * 0.6));
			info->peak_count = (1000.0 / AW_PEAK_TIME) * div_playmode_rate;
			if(info->release <= AW_SENS_RELEASE_TIME)
				info->release = AW_SENS_RELEASE_TIME;
			info->release_cnt = info->release * playmode_rate_ms;
			info->attack_cnt = AW_SENS_ATTACK_TIME * playmode_rate_ms;
		}
		if(info->type != info->ptype){
			if(info->type){
				set_sample_filter_type(&info->fc, FILTER_BPF12_3);
			}else{
				set_sample_filter_type(&info->fc, FILTER_LPF_BW);
			}
			info->ptype = info->type;
			init_envelope3(&info->man_env, info->manual, AW_SENS_ATTACK_TIME * playmode_rate_ms);
			set_sample_filter_freq(&info->fc, info->manual);
		}
		reset_envelope3(&info->man_env, info->manual, ENVELOPE_KEEP);
		set_sample_filter_reso(&info->fc, info->peak); // peak to dB
		info->in_leveld = otd.efx_CustomWahLvIn;
		if(info->type)
			info->leveld = AW_BPF_LEVEL * otd.efx_CustomWahLvOut;
		else
			info->leveld = AW_LPF_LEVEL * otd.efx_CustomWahLvOut;		
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		info->init = 0;
		return;
	} else if(count == 0) {
		return;
	}
	compute_envelope3(&info->man_env, cnt);
	if(info->sens_sw && info->lfo_sw){
		FLOAT_T cutoff, sens_out, lfo_out;
		// peak level
		if((info->peak_rate += info->peak_count * cnt) >= 1.0){
			FLOAT_T sens_level = info->peak_level * info->sens_coef;
			info->peak_rate -= floor(info->peak_rate); // reset count
			if(sens_level > 1.0)
				sens_level = 1.0;
			if(sens_level > info->sens_level){ 
				info->env_mode = 0; // attack
				info->sens_level = sens_level;
				reset_envelope3(&info->sens_env, sens_level, info->attack_cnt * (sens_level - info->sens_level));
			}else if(sens_level < info->sens_level && (info->env_mode || !check_envelope3(&info->sens_env))){ // after attack time
				info->env_mode = 1; // release
				info->sens_level = sens_level;
				reset_envelope3(&info->sens_env, sens_level, info->release_cnt * (info->sens_level - sens_level));
			}
			info->peak_level = 0;
		}
		// lfo
		if((info->lfo_rate += info->lfo_freq * cnt) >= 1.0)
			info->lfo_rate -= floor(info->lfo_rate); // reset count
		lfo_out = (info->lfo_rate < 0.5) ? (info->lfo_rate * 2.0) : (info->lfo_rate * -2.0 + 2.0); // triangular // lfo_out 0.0~<1.0	
		// cutoff
		cutoff = info->man_env.vol * POW2(info->sens_env.vol * info->sens_mult) * POW2(lfo_out * info->depth_mult);
		cutoff = clip_FLOAT_T(cutoff, manual_table[0], manual_table[127]);
		reset_envelope3(&info->flt_env, cutoff, ENVELOPE_KEEP);
	}else if(info->sens_sw){	
		FLOAT_T cutoff, sens_out;
		// peak level
		if((info->peak_rate += info->peak_count * cnt) >= 1.0){
			FLOAT_T sens_level = info->peak_level * info->sens_coef;
			info->peak_rate -= floor(info->peak_rate); // reset count
			if(sens_level > 1.0)
				sens_level = 1.0;
			if(sens_level > info->sens_level){ 
				info->env_mode = 0; // attck
				info->sens_level = sens_level;
				reset_envelope3(&info->sens_env, sens_level, info->attack_cnt * (sens_level - info->sens_level));
			}else if(sens_level < info->sens_level && (info->env_mode || !check_envelope3(&info->sens_env))){ // after attack time
				info->env_mode = 1; // release
				info->sens_level = sens_level;
				reset_envelope3(&info->sens_env, sens_level, info->release_cnt * (info->sens_level - sens_level));
			}
			info->peak_level = 0;
		}
		compute_envelope3(&info->sens_env, cnt);
		// cutoff
		cutoff = info->man_env.vol * POW2(info->sens_env.vol * info->sens_mult);
		cutoff = clip_FLOAT_T(cutoff, manual_table[0], manual_table[127]);
		reset_envelope3(&info->flt_env, cutoff, ENVELOPE_KEEP);
	}else if(info->lfo_sw){	
		FLOAT_T cutoff, lfo_out;	
		// lfo	
		if((info->lfo_rate += info->lfo_freq * cnt) >= 1.0)
			info->lfo_rate -= floor(info->lfo_rate); // reset count
		lfo_out = (info->lfo_rate < 0.5) ? (info->lfo_rate * 2.0) : (info->lfo_rate * -2.0 + 2.0); // triangular // lfo_out 0.0~<1.0	
		// cutoff
		cutoff = info->man_env.vol * POW2(lfo_out * info->depth_mult);
		cutoff = clip_FLOAT_T(cutoff, manual_table[0], manual_table[127]);
		reset_envelope3(&info->flt_env, cutoff, ENVELOPE_KEEP);
	}else
		reset_envelope3(&info->flt_env, info->man_env.vol, ENVELOPE_KEEP);
	compute_envelope3(&info->flt_env, cnt);
	// filter
	set_sample_filter_freq(&info->fc, info->flt_env.vol);
	recalc_filter(&info->fc);

	switch(info->mode){
	case CH_STEREO:
		for (i = 0; i < count; i++)
		{
			DATA_T inputL = buf[i] * info->in_leveld;
			DATA_T inputR = buf[i + 1] * info->in_leveld;
			if((tmpm = fabs((FLOAT_T)inputL)) > info->peak_level)
				info->peak_level = tmpm;
			if((tmpm = abs((DATA_T)inputR)) > info->peak_level)
				info->peak_level = tmpm;
			sample_filter_stereo(&info->fc, &inputL, &inputR);	
			buf[i] = inputL * info->leveld;
			i++;
			buf[i] = inputR * info->leveld;
		}
		break;
	case CH_MIX_STEREO:
	case CH_MIX_MONO:
		for (i = 0; i < count; i++)
		{
			tmp = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL * info->in_leveld;
			tmpm = fabs((FLOAT_T)tmp);
			if(tmpm > info->peak_level)
				info->peak_level = tmpm;
			sample_filter_left(&info->fc, &tmp);	
			tmp *= info->leveld;
			buf[i] = tmp;
			i++;
			buf[i] = tmp;
		}
		break;
	case CH_MONO_STEREO:
	case CH_MONO:
		for (i = 0; i < count; i++)
		{
			tmp = buf[i] * info->in_leveld;
			tmpm = fabs((FLOAT_T)tmp);
			if(tmpm > info->peak_level)
				info->peak_level = tmpm;
			sample_filter_left(&info->fc, &tmp);	
			tmp *= info->leveld;
			buf[i] = tmp;
			i++;
			buf[i] = tmp;

		}
		break;
	case CH_LEFT:
		for (i = 0; i < count; i++)
		{
			tmp = buf[i] * info->in_leveld;
			tmpm = fabs((FLOAT_T)tmp);
			if(tmpm > info->peak_level)
				info->peak_level = tmpm;
			sample_filter_left(&info->fc, &tmp);
			buf[i] = tmp * info->leveld;
			i++;

		}
		break;
	case CH_RIGHT:
		for (i = 0; i < count; i++)
		{
			i++;
			tmp = buf[i] * info->in_leveld;
			tmpm = fabs((FLOAT_T)tmp);
			if(tmpm > info->peak_level)
				info->peak_level = tmpm;
			sample_filter_right(&info->fc, &tmp);
			buf[i] = tmp * info->leveld;
		}
		break;
	}
}


#define ROTALY_LEVEL      (1.5)
#define ROTALY_ACCEL_MIN  (1000.0) // ms
#define ROTALY_ACCEL_MAX  (5000.0) // ms
#define ROTARY_LOW_CUTOFF (2000.0) // Hz
#define ROTARY_HI_CUTOFF  (1000.0) // Hz
#define ROTARY_LPF_CUTOFF (8000.0) // Hz
#define ROTARY_LPF_MULT   (4.00) // 1.0 ~ 1/MULT
#define ROTARY_VOL_DEPTH  (0.5)
#define ROTARY_PAN_DEPTH  (0.125)

static void do_rotary_multi(DATA_T *buf, int32 count, InfoRotary *info)
{
	Envelope3 *low_env = &info->low_env, *hi_env = &info->hi_env;
	int i, cnt = count / 2;
	double low_vol, low_pan, hi_vol, hi_pan, spl, spr;
	double l_lv, h_lv, ll_lv, lh_lv, rl_lv, rh_lv;
	DATA_T low_tmp, hi_tmp;

	if (count == MAGIC_INIT_EFFECT_INFO) {
		if(!info->init){
			info->init = 1;
			init_sample_filter(&info->fc_rotL, ROTARY_LOW_CUTOFF, 1.0, FILTER_LPF_BW); // scoker
			init_sample_filter(&info->fc_rotH, ROTARY_HI_CUTOFF, 1.0, FILTER_HPF_BW); // tweeter
			init_sample_filter(&info->fc_lpfL, ROTARY_LPF_CUTOFF, 1.0, FILTER_LPF6); // cycle
			init_sample_filter(&info->fc_lpfH, ROTARY_LPF_CUTOFF, 1.0, FILTER_LPF6); // cycle
			if(info->speed == 0){
				init_envelope3(low_env, info->low_slow_freq, info->low_cnt);
				init_envelope3(hi_env, info->hi_slow_freq, info->hi_cnt);
			}else{
				init_envelope3(low_env, info->low_fast_freq, info->low_cnt);
				init_envelope3(hi_env, info->hi_fast_freq, info->hi_cnt);
			}
			info->speedp = info->speed;
			info->low_rate = 0;
			info->hi_rate = 0;
		}
		info->low_cnt = (ROTALY_ACCEL_MIN * info->low_accl + ROTALY_ACCEL_MAX * (1.0 - info->low_accl)) * playmode_rate_ms;
		info->hi_cnt = (ROTALY_ACCEL_MIN * info->hi_accl + ROTALY_ACCEL_MAX * (1.0 - info->hi_accl)) * playmode_rate_ms;
		info->low_slow_freq = info->low_slow * div_playmode_rate;
		info->low_fast_freq = info->low_fast * div_playmode_rate;
		info->hi_slow_freq = info->hi_slow * div_playmode_rate;
		info->hi_fast_freq = info->hi_fast * div_playmode_rate;
		info->low_leveld = info->low_level * ROTALY_LEVEL * otd.efx_CustomRotLvOut;
		info->hi_leveld = info->hi_level * ROTALY_LEVEL * otd.efx_CustomRotLvOut;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		info->init = 0;
		return;
	} else if(count == 0) {
		return;
	}
	if(info->speedp != info->speed){
		if(info->speed == 0){
			reset_envelope3(low_env, info->low_slow_freq, info->low_cnt);
			reset_envelope3(hi_env, info->hi_slow_freq, info->hi_cnt);
		}else{
			reset_envelope3(low_env, info->low_fast_freq, info->low_cnt);
			reset_envelope3(hi_env, info->hi_fast_freq, info->hi_cnt);
		}
	}
	compute_envelope3(low_env, cnt);
	compute_envelope3(hi_env, cnt);	
	low_vol = lookup2_sine_p(info->low_rate) * ROTARY_VOL_DEPTH;
	low_pan = (lookup2_sine_p(info->low_rate + DIV_4) * ROTARY_PAN_DEPTH - 0.5) * info->separate + 0.5;		
	hi_vol = lookup2_sine_p(info->hi_rate) * ROTARY_VOL_DEPTH;
	hi_pan = (lookup2_sine_p(info->hi_rate + DIV_4) * ROTARY_PAN_DEPTH - 0.5) * info->separate + 0.5;	
	l_lv = (1.0 - low_vol) * info->low_leveld;
	h_lv = (1.0 - hi_vol) * info->hi_leveld;
	// lowとhiで回転方向逆にする
	ll_lv = l_lv * (1.0 - low_pan);
	lh_lv = h_lv * hi_pan;
	rl_lv = l_lv * low_pan;
	rh_lv = h_lv * (1.0 - hi_pan);
	set_sample_filter_freq(&info->fc_lpfL, ROTARY_LPF_CUTOFF * pow(ROTARY_LPF_MULT, -lookup2_sine_p(info->low_rate)));
	set_sample_filter_freq(&info->fc_lpfL, ROTARY_LPF_CUTOFF * pow(ROTARY_LPF_MULT, -lookup2_sine_p(info->hi_rate)));
	recalc_filter(&info->fc_lpfL);
	recalc_filter(&info->fc_lpfH);
	if((info->low_rate += low_env->vol * cnt) >= 1.0)
		info->low_rate -= floor(info->low_rate);
	if((info->hi_rate += hi_env->vol * cnt) >= 1.0)
		info->hi_rate -= floor(info->hi_rate);
	switch(info->mode){
	case CH_MIX_STEREO:
		for (i = 0; i < count; i++)
		{
			low_tmp = hi_tmp = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL; // mix
			sample_filter(&info->fc_rotL, &low_tmp);
			sample_filter(&info->fc_lpfL, &low_tmp);
			sample_filter(&info->fc_rotH, &hi_tmp);
			sample_filter(&info->fc_lpfH, &hi_tmp);	
			buf[i] = low_tmp * ll_lv + hi_tmp * lh_lv;
			i++;
			buf[i] = low_tmp * rl_lv + hi_tmp * rh_lv;
		}
		break;
	case CH_MONO_STEREO:
		for (i = 0; i < count; i++)
		{
			low_tmp = hi_tmp = buf[i]; // mono (left
			sample_filter(&info->fc_rotL, &low_tmp);
			sample_filter(&info->fc_lpfL, &low_tmp);
			sample_filter(&info->fc_rotH, &hi_tmp);
			sample_filter(&info->fc_lpfH, &hi_tmp);	
			buf[i] = low_tmp * ll_lv + hi_tmp * lh_lv;
			i++;
			buf[i] = low_tmp * rl_lv + hi_tmp * rh_lv;
		}
		break;
	case CH_RIGHT:
		for (i = 0; i < count; i++)
		{
			i++;
			low_tmp = hi_tmp = buf[i];
			sample_filter(&info->fc_rotL, &low_tmp);
			sample_filter(&info->fc_lpfL, &low_tmp);
			sample_filter(&info->fc_rotH, &hi_tmp);
			sample_filter(&info->fc_lpfH, &hi_tmp);	
			buf[i] = low_tmp * rl_lv + hi_tmp * rh_lv;
		}
		break;
	}
}


#if (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE) && defined(FLOAT_T_DOUBLE)
static void do_tremolo_pmod_st(InfoTremolo *info, DATA_T *buf, FLOAT_T *vol)
{
	Envelope3 *pm_env = &info->pm_env;
	DATA_T *ebufL = &info->buf[0], *ebufR = &info->buf[info->size + 1];
	const __m128d vc1 = _mm_set1_pd(1.0), vcsd2 = _mm_set1_pd(-DIV_2);
	__m128d vsizef = _mm_set1_pd((double)info->size);
	__m128d vfp = _mm_loadu_pd(vol);
	__m128d vin1, vin2, vv1, vv2;
	__m128i vindex;
	FLOAT_T countf;
	
	compute_envelope3(pm_env, 1);
	if(!info->count){
		ebufL[info->size] = ebufL[0]; // for linear interpolation
		ebufR[info->size] = ebufR[0]; // for linear interpolation
	}
	if(++info->count >= info->size) {info->count = 0;}
	ebufL[info->count] = buf[0];
	ebufR[info->count] = buf[1];
	countf = info->count - 2; // must delay >=1sample
	vfp = _mm_mul_pd(_mm_add_pd(vfp, vc1), vcsd2);		
	vfp = MM_FMA_PD(vfp, MM_LOAD1_PD(&pm_env->vol), MM_LOAD1_PD(&countf));
	vfp = _mm_add_pd(vfp, _mm_and_pd(vsizef, _mm_cmplt_pd(vfp, _mm_setzero_pd())));		
	vindex = _mm_cvttpd_epi32(vfp);
#if (USE_X86_EXT_INTRIN >= 6) // sse4.1 floor
	vfp = _mm_sub_pd(vfp, _mm_floor_pd(vfp));
#else
	vfp = _mm_sub_pd(vfp, _mm_cvtepi32_pd(vindex));
#endif	
	vin1 = _mm_loadu_pd(&ebufL[_mm_cvtsi128_si32(vindex)]); // L, L+1
	vin2 = _mm_loadu_pd(&ebufR[MM_EXTRACT_EPI32(vindex, 0x1)]); // R, R+1
	vv1 = _mm_shuffle_pd(vin1, vin2, 0x0); //  L,L+1 , R,R+1 to L,R
	vv2 = _mm_shuffle_pd(vin1, vin2, 0x3); //  L,L+1 , R,R+1 to L+1, R+1
	vv1 = MM_FMA_PD(_mm_sub_pd(vv2, vv1), vfp, vv1); // linear interpolation
	_mm_storeu_pd(buf, vv1);
}

#else
static inline void do_tremolo_pmod_st(InfoTremolo *info, DATA_T *buf, FLOAT_T *vol)
{
	Envelope3 *pm_env = &info->pm_env;
	DATA_T *ebufL = &info->buf[0], *ebufR = &info->buf[info->size + 1];
	int32 indexL, indexR;
	DATA_T v1L, v2L, v1R, v2R;
	FLOAT_T fp1L, fp2L, fp1R, fp2R, countf, sizef = info->size;
	
	compute_envelope3(pm_env, 1);
	if(!info->count){
		ebufL[info->size] = ebufL[0]; // for linear interpolation
		ebufR[info->size] = ebufR[0]; // for linear interpolation
	}
	if((++info->count) >= info->size) {info->count = 0;}
	ebufL[info->count] = buf[0];
	ebufR[info->count] = buf[1];	
	countf = info->count - 2; // must delay >1sample
	fp1L = countf - (vol[0] + 1.0) * DIV_2 * pm_env->vol;
	fp1R = countf - (vol[1] + 1.0) * DIV_2 * pm_env->vol;
	if(fp1L < 0) {fp1L += sizef;}	
	if(fp1R < 0) {fp1R += sizef;}			
	fp2L = floor(fp1L);	
	fp2R = floor(fp1R);
	indexL = fp2L;
	indexR = fp2R;
	v1L = ebufL[indexL]; v2L = ebufL[indexL + 1];
	v1R = ebufR[indexR]; v2R = ebufR[indexR + 1];
	buf[0] = v1L + (v2L - v1L) * (fp1L - fp2L); // linear interpolation
	buf[1] = v1R + (v2R - v1R) * (fp1R - fp2R); // linear interpolation		
}
#endif

static inline void do_tremolo_pmod_mono(InfoTremolo *info, DATA_T *buf, FLOAT_T *vol)
{
	Envelope3 *pm_env = &info->pm_env;
	DATA_T *ebufL = &info->buf[0];
	int32 indexL;
	DATA_T v1L, v2L;
	FLOAT_T fp1L, fp2L, countf, sizef = info->size;
	
	compute_envelope3(pm_env, 1);
	if(!info->count){
		ebufL[info->size] = ebufL[0]; // for linear interpolation
	}
	if(++info->count >= info->size) {info->count = 0;}
	ebufL[info->count] = buf[0];	
	countf = info->count - 2; // must delay >1sample
	fp1L = (FLOAT_T)info->count - (vol[0] + 1.0) * DIV_2 * pm_env->vol;
	if(fp1L >= info->size) {fp1L -= info->size;}	
	else if(fp1L < 0) {fp1L += info->size;}		
	fp2L = floor(fp1L);	
	indexL = fp2L;
	v1L = ebufL[indexL]; v2L = ebufL[indexL + 1];
	buf[0] = v1L + (v2L - v1L) * (fp1L - fp2L); // linear interpolation
}

static void do_tremolo_autopan(DATA_T *buf, int32 count, InfoTremolo *info)
{
	Oscillator2 *lfo = &info->lfo;
	Envelope2 *env = &info->env;
	Envelope3 *pm_env = &info->pm_env;
	int i, cnt = count / 2;
	FLOAT_T tmp;
	ALIGN FLOAT_T data[2];

	if (count == MAGIC_INIT_EFFECT_INFO) {
#if 0 // test
		info->pm_mode = 1;
		info->depth_cent = calc_chorus_depth_xg(127);
		info->depth = 0.0;
#endif
		if(!info->init){
			info->init = 1;
			info->pre_type = info->type;
			info->pre_wave = info->wave;
			info->pre_phase = info->phase;
			tmp = info->phase * DIV_360;
			if(tmp < 0) tmp += 1.0;
			init_oscillator2(lfo, info->rate, info->wave, 0.0, tmp); // tmp==0 trem , tmp!=0 autopan
			init_envelope2(env, info->rate, info->depth, playmode_rate_ms * 500.0); // 500ms
			if(info->pm_mode){
				// 200ms : depth max 40ms + safety
				int32 size = 100.0 * playmode_rate_ms;
				int32 byte = sizeof(DATA_T) * (size + 1) * 2; // +1 interp, * 2ch
#ifdef ALIGN_SIZE
				info->buf = (DATA_T*)aligned_malloc(byte, ALIGN_SIZE);
#else
				info->buf = (DATA_T*)safe_malloc(byte);
#endif
				if(!info->buf){	
					info->pm_mode = 0;
					return;
				}
				memset(info->buf, 0, byte);
				info->size = size;
				info->count = 0; // delay_count
				info->depth_cnt = calc_chorus_depth_cent(info->depth_cent, info->rate); // depth [cent]
				init_envelope3(pm_env, info->depth_cnt, playmode_rate_ms * 100.0); // 100ms
				info->pm_init = 1;
			}
			return;
		}
		if(info->pre_type != info->type || info->pre_wave != info->wave || info->pre_phase != info->phase){	
			info->pre_type = info->type;
			info->pre_wave = info->wave;	
			info->pre_phase = info->phase;	
			tmp = info->phase * DIV_360;
			if(tmp < 0) tmp += 1.0;
			init_oscillator2(lfo, info->rate, info->wave, 0.0, tmp); // tmp==0 trem , tmp!=0 autopan
			init_envelope2(env, info->rate, info->depth, playmode_rate_ms * 500.0); // 500ms
		}else{
			reset_envelope2(env, info->rate, info->depth, ENVELOPE_KEEP);
		}	
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		if(info->pm_init){
			if(info->buf){	
#ifdef ALIGN_SIZE
				aligned_free(info->buf);
#else
				safe_free(info->buf);
#endif
				info->buf = NULL;
				return;
			}
		}
		return;
	} else if(count == 0) {
		return;
	}
	compute_envelope2(env, cnt); // vol[0] : lfo freq , vol[1] : depth
	reset_oscillator2(lfo, env->vol[0]);
	if(info->pm_mode){
		reset_envelope3(pm_env, calc_chorus_depth_cent(info->depth_cent, env->vol[0]), ENVELOPE_KEEP);
	}
	switch(info->mode){
#if (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE) && defined(FLOAT_T_DOUBLE)
	case CH_STEREO:
		{
			const __m128d vc1 = _mm_set1_pd(1.0), vcs1 = _mm_set1_pd(-1.0);
			__m128d vdepth = MM_LOAD1_PD(&env->vol[1]);	
			__m128d vtmp, vout, vdata;
			vdepth = _mm_mul_pd(vdepth, vcs1); // -depth
			for (i = 0; i < count; i += 2)
			{
				data[0] = buf[i]; data[1] = buf[i + 1];
				compute_oscillator2(lfo, 1);
				if(info->pm_mode)
					do_tremolo_pmod_st(info, data, lfo->out);
				vout = _mm_loadu_pd(lfo->out);
				vtmp = MM_FMA_PD(vout, vdepth, vc1); // out * (-depth) + 1.0 
				vdata =	_mm_load_pd(data);
				vdata =	_mm_mul_pd(vdata, vtmp);
				_mm_storeu_pd(&buf[i], vdata);
			}
		}
		break;
	case CH_MIX_STEREO:
		{
			const __m128d vc1 = _mm_set1_pd(1.0), vcs1 = _mm_set1_pd(-1.0);
			__m128d vdepth = MM_LOAD1_PD(&env->vol[1]);	
			__m128d vtmp, vout, vdata;
			vdepth = _mm_mul_pd(vdepth, vcs1); // -depth
			for (i = 0; i < count; i += 2)
			{
				data[1] = data[0] = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
				compute_oscillator2(lfo, 1);
				if(info->pm_mode)
					do_tremolo_pmod_st(info, data, lfo->out);
				vout = _mm_loadu_pd(lfo->out);
				vtmp = MM_FMA_PD(vout, vdepth, vc1); // out * (-depth) + 1.0 
				vdata =	_mm_load_pd(data);
				vdata =	_mm_mul_pd(vdata, vtmp);
				_mm_storeu_pd(&buf[i], vdata);
			}
		}
		break;
	case CH_MONO_STEREO:
		{
			const __m128d vc1 = _mm_set1_pd(1.0), vcs1 = _mm_set1_pd(-1.0);
			__m128d vdepth = MM_LOAD1_PD(&env->vol[1]);	
			__m128d vtmp, vout, vdata;
			vdepth = _mm_mul_pd(vdepth, vcs1); // -depth
			for (i = 0; i < count; i += 2)
			{
				data[1] = data[0] = buf[i];
				compute_oscillator2(lfo, 1);
				if(info->pm_mode)
					do_tremolo_pmod_st(info, data, lfo->out);
				vout = _mm_loadu_pd(lfo->out);
				vtmp = MM_FMA_PD(vout, vdepth, vc1); // out * (-depth) + 1.0 
				vdata =	_mm_load_pd(data);
				vdata =	_mm_mul_pd(vdata, vtmp);
				_mm_storeu_pd(&buf[i], vdata);
			}
		}
		break;
#else // ! USE_X86_EXT_INTRIN
	case CH_STEREO:
		for (i = 0; i < count; i++)
		{
			data[0] = buf[i]; data[1] = buf[i + 1];
			compute_oscillator2(lfo, 1);
			if(info->pm_mode)
				do_tremolo_pmod_st(info, data, lfo->out);
			tmp = 1.0 - lfo->out[0] * env->vol[1];
			buf[i] = data[0] * tmp;
			i++;
			tmp = 1.0 - lfo->out[1] * env->vol[1];
			buf[i] = data[1] * tmp;
		}
		break;
	case CH_MIX_STEREO:
		for (i = 0; i < count; i++)
		{
			data[1] = data[0] = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			compute_oscillator2(lfo, 1);
			if(info->pm_mode)
				do_tremolo_pmod_st(info, data, lfo->out);
			tmp = 1.0 - lfo->out[0] * env->vol[1];
			buf[i] = data[0] * tmp;
			i++;
			tmp = 1.0 - lfo->out[1] * env->vol[1];
			buf[i] = data[1] * tmp;
		}
		break;
	case CH_MONO_STEREO:
		for (i = 0; i < count; i++)
		{
			data[1] = data[0] = buf[i];
			compute_oscillator2(lfo, 1);
			if(info->pm_mode)
				do_tremolo_pmod_st(info, data, lfo->out);
			tmp = 1.0 - lfo->out[0] * env->vol[1];
			buf[i] = data[0] * tmp;
			i++;
			tmp = 1.0 - lfo->out[1] * env->vol[1];
			buf[i] = data[1] * tmp;
		}
		break;
#endif // USE_X86_EXT_INTRIN
	case CH_MONO:
		for (i = 0; i < count; i++)
		{
			data[1] = data[0] = buf[i];
			compute_oscillator2(lfo, 1);
			if(info->pm_mode)
				do_tremolo_pmod_mono(info, data, lfo->out);
			tmp = 1.0 - lfo->out[0] * env->vol[1];
			tmp = data[0] * tmp;
			buf[i] = tmp;
			i++;
			buf[i] = tmp;
		}
		break;
	case CH_LEFT:
		for (i = 0; i < count; i++)
		{
			data[1] = data[0] = buf[i];
			compute_oscillator2(lfo, 1);
			if(info->pm_mode)
				do_tremolo_pmod_mono(info, data, lfo->out);
			tmp = 1.0 - lfo->out[0] * env->vol[1];
			buf[i] = data[0] * tmp;
			i++;
		}
		break;
	case CH_RIGHT:
		for (i = 0; i < count; i++)
		{
			i++;
			data[1] = data[0] = buf[i];
			compute_oscillator2(lfo, 1);
			if(info->pm_mode)
				do_tremolo_pmod_mono(info, data, lfo->out);
			tmp = 1.0 - lfo->out[0] * env->vol[1];
			buf[i] = data[0] * tmp;
		}
		break;
	}
}


/*
attak       // attack time  (ms) 10
sustain     // release time (ms) 300
threshold   // threshold (~1.0) 80
slope       // slope angle (~1.0) 0.5
lookahead   // lookahead  (ms) 5
window,     // window time (ms) 1
*/
static void do_compressor_multi(DATA_T *buf, int32 count, InfoCompressor *cmp)
{
	double rms, theta=0, gain=0, summ;
	DATA_T tmp;
	int  i, j;

	if(count == MAGIC_INIT_EFFECT_INFO) {
//cmp->mode = CH_STEREO;
//cmp->attak = 10; // ms
//cmp->sustain = 300; // ms
//cmp->pre_gain = 6; // dB
//cmp->post_gain = 0; // dB
//cmp->threshold = 1.0; // threshold(~1.0)
//cmp->pan = 0x00;
//cmp->level = 1.0;
//cmp->slope = 0.5; // ratio
//cmp->div_level_0db = div_ins_level;
		cmp->lookahead = 5; // lookahead (ms)
		cmp->window = 1;// window (ms)

		cmp->att = (cmp->attak == 0.0) ? (0.0) : exp (-1.0 / (playmode_rate_ms * cmp->attak)); // attack "per sample decay"
		cmp->rel = (cmp->sustain == 0.0) ? (0.0) : exp (-1.0 / (playmode_rate_ms * cmp->sustain)); // release "per sample decay"
		cmp->lhsmp = (int)(playmode_rate_ms * cmp->lookahead); // sample offset to lookahead wnd start		
		cmp->nrms = (int)(playmode_rate_ms * cmp->window); // samples count in lookahead window
		if(cmp->nrms & 0x1)
			cmp->nrms++;
		cmp->div_nrms = 1.0 / (double)cmp->nrms;
		cmp->prgain = pow(10.0, cmp->pre_gain * DIV_40) * otd.efx_CustomCmpLvIn;
		cmp->pogain = cmp->prgain * pow(10.0, cmp->post_gain * DIV_40) * otd.efx_CustomCmpLvOut;
		cmp->env = 0;
		cmp->delay1 = cmp->nrms; // < 1ms
		cmp->count1 = 0;
		cmp->delay2 = cmp->lhsmp * 2; // < 5ms stereo
		cmp->count2 = 0;
		if(cmp->div_level_0db <= 0.0)			
			cmp->div_level_0db = div_ins_level;
		memset(cmp->ptr1, 0, sizeof(FLOAT_T) * 400);
		memset(cmp->ptr2, 0, sizeof(DATA_T) * 4000);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		return;
	}	 
	switch(cmp->mode){
	case CH_STEREO: // stereo link
#if (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE) && defined(FLOAT_T_DOUBLE)
		{
			__m128d vec_div2_nrms =_mm_set1_pd(cmp->div_nrms * DIV_2);
			__m128d vec_in_level = _mm_set1_pd(cmp->prgain * cmp->div_level_0db); // cnv ins level
			for (i = 0; i < count; i += 2)
			{
				__m128d vec_tmp, vec_buf = _mm_loadu_pd(&buf[i]), vec_data = _mm_loadu_pd(&cmp->ptr2[cmp->count2]);
				_mm_storeu_pd(&cmp->ptr2[cmp->count2], vec_buf);
				vec_tmp = _mm_mul_pd(vec_buf, vec_in_level);
				vec_tmp = _mm_mul_pd(vec_tmp, vec_tmp);
				vec_tmp = _mm_add_pd(vec_tmp, _mm_shuffle_pd(vec_tmp, vec_tmp, 0x1));
				_mm_store_sd(&(cmp->ptr1[cmp->count1]), vec_tmp);
				if (++cmp->count1 >= cmp->delay1) {cmp->count1 -= cmp->delay1;}
				if ((cmp->count2 += 2) >= cmp->delay2) {cmp->count2 -= cmp->delay2;}
				vec_tmp = _mm_setzero_pd();
				for (j = 0; j < cmp->nrms; j += 2)
					vec_tmp = _mm_add_pd(vec_tmp, _mm_loadu_pd(&cmp->ptr1[j]));				
				vec_tmp = _mm_add_pd(vec_tmp, _mm_shuffle_pd(vec_tmp, vec_tmp, 0x1));
				vec_tmp = _mm_mul_sd(vec_tmp, vec_div2_nrms);
				vec_tmp = _mm_sqrt_sd(vec_tmp, vec_tmp);   // root-mean-square
				_mm_store_sd(&rms, vec_tmp);
				theta = rms > cmp->env ? cmp->att : cmp->rel;
				cmp->env = (1.0 - theta) * rms + theta * cmp->env;
				gain = (cmp->env > cmp->threshold) ? (cmp->threshold / cmp->env) : 1.0;
				if(gain < cmp->slope)
					gain = cmp->slope;
				_mm_storeu_pd(&buf[i], _mm_mul_pd(vec_data, _mm_set1_pd(gain * cmp->pogain)));
			}
		}
#else // ! USE_X86_EXT_INTRIN
		for (i = 0; i < count; ++i)
		{
			FLOAT_T dataL = cmp->ptr2[cmp->count2], dataR = cmp->ptr2[cmp->count2 + 1];
			FLOAT_T inL = buf[i] * cmp->prgain * cmp->div_level_0db; // cnv ins level
			FLOAT_T inR = buf[i + 1] * cmp->prgain * cmp->div_level_0db; // cnv ins level
			cmp->ptr2[cmp->count2] = buf[i];
			cmp->ptr2[++cmp->count2] = buf[i + 1];
			cmp->ptr1[cmp->count1] = inL * inL + inR * inR;
			if (++cmp->count1 >= cmp->delay1) {cmp->count1 -= cmp->delay1;}
			if (++cmp->count2 >= cmp->delay2) {cmp->count2 -= cmp->delay2;}
			// now compute RMS
			summ = 0;
			// for each sample in window
			for (j = 0; j < cmp->nrms; ++j)
				summ += cmp->ptr1[j]; // level float
			rms = sqrt(summ * cmp->div_nrms * DIV_2);   // root-mean-square
			// dynamic selection: attack or release?
			theta = rms > cmp->env ? cmp->att : cmp->rel;
			// smoothing with capacitor, envelope extraction...
			// here be aware of pIV denormal numbers glitch
			cmp->env = (1.0 - theta) * rms + theta * cmp->env;
			// the very easy hard knee 1:N compressor
		//	gain = (cmp->env > cmp->threshold) ? (1.0 - (cmp->env - cmp->threshold))) : 1.0;
			gain = (cmp->env > cmp->threshold) ? (cmp->threshold / cmp->env) : 1.0;
			if(gain < cmp->slope)
				gain = cmp->slope;
			gain *= cmp->pogain;
			// result - two hard kneed compressed channels...
			buf[i] = dataL * gain;
			i++;
			buf[i] = dataR * gain;
		}
#endif // USE_X86_EXT_INTRIN
		break;
	case CH_MIX_STEREO:
	case CH_MIX_MONO:
		for (i = 0; i < count; ++i)
		{
			FLOAT_T dataM = (cmp->ptr2[cmp->count2] + cmp->ptr2[cmp->count2 + 1]) * DIV_MIX_LEVEL;
			FLOAT_T inM = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL * cmp->prgain * cmp->div_level_0db; // level int to float // cnv ins level
			cmp->ptr2[cmp->count2] = buf[i];
			cmp->ptr2[++cmp->count2] = buf[i + 1];
			cmp->ptr1[cmp->count1] = inM * inM;
			if (++cmp->count1 >= cmp->delay1) {cmp->count1 -= cmp->delay1;}
			if (++cmp->count2 >= cmp->delay2) {cmp->count2 -= cmp->delay2;}
			// now compute RMS
			summ = 0;
			// for each sample in window
			for (j = 0; j < cmp->nrms; ++j)
				summ += cmp->ptr1[j]; // level float
			rms = sqrt(summ * cmp->div_nrms);   // root-mean-square
			// dynamic selection: attack or release?
			theta = rms > cmp->env ? cmp->att : cmp->rel;
			// smoothing with capacitor, envelope extraction...
			// here be aware of pIV denormal numbers glitch
			cmp->env = (1.0 - theta) * rms + theta * cmp->env;
			// the very easy hard knee 1:N compressor
		//	gain = (cmp->env > cmp->threshold) ? (1.0 - (cmp->env - cmp->threshold))) : 1.0;
			gain = (cmp->env > cmp->threshold) ? (cmp->threshold / cmp->env) : 1.0;
			if(gain < cmp->slope)
				gain = cmp->slope;
			gain *= cmp->pogain;
			// result - two hard kneed compressed channels...
			tmp = dataM * gain;
			buf[i] = tmp;
			i++;
			buf[i] = tmp;
		}
		break;
	case CH_MONO:
		for (i = 0; i < count; ++i)
		{
			FLOAT_T dataM = cmp->ptr2[cmp->count2];
			FLOAT_T inM = buf[i] * cmp->prgain * cmp->div_level_0db; // level int to float // cnv ins level
			cmp->ptr2[cmp->count2++] = buf[i];
			cmp->ptr1[cmp->count1] = inM * inM;
			if (++cmp->count1 >= cmp->delay1) {cmp->count1 -= cmp->delay1;}
			if (++cmp->count2 >= cmp->delay2) {cmp->count2 -= cmp->delay2;}
			// now compute RMS
			summ = 0;
			// for each sample in window
			for (j = 0; j < cmp->nrms; ++j)
				summ += cmp->ptr1[j]; // level float
			rms = sqrt(summ * cmp->div_nrms);   // root-mean-square
			// dynamic selection: attack or release?
			theta = rms > cmp->env ? cmp->att : cmp->rel;
			// smoothing with capacitor, envelope extraction...
			// here be aware of pIV denormal numbers glitch
			cmp->env = (1.0 - theta) * rms + theta * cmp->env;
			// the very easy hard knee 1:N compressor
		//	gain = (cmp->env > cmp->threshold) ? (1.0 - (cmp->env - cmp->threshold))) : 1.0;
			gain = (cmp->env > cmp->threshold) ? (cmp->threshold / cmp->env) : 1.0;
			if(gain < cmp->slope)
				gain = cmp->slope;
			gain *= cmp->pogain;
			// result - two hard kneed compressed channels...
			tmp = dataM * gain;
			buf[i] = tmp;
			i++;
			buf[i] = tmp;
		}
		break;
	case CH_LEFT:
		break;
	case CH_RIGHT:
		break;
	}
}


#define INS_LIMITER_MAX_FIX (0.80)
/*
threshold 0.0 ~ 1.0;
	圧縮開始レベル 内部ではlimiter_max*thresholdをしきい値とする
ratio 0.0~ 1.0;
	圧縮率の上限(小さいほど高い) 0以下は無限とする
ahead : ms
	圧縮開始してから指定圧縮率に到達するまでの時間 10ms程度
release : ms
	指定圧縮率に到達してから 入力レベルが圧縮開始レベル未満に下がったとき
	圧縮率を下げ終わるまでの時間
	下げてる途中で入力レベルが圧縮開始レベルを超えた場合はまた圧縮開始する	
pre_gain : dB
	入力ゲイン
post_gain : dB
	出力ゲイン
*/
static void do_limiter_multi(DATA_T *buf, int32 count, InfoLimiter *info)
{
	int i;
	FLOAT_T gain = 0, tmp, input, theta;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		int32 ahead_cnt = info->ahead * playmode_rate_ms;
		info->pre = pow(10.0, info->pre_gain * DIV_40) * otd.efx_CustomLmtLvIn;
		info->post = pow(10.0, info->post_gain * DIV_40) * otd.efx_CustomLmtLvOut;
		info->max = info->threshold * ins_level * INS_LIMITER_MAX_FIX;
		info->max2 = info->max * info->max;
		info->amp = 1.0;
		info->leveld = info->pre * info->post;
		info->dir = 0;
		info->buffer_size = ahead_cnt * 2;
		info->write_cnt = 2;
		info->read_cnt = 0;
		info->wnd_cnt = 0;
		info->wnd_size = playmode_rate_ms;
		info->env = info->max;
		info->att = exp (-1.0 / (playmode_rate_ms * info->ahead)); // attack "per sample decay"
		info->rel = exp (-1.0 / (playmode_rate_ms * info->release)); // release "per sample decay"  
		info->hold_len = 6 * playmode_rate_ms; // 6ms
		info->hold_cnt = 0;
		info->peak_tmp = info->max2;
		info->peak_hold = info->max;
		if(info->init && info->ptr != NULL) {
			free(info->ptr);
			info->ptr = NULL;
		}
		info->ptr = (DATA_T *)safe_malloc(sizeof(DATA_T) * (info->buffer_size + 2));
		if(info->ptr){
			memset(info->ptr, 0, sizeof(DATA_T) * (info->buffer_size + 2));			
			info->init = 1;
		}else
			info->init = 0;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		if(info->ptr != NULL) {
			free(info->ptr);
			info->ptr = NULL;
		}
		info->init = 0;
		return;
	} else if(count == 0)
		return;
	switch(info->mode){
	case CH_STEREO:
		for (i = 0; i < count; i++) {
			// compute envelope
			theta = info->peak_hold > info->env ? info->att : info->rel;
			info->env = (1.0 - theta) * info->peak_hold + theta * info->env;
			gain = info->max / info->env;
			if((info->ratio > 0) && (gain < info->ratio))
				gain = info->ratio;
			gain *= info->leveld;
			/* left channel */
			// buffer copy , search peak level
			info->ptr[info->write_cnt++] = input = info->pre * buf[i];
			if((tmp = input * input) > info->peak_tmp) {info->peak_tmp = tmp;}
			// output
			buf[i++] = gain * info->ptr[info->read_cnt++];
			/* right channel */
			// buffer copy , search peak level
			info->ptr[info->write_cnt++] = input = info->pre * buf[i];
			if((tmp = input * input) > info->peak_tmp) {info->peak_tmp = tmp;}
			// output
			buf[i] = gain * info->ptr[info->read_cnt++];
			/* common */
			// count reset
			if(info->write_cnt >= info->buffer_size) {info->write_cnt = 0;}
			if(info->read_cnt >= info->buffer_size) {info->read_cnt = 0;}
			// calc gain , reset envelope
			if(++info->wnd_cnt >= info->wnd_size){
				if(info->peak_tmp > info->peak_hold){
					info->peak_hold = sqrt(info->peak_tmp);
					info->hold_cnt = 0;
					info->dir = 0;
				}else if(info->peak_tmp < info->peak_hold){
					switch(info->dir){
					case 0:
						info->dir = 1;
					case 1:
						if((info->hold_cnt += info->wnd_cnt) <= info->hold_len)
							break;
						info->dir = 2;
					case 2:
						info->peak_hold = sqrt(info->peak_tmp);
						break;
					}
				}
				info->wnd_cnt = 0;			
				info->peak_tmp = info->max2;
			}
		}
		break;
	case CH_MIX_STEREO:
	case CH_MIX_MONO:
		for (i = 0; i < count; i++) {
			// compute envelope
			theta = info->peak_hold > info->env ? info->att : info->rel;
			info->env = (1.0 - theta) * info->peak_hold + theta * info->env;
			gain = info->max / info->env;
			if((info->ratio > 0) && (gain < info->ratio))
				gain = info->ratio;
			gain *= info->leveld;
			/* mix lr channel */
			// buffer copy , search peak level
			info->ptr[info->write_cnt++] = input = info->pre * (buf[i] + buf[i + 1]) * DIV_2;
			if((tmp = input * input) > info->peak_tmp) {info->peak_tmp = tmp;}
			// output
			tmp = gain * info->ptr[info->read_cnt++];
			buf[i] = tmp;
			i++;
			buf[i] = tmp;
			info->write_cnt++;
			info->read_cnt++;
			/* common */
			// count reset
			if(info->write_cnt >= info->buffer_size) {info->write_cnt = 0;}
			if(info->read_cnt >= info->buffer_size) {info->read_cnt = 0;}
			// calc gain , reset envelope
			if(++info->wnd_cnt >= info->wnd_size){
				if(info->peak_tmp > info->peak_hold){
					info->peak_hold = sqrt(info->peak_tmp);
					info->hold_cnt = 0;
					info->dir = 0;
				}else if(info->peak_tmp < info->peak_hold){
					switch(info->dir){
					case 0:
						info->dir = 1;
					case 1:
						if((info->hold_cnt += info->wnd_cnt) <= info->hold_len)
							break;
						info->dir = 2;
					case 2:
						info->peak_hold = sqrt(info->peak_tmp);
						break;
					}
				}
				info->wnd_cnt = 0;			
				info->peak_tmp = info->max2;
			}
		}
		break;
	case CH_LEFT:
		for (i = 0; i < count; i++) {
			// compute envelope
			theta = info->peak_hold > info->env ? info->att : info->rel;
			info->env = (1.0 - theta) * info->peak_hold + theta * info->env;
			gain = info->max / info->env;
			if((info->ratio > 0) && (gain < info->ratio))
				gain = info->ratio;
			gain *= info->leveld;
			/* left channel */
			// buffer copy , search peak level
			info->ptr[info->write_cnt++] = input = info->pre * buf[i];
			if((tmp = input * input) > info->peak_tmp) {info->peak_tmp = tmp;}
			// output
			buf[i] = gain * info->ptr[info->read_cnt++];
			i++;
			info->write_cnt++;
			info->read_cnt++;
			/* common */
			// count reset
			if(info->write_cnt >= info->buffer_size) {info->write_cnt = 0;}
			if(info->read_cnt >= info->buffer_size) {info->read_cnt = 0;}
			// calc gain , reset envelope
			if(++info->wnd_cnt >= info->wnd_size){
				if(info->peak_tmp > info->peak_hold){
					info->peak_hold = sqrt(info->peak_tmp);
					info->hold_cnt = 0;
					info->dir = 0;
				}else if(info->peak_tmp < info->peak_hold){
					switch(info->dir){
					case 0:
						info->dir = 1;
					case 1:
						if((info->hold_cnt += info->wnd_cnt) <= info->hold_len)
							break;
						info->dir = 2;
					case 2:
						info->peak_hold = sqrt(info->peak_tmp);
						break;
					}
				}
				info->wnd_cnt = 0;			
				info->peak_tmp = info->max2;
			}
		}
		break;
	case CH_RIGHT:
		for (i = 0; i < count; i++) {
			// compute envelope
			theta = info->peak_hold > info->env ? info->att : info->rel;
			info->env = (1.0 - theta) * info->peak_hold + theta * info->env;
			gain = info->max / info->env;
			if((info->ratio > 0) && (gain < info->ratio))
				gain = info->ratio;
			gain *= info->leveld;
			/* left channel */
			info->write_cnt++;
			info->read_cnt++;
			i++;
			/* right channel */
			// buffer copy , search peak level
			info->ptr[info->write_cnt++] = input = info->pre * buf[i];
			if((tmp = input * input) > info->peak_tmp) {info->peak_tmp = tmp;}
			// output
			buf[i] = gain * info->ptr[info->read_cnt++];
			/* common */
			// count reset
			if(info->write_cnt >= info->buffer_size) {info->write_cnt = 0;}
			if(info->read_cnt >= info->buffer_size) {info->read_cnt = 0;}
			// calc gain , reset envelope
			// calc gain , reset envelope
			if(++info->wnd_cnt >= info->wnd_size){
				if(info->peak_tmp > info->peak_hold){
					info->peak_hold = sqrt(info->peak_tmp);
					info->hold_cnt = 0;
					info->dir = 0;
				}else if(info->peak_tmp < info->peak_hold){
					switch(info->dir){
					case 0:
						info->dir = 1;
					case 1:
						if((info->hold_cnt += info->wnd_cnt) <= info->hold_len)
							break;
						info->dir = 2;
					case 2:
						info->peak_hold = sqrt(info->peak_tmp);
						break;
					}
				}
				info->wnd_cnt = 0;			
				info->peak_tmp = info->max2;
			}
		}
		break;
	}
}


// delay_lr_multi
#define DELAY_LR_MULTI_FEEDBACK (0.70)

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void do_delay_lr_multi(int32 *buf, int32 count, InfoDelayLR *info)
{
	int32 i;
	simple_delay *delayL = &(info->delayL), *delayR = &(info->delayR);
	FilterCoefficients *lpf = &(info->lpf);
	int32 *bufL = delayL->buf, *bufR = delayR->buf, tmp, x, vx[2];
	int32 size = delayL->size, *offset = info->offset, *index = info->index;
	int32 feedbacki = info->feedbacki;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		if(!info->init){
			info->init = 1;
			// 3000ms : delay_time (SD max=3000.0ms) + safety
			size = 3010.0 * playmode_rate_ms;
			set_delay(&(info->delayL), size);
			set_delay(&(info->delayR), size);
			size = delayL->size;
		}
		info->offset[0] = info->ldelay * playmode_rate_ms;
		info->offset[1] = info->rdelay * playmode_rate_ms;
		info->offset[2] = info->fdelay1 * playmode_rate_ms;
		info->offset[3] = info->fdelay2 * playmode_rate_ms;
		++info->offset[0];
		++info->offset[1];
		++info->offset[2];
		++info->offset[3];
		info->psignL = info->phasel ? (-1) : (+1);
		info->psignR = info->phaser ? (-1) : (+1);
		if(info->fb_mode){
			info->fb_bufL = delayR->buf;
			info->fb_bufR = delayL->buf;
			info->fb_indexL = &delayR->index;
			info->fb_indexR = &delayL->index;
		}else{
			info->fb_bufL = delayL->buf;
			info->fb_bufR = delayR->buf;
			info->fb_indexL = &delayL->index;
			info->fb_indexR = &delayR->index;
		}
		info->feedbackd = info->feedback * DELAY_LR_MULTI_FEEDBACK;
		info->feedbacki = TIM_FSCALE(info->feedbackd, 24);
		init_sample_filter(lpf, info->high_damp, 0, FILTER_LPF6); // damp Hz
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		if(info->init){
			free_delay(&(info->delayL));
			free_delay(&(info->delayR));
		}
		return;
	}
	switch(info->mode){
	case CH_STEREO:
		for (i = 0; i < count; i++)
		{
			index[0] = delayL->index - offset[0];
			index[1] = delayL->index - offset[1];
			index[2] = delayL->index - offset[2];
			index[3] = delayL->index - offset[3];
			if(index[0] < 0) {index[0] += size;}
			if(index[1] < 0) {index[1] += size;}
			if(index[2] < 0) {index[2] += size;}
			if(index[3] < 0) {index[3] += size;}
			vx[0] = imuldiv24(bufL[*info->fb_indexL], feedbacki);
			vx[1] = imuldiv24(bufR[*info->fb_indexR], feedbacki);
			sample_filter_stereo2(lpf, vx);
			bufL[delayL->index] = buf[i] + vx[0];
			buf[i] = bufL[index[0]] * info->psignL;
			i++;
			bufR[delayL->index] = buf[i] + vx[1];
			buf[i] = bufR[index[1]] * info->psignR;			
			if ((++(delayL->index)) >= size) {delayL->index = 0;}	
		}
		break;
	case CH_MIX_STEREO:
		for (i = 0; i < count; i++)
		{
			index[0] = delayL->index - offset[0];
			index[1] = delayL->index - offset[1];
			index[2] = delayL->index - offset[2];
			index[3] = delayL->index - offset[3];
			if(index[0] < 0) {index[0] += size;}
			if(index[1] < 0) {index[1] += size;}
			if(index[2] < 0) {index[2] += size;}
			if(index[3] < 0) {index[3] += size;}
			tmp = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			vx[0] = imuldiv24(bufL[*info->fb_indexL], feedbacki);
			vx[1] = imuldiv24(bufR[*info->fb_indexR], feedbacki);
			sample_filter_stereo2(lpf, vx);
			bufL[delayL->index] = tmp + vx[0];
			bufR[delayL->index] = tmp + vx[1];
			buf[i] = bufL[index[0]] * info->psignL;
			i++;
			buf[i] = bufR[index[1]] * info->psignR;	
			if ((++(delayL->index)) >= size) {delayL->index = 0;}
		}
		break;
	case CH_MONO_STEREO:
		for (i = 0; i < count; i++)
		{
			index[0] = delayL->index - offset[0];
			index[1] = delayL->index - offset[1];
			index[2] = delayL->index - offset[2];
			index[3] = delayL->index - offset[3];
			if(index[0] < 0) {index[0] += size;}
			if(index[1] < 0) {index[1] += size;}
			if(index[2] < 0) {index[2] += size;}
			if(index[3] < 0) {index[3] += size;}
			tmp = buf[i];
			vx[0] = imuldiv24(bufL[*info->fb_indexL], feedbacki);
			vx[1] = imuldiv24(bufR[*info->fb_indexR], feedbacki);
			sample_filter_stereo2(lpf, vx);
			bufL[delayL->index] = tmp + vx[0];
			bufR[delayL->index] = tmp + vx[1];
			buf[i] = bufL[index[0]] * info->psignL;
			i++;
			buf[i] = bufR[index[1]] * info->psignR;	
			if ((++(delayL->index)) >= size) {delayL->index = 0;}	
		}
		break;
	case CH_MIX_MONO:
		for (i = 0; i < count; i++)
		{
			index[0] = delayL->index - offset[0];
			index[2] = delayL->index - offset[2];
			if(index[0] < 0) {index[0] += size;}
			if(index[2] < 0) {index[2] += size;}
			tmp = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			x = imuldiv24(bufL[index[2]], feedbacki);
			sample_filter_left(lpf, &x);
			bufL[delayL->index] = tmp + x;
			tmp = bufL[index[0]] * info->psignL;
			buf[i] = tmp;
			i++;
			buf[i] = tmp;	
			if ((++(delayL->index)) >= size) {delayL->index = 0;}	
		}
		break;
	case CH_LEFT:
		for (i = 0; i < count; i++)
		{
			index[0] = delayL->index - offset[0];
			index[2] = delayL->index - offset[2];
			if(index[0] < 0) {index[0] += size;}
			if(index[2] < 0) {index[2] += size;}
			x = imuldiv24(bufL[index[2]], feedbacki);
			sample_filter_left(lpf, &x);
			bufL[delayL->index] = buf[i] + x;
			buf[i] = bufL[index[0]] * info->psignL;
			i++;
			if ((++(delayL->index)) >= size) {delayL->index = 0;}
		}
		break;
	case CH_RIGHT:
		for (i = 0; i < count; i++)
		{
			index[1] = delayL->index - offset[1];
			index[3] = delayL->index - offset[3];
			if(index[1] < 0) {index[1] += size;}
			if(index[3] < 0) {index[3] += size;}
			i++;
			x = imuldiv24(bufR[index[3]], feedbacki);
			sample_filter_right(lpf, &x);
			bufR[delayR->index] = buf[i] + x;
			buf[i] = bufR[index[1]] * info->psignR;
			if ((++(delayR->index)) >= size) {delayR->index = 0;}	
		}
		break;
	}	
}

#else /* floating-point implementation */
static void do_delay_lr_multi(DATA_T *buf, int32 count, InfoDelayLR *info)
{
	int32 i;
	simple_delay *delayL = &(info->delayL), *delayR = &(info->delayR);
	FilterCoefficients *lpf = &(info->lpf);
	DATA_T *bufL = delayL->buf, *bufR = delayR->buf, tmp, x, vx[2];
	int32 size = delayL->size, *offset = info->offset, *index = info->index;
	FLOAT_T feedback = info->feedbackd;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		if(!info->init){
			info->init = 1;
			// 3000ms : delay_time (SD max=3000.0ms) + safety
			size = 3010.0 * playmode_rate_ms;
			set_delay(&(info->delayL), size);
			set_delay(&(info->delayR), size);
			size = delayL->size;
		}
		info->offset[0] = info->ldelay * playmode_rate_ms + 1;
		info->offset[1] = info->rdelay * playmode_rate_ms + 1;
		info->offset[2] = info->fdelay1 * playmode_rate_ms + 1;
		info->offset[3] = info->fdelay2 * playmode_rate_ms + 1;
		info->psignL = info->phasel ? (-1.0) : (1.0);
		info->psignR = info->phaser ? (-1.0) : (1.0);
		if(info->fb_mode){
			info->fb_bufL = delayR->buf;
			info->fb_bufR = delayL->buf;
			info->fb_indexL = &info->index[3];
			info->fb_indexR = &info->index[2];
		}else{
			info->fb_bufL = delayL->buf;
			info->fb_bufR = delayR->buf;
			info->fb_indexL = &info->index[2];
			info->fb_indexR = &info->index[3];
		}
		info->feedbackd = info->feedback * DELAY_LR_MULTI_FEEDBACK;
		init_sample_filter(lpf, info->high_damp, 0, FILTER_LPF6); // damp Hz
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		if(info->init){
			free_delay(&(info->delayL));
			free_delay(&(info->delayR));
		}
		return;
	}
	switch(info->mode){
	case CH_STEREO:
		for (i = 0; i < count; i++)
		{
			index[0] = delayL->index - offset[0];
			index[1] = delayL->index - offset[1];
			index[2] = delayL->index - offset[2];
			index[3] = delayL->index - offset[3];
			if(index[0] < 0) {index[0] += size;}
			if(index[1] < 0) {index[1] += size;}
			if(index[2] < 0) {index[2] += size;}
			if(index[3] < 0) {index[3] += size;}
			vx[0] = info->fb_bufL[*info->fb_indexL] * feedback;
			vx[1] = info->fb_bufR[*info->fb_indexR] * feedback;
			sample_filter_stereo2(lpf, vx);
			bufL[delayL->index] = buf[i] + vx[0];
			buf[i] = bufL[index[0]] * info->psignL;
			i++;
			bufR[delayL->index] = buf[i] + vx[1];
			buf[i] = bufR[index[1]] * info->psignR;			
			if ((++(delayL->index)) >= size) {delayL->index = 0;}		
		}
		break;
	case CH_MIX_STEREO:
		for (i = 0; i < count; i++)
		{
			index[0] = delayL->index - offset[0];
			index[1] = delayL->index - offset[1];
			index[2] = delayL->index - offset[2];
			index[3] = delayL->index - offset[3];
			if(index[0] < 0) {index[0] += size;}
			if(index[1] < 0) {index[1] += size;}
			if(index[2] < 0) {index[2] += size;}
			if(index[3] < 0) {index[3] += size;}
			tmp = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			vx[0] = info->fb_bufL[*info->fb_indexL] * feedback;
			vx[1] = info->fb_bufR[*info->fb_indexR] * feedback;
			sample_filter_stereo2(lpf, vx);
			bufL[delayL->index] = tmp + vx[0];
			bufR[delayL->index] = tmp + vx[1];
			buf[i] = bufL[index[0]] * info->psignL;
			i++;
			buf[i] = bufR[index[1]] * info->psignR;	
			if ((++(delayL->index)) >= size) {delayL->index = 0;}		
		}
		break;
	case CH_MONO_STEREO:
		for (i = 0; i < count; i++)
		{
			index[0] = delayL->index - offset[0];
			index[1] = delayL->index - offset[1];
			index[2] = delayL->index - offset[2];
			index[3] = delayL->index - offset[3];
			if(index[0] < 0) {index[0] += size;}
			if(index[1] < 0) {index[1] += size;}
			if(index[2] < 0) {index[2] += size;}
			if(index[3] < 0) {index[3] += size;}
			tmp = buf[i];
			vx[0] = info->fb_bufL[*info->fb_indexL] * feedback;
			vx[1] = info->fb_bufR[*info->fb_indexR] * feedback;
			sample_filter_stereo2(lpf, vx);
			bufL[delayL->index] = tmp + vx[0];
			bufR[delayL->index] = tmp + vx[1];
			buf[i] = bufL[index[0]] * info->psignL;
			i++;
			buf[i] = bufR[index[1]] * info->psignR;	
			if ((++(delayL->index)) >= size) {delayL->index = 0;}		
		}
		break;
	case CH_MIX_MONO:
		for (i = 0; i < count; i++)
		{
			index[0] = delayL->index - offset[0];
			index[2] = delayL->index - offset[2];
			if(index[0] < 0) {index[0] += size;}
			if(index[2] < 0) {index[2] += size;}
			tmp = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			x = bufL[index[2]] * feedback;
			sample_filter_left(lpf, &x);
			bufL[delayL->index] = tmp + x;
			tmp = bufL[index[0]] * info->psignL;
			buf[i] = tmp;
			i++;
			buf[i] = tmp;	
			if ((++(delayL->index)) >= size) {delayL->index = 0;}	
		}
		break;
	case CH_LEFT:
		for (i = 0; i < count; i++)
		{
			index[0] = delayL->index - offset[0];
			index[2] = delayL->index - offset[2];
			if(index[0] < 0) {index[0] += size;}
			if(index[2] < 0) {index[2] += size;}
			x = bufL[index[2]] * feedback;
			sample_filter_left(lpf, &x);
			bufL[delayL->index] = buf[i] + x;
			buf[i] = bufL[index[0]] * info->psignL;
			i++;
			if ((++(delayL->index)) >= size) {delayL->index = 0;}	
		}
		break;
	case CH_RIGHT:
		for (i = 0; i < count; i++)
		{
			index[1] = delayL->index - offset[1];
			index[3] = delayL->index - offset[3];
			if(index[1] < 0) {index[1] += size;}
			if(index[3] < 0) {index[3] += size;}
			i++;
			x = bufR[index[3]] * feedback;
			sample_filter_right(lpf, &x);
			bufR[delayR->index] = buf[i] + x;
			buf[i] = bufR[index[1]] * info->psignR;
			if ((++(delayR->index)) >= size) {delayR->index = 0;}		
		}
		break;
	}	
}
#endif /* OPT_MODE != 0 */


// mod_delay_ex
#define MODDELAY_FEEDBACK (0.70)
#define MODDELAY_WET (1.00)
static void do_mod_delay_multi(DATA_T *buf, int32 count, InfoModDelay *info)
{
	int32 i;
	int32 size = info->delay_size, delay_countL = info->delay_countL, delay_countR = info->delay_countR;
	DATA_T *ebufL = info->delayL.buf, *ebufR = info->delayR.buf;
	FLOAT_T delaycL = info->delaycdL, delaycR = info->delaycdR, depthc = info->depthcd,
		lfo_count = info->lfo_count, lfo_rate = info->lfo_rate;
	FLOAT_T feedbackd = info->feedbackd, wetd = info->wetd;
	DATA_T inputL, inputR;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		FLOAT_T ch_diff;
		int32 depth2;
		if(!info->init){
			info->init = 1;
			// 1000ms : delay_time(max=500ms) + depth max 40ms + safety
			set_delay(&info->delayL, (int32)(1000 * playmode_rate_ms + 1));
			set_delay(&info->delayR, (int32)(1000 * playmode_rate_ms + 1));
			if(info->delayL.size < info->delayR.size) // same
				info->delay_size = info->delayL.size - 1;
			else
				info->delay_size = info->delayR.size - 1;
			info->delay_countL = info->delay_countL = 0;
			info->hist[0] = info->hist[1] = 0;
		}
		info->feedbackd = info->feedback * MODDELAY_FEEDBACK * ext_chorus_feedback;
		info->wetd = MODDELAY_WET * ext_chorus_level;		
		if(info->depth_type) // depth [ms] p-p
			info->depthcd = info->depth_ms * playmode_rate_ms; // depth_ms = pp_max , -depth
		else // depth [cent]
			info->depthcd = calc_chorus_depth_cent(info->depth_cent, info->rate);
		info->delaycdL = info->ldelay_ms * playmode_rate_ms; // left
		if(info->delaycdL < 1) {info->delaycdL = 1;}	
		info->delaycdR = info->rdelay_ms * playmode_rate_ms; // right
		if(info->delaycdR < 1) {info->delaycdR = 1;}	
		info->lfo_rate = info->rate * div_playmode_rate;
		ch_diff = info->phase_diff * DIV_360; // deg 0 ~ 360
		if(info->offset <= 0)
			info->offset = 1.0 * DIV_360;
		info->lfo_phaseL = 0.0;
		info->lfo_phaseR = info->phase_diff * DIV_360; // deg 0 ~ 360	
		init_sample_filter(&info->fc, info->high_damp, 0, FILTER_LPF6);
		if(info->fb_mode){
			info->fb_ptrL = &info->hist[1];
			info->fb_ptrR = &info->hist[0];
		}else{
			info->fb_ptrL = &info->hist[0];
			info->fb_ptrR = &info->hist[1];
		}
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		info->init = 0;
		free_delay(&(info->delayL));
		free_delay(&(info->delayR));
		return;
	}
	// CH_STEREO:		
	for (i = 0; i < count; i++) {
		int32 index;
		FLOAT_T fp1, fp2;
		DATA_T v1, v2;
		// count
		if(!delay_countL) {ebufL[size] = ebufL[0];} // for linear interpolation
		if(++delay_countL >= size) {delay_countL -= size;}		
		if(!delay_countR){ ebufR[size] = ebufR[0];} // for linear interpolation
		if(++delay_countR >= size){	delay_countR -= size;}
		if((lfo_count += lfo_rate) >= 1.0) {lfo_count -= 1.0;}
		// left
		ebufL[delay_countL] = buf[i] + *info->fb_ptrL * feedbackd;
		fp1 = (FLOAT_T)delay_countL - delaycL - depthc * lookup2_sine_p((lfo_count + info->lfo_phaseL));
		if(fp1 < 0) {fp1 += size;}	
		fp2 = floor(fp1);
		index = fp2;
		v1 = ebufL[index]; v2 = ebufL[index + 1];
		info->hist[0] = v1 + (v2 - v1) * (fp1 - fp2);
		// right
		ebufR[delay_countR] = buf[i + 1] + *info->fb_ptrR * feedbackd;
		fp1 = (FLOAT_T)delay_countR - delaycR - depthc * lookup2_sine_p((lfo_count + info->lfo_phaseR));
		if(fp1 < 0) {fp1 += size;}	
		fp2 = floor(fp1);
		index = fp2;
		v1 = ebufR[index]; v2 = ebufR[index + 1];
		info->hist[1] = v1 + (v2 - v1) * (fp1 - fp2);
		// out
		buf[i] = info->hist[0] * wetd;
		buf[++i] = info->hist[1] * wetd;		
		sample_filter_stereo2(&info->fc, info->hist);
	}
	info->delay_countL = delay_countL, info->delay_countR = delay_countR, info->lfo_count = lfo_count;
}
				



#define MULTI_TAP_DELAY_FEEDBACK (0.70)
/*
ディレイ入力はmix後1chで全tap共通なのでバッファは1個
バッファサイズは一番長いディレイタイムに合わせる XG
各タップの読み出しカウント = バッファ書き込みカウント - 各タップのディレイタイム(サイズ)

[0]~[tap-1] tap_delay
[tap] feedbak_delay (for XG, GSでは[tap]=[0]ms
*/

static void do_multi_tap_delay(DATA_T *buf, int32 count, InfoMultiTapDelay *info)
{
	int32 i, k;
	simple_delay *delay = &info->delay;
	DATA_T *dbuf = delay->buf;
	int32 buf_index = delay->index, buf_size = delay->size;
	int32 index[MT_DELAY_TAP_MAX];
	FLOAT_T	feedback = info->feedback;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		if(!info->init){
			info->init = 1;
			// 3000ms : delay_time (SD max=3000.0ms) + safety
			set_delay(&info->delay, (int32)(3010 * playmode_rate_ms + 1));
		}
		if(info->tap > MT_DELAY_TAP_MAX - 1)
			info->tap = MT_DELAY_TAP_MAX - 1;
		for (i = 0; i <= info->tap; i++){
			info->size[i] = info->dtime[i] * playmode_rate_ms;
			info->outL[i] = do_left_panning(info->dlevel[i], info->pan[i]);
			info->outR[i] = do_right_panning(info->dlevel[i], info->pan[i]);
		}		
		init_sample_filter(&info->fc, info->high_damp, 0, FILTER_LPF6);
		info->feedbackd = info->feedback * MULTI_TAP_DELAY_FEEDBACK;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		info->init = 0;
		free_delay(&(info->delay));
		return;
	}
	// CH_MIX_STEREO
	for (k = 0; k < count; k++)
	{
		DATA_T mixL = 0, mixR = 0, input, fb, tmp;

		input = (buf[k] + buf[k + 1]) * DIV_MIX_LEVEL;		
		for (i = 0; i <= info->tap; i++){
			if((index[i] = buf_size - info->size[i]) < 0)
				index[i] += buf_size;
			tmp = dbuf[index[i]];
			if(i == info->tap){
				fb = tmp;
			}else{
				mixL += tmp * info->outL[i];
				mixR += tmp * info->outR[i];
			}
		}
		sample_filter(&info->fc, &fb);
		dbuf[buf_index] = input + fb * feedback;
		buf[k] = mixL;
		buf[++k] = mixR;
		// delay count / reset
		if (++buf_index >= buf_size) {buf_index = 0;}
	}
	delay->index = buf_index;
}

static void do_3d_multi_tap_delay(DATA_T *buf, int32 count, Info3DMultiTapDelay *info)
{
	int32 i, k;
	simple_delay *delay = &info->delay;
	DATA_T *dbuf = delay->buf;
	int32 buf_index = delay->index, buf_size = delay->size;
	int32 index[MT_DELAY_TAP_MAX];
	FLOAT_T	feedback = info->feedback;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		if(!info->init){
			info->init = 1;
			// 3000ms : delay_time (SD max=3000.0ms) + safety
			set_delay(&info->delay, (int32)(3010 * playmode_rate_ms + 1));
		}
		if(info->tap > MT_DELAY_TAP_MAX - 1)
			info->tap = MT_DELAY_TAP_MAX - 1;
		for (i = 0; i <= info->tap; i++){
			info->size[i] = info->dtime[i] * playmode_rate_ms;
			info->azimuth[i] = (FLOAT_T)(info->pan[i] - 0x40) * DIV_128;
		}		
		init_sample_filter(&info->fc, info->high_damp, 0, FILTER_LPF6);
		info->feedbackd = info->feedback * MULTI_TAP_DELAY_FEEDBACK;
		for (i = 0; i < MT_DELAY_TAP_MAX; i++){
			info->locate[i].out = info->out;
			init_3d_locate(&info->locate[i]);
		}
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		info->init = 0;
		free_delay(&(info->delay));
		for (i = 0; i < MT_DELAY_TAP_MAX; i++){
			uninit_3d_locate(&info->locate[i]);
		}
		return;
	}
	// CH_MIX_STEREO
	for (k = 0; k < count; k++)
	{
		DATA_T mixL = 0, mixR = 0, input, fb, inout[2];

		input = (buf[k] + buf[k + 1]) * DIV_MIX_LEVEL;		
		for (i = 0; i <= info->tap; i++){
			if((index[i] = buf_size - info->size[i]) < 0)
				index[i] += buf_size;
			inout[0] = dbuf[index[i]];
			if(i == info->tap){
				fb = inout[0];
			}else{				
				do_3d_locate(&info->locate[i], inout, info->azimuth[i]);
				mixL += inout[0];
				mixR += inout[1];
			}
		}
		sample_filter(&info->fc, &fb);
		dbuf[buf_index] = input + fb * feedback;
		buf[k] = mixL;
		buf[++k] = mixR;
		// delay count / reset
		if (++buf_index >= buf_size) {buf_index = 0;}
	}
	delay->index = buf_index;
}

 /* floating-point implementation */
// delay_shifter
#define DELAY_SHIFTER_FEEDBACK (0.70)
#define SHIFT_NONE 0
#define SHIFT_UP   1
#define SHIFT_DOWN 2
static void do_delay_shifter(DATA_T *buf, int32 count, InfoDelayShifter *info)
{
	int32 i;
	simple_delay *delayL = &(info->delayL), *delayR = &(info->delayR);
	DATA_T *bufL = delayL->buf, *bufR = delayR->buf, tmp;
	int32  sizel = delayL->size, sizer = delayR->size;
	int32 index0 = info->index[0], index1 = info->index[1];
	FLOAT_T index20 = info->index2[0], index21 = info->index2[1];
	FLOAT_T laccel = info->laccel, raccel = info->raccel;
	FLOAT_T feedback = info->feedbackd;
	DATA_T x;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		if(!info->init){
			info->init = 1;
			set_delay(&(info->delayL), play_mode->rate); // max 1000ms
			set_delay(&(info->delayR), play_mode->rate); // max 1000ms
			info->lshift = info->rshift = SHIFT_NONE; 
			info->ldelay_set = info->ldelay;
			info->rdelay_set = info->rdelay;
			info->index[0] = info->index2[0] = play_mode->rate - info->ldelay * playmode_rate_ms; // 1 ~ play_mode->rate
			info->index[1] = info->index2[1] = play_mode->rate - info->rdelay * playmode_rate_ms; // 1 ~ play_mode->rate
			info->laccel = info->raccel = 1.0;
		}
		if(info->ldelay != info->ldelay_set){
			if(info->ldelay > info->ldelay_set){
				info->lshift = SHIFT_DOWN;
				info->laccel = 1.0 / pow((double)2.0, (double)(info->accel + 1) * DIV_4); // -0.25oct ~ -4.0oct
			}else if(info->ldelay < info->ldelay_set){
				info->lshift = SHIFT_UP;
				info->laccel = pow((double)2.0, (double)(info->accel + 1) * DIV_4); // +0.25oct ~ +4.0oct
			}
			info->index[0] = delayL->index - info->ldelay * playmode_rate_ms;
			if(info->index[0] > delayL->size)
				info->index[0] -= delayL->size;
			info->ldelay_set = info->ldelay;
		}
		if(info->rdelay != info->rdelay_set){
			if(info->rdelay > info->rdelay_set){
				info->rshift = SHIFT_DOWN;
				info->raccel = 1.0 / ((double)(info->accel + 1) * DIV_4); 

			}else if(info->rdelay < info->rdelay_set){
				info->rshift = SHIFT_UP;
				info->raccel = (double)(info->accel + 1) * DIV_4; 
			}
			info->index[1] = delayR->index - info->rdelay * playmode_rate_ms;
			if(info->index[1] > delayR->size)
				info->index[1] -= delayR->size;
			info->ldelay_set = info->ldelay;
		}
		info->feedbackd = info->feedback * DELAY_SHIFTER_FEEDBACK;
		init_sample_filter(&info->fc, info->high_damp, 0, FILTER_LPF6);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		info->init = 0;
		free_delay(&(info->delayL));
		free_delay(&(info->delayR));
		return;
	}
	switch(info->mode){
	case CH_STEREO:
		for (i = 0; i < count; i++)
		{
			x = delayL->buf[(int)index20] * feedback;
			sample_filter_left(&info->fc, &x);
			bufL[delayL->index] = buf[i] + x * feedback;
			buf[i] = bufL[index0];
			i++;
			x = delayR->buf[(int)index21] * feedback;
			sample_filter_right(&info->fc, &x);
			bufR[delayR->index] = buf[i] + x * feedback;
			buf[i] = bufR[index1];
			if (++index0 >= sizel) {index0 = 0;}
			if (++index1 >= sizer) {index1 = 0;}
			if (++delayL->index >= sizel) {delayL->index = 0;}
			if (++delayR->index >= sizer) {delayR->index = 0;}
			if ((index20 += laccel)  >= sizel) {index20 -= sizel;}
			if ((index21 += raccel)  >= sizer) {index21 -= sizer;}
			if(info->lshift){
				FLOAT_T sub = (FLOAT_T)index0 - index20;
				if(fabs((FLOAT_T)sub) < laccel || fabs(sub + sizel) < laccel || fabs(sub - sizel) < laccel){
					info->lshift = SHIFT_NONE;
					laccel = 1.0;
				}
			}
			if(info->rshift){
				FLOAT_T sub = (FLOAT_T)index1 - index21;
				if(fabs((FLOAT_T)sub) < raccel || fabs(sub + sizer) < raccel || fabs(sub - sizer) < raccel){
					info->lshift = SHIFT_NONE;
					laccel = 1.0;
				}
			}
		}
		break;
	case CH_MIX_STEREO:
		for (i = 0; i < count; i++)
		{
			tmp = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			x = delayL->buf[(int)index20] * feedback;
			sample_filter_left(&info->fc, &x);
			bufL[delayL->index] = tmp + x * feedback;
			buf[i] = bufL[index0];
			i++;
			x = delayR->buf[(int)index21] * feedback;
			sample_filter_right(&info->fc, &x);
			bufR[delayR->index] = tmp + x * feedback;
			buf[i] = bufR[index1];
			if (++index0 >= sizel) {index0 = 0;}
			if (++index1 >= sizer) {index1 = 0;}
			if (++delayL->index >= sizel) {delayL->index = 0;}
			if (++delayR->index >= sizer) {delayR->index = 0;}
			if ((index20 += laccel)  >= sizel) {index20 -= sizel;}
			if ((index21 += raccel)  >= sizer) {index21 -= sizer;}
			if(info->lshift){
				FLOAT_T sub = (FLOAT_T)index0 - index20;
				if(fabs((FLOAT_T)sub) < laccel || fabs(sub + sizel) < laccel || fabs(sub - sizel) < laccel){
					info->lshift = SHIFT_NONE;
					laccel = 1.0;
				}
			}
			if(info->rshift){
				FLOAT_T sub = (FLOAT_T)index1 - index21;
				if(fabs((FLOAT_T)sub) < raccel || fabs(sub + sizer) < raccel || fabs(sub - sizer) < raccel){
					info->lshift = SHIFT_NONE;
					laccel = 1.0;
				}
			}
		}
		break;
	case CH_MONO_STEREO:
		for (i = 0; i < count; i++)
		{
			tmp = buf[i];
			x = delayL->buf[(int)index20] * feedback;
			sample_filter_left(&info->fc, &x);
			bufL[delayL->index] = tmp + x * feedback;
			buf[i] = bufL[index0];
			i++;
			x = delayR->buf[(int)index21] * feedback;
			sample_filter_right(&info->fc, &x);
			bufR[delayR->index] = tmp + x * feedback;
			buf[i] = bufR[index1];
			if (++index0 >= sizel) {index0 = 0;}
			if (++index1 >= sizer) {index1 = 0;}
			if (++delayL->index >= sizel) {delayL->index = 0;}
			if (++delayR->index >= sizer) {delayR->index = 0;}
			if ((index20 += laccel)  >= sizel) {index20 -= sizel;}
			if ((index21 += raccel)  >= sizer) {index21 -= sizer;}
			if(info->lshift){
				FLOAT_T sub = (FLOAT_T)index0 - index20;
				if(fabs((FLOAT_T)sub) < laccel || fabs(sub + sizel) < laccel || fabs(sub - sizel) < laccel){
					info->lshift = SHIFT_NONE;
					laccel = 1.0;
				}
			}
			if(info->rshift){
				FLOAT_T sub = (FLOAT_T)index1 - index21;
				if(fabs((FLOAT_T)sub) < raccel || fabs(sub + sizer) < raccel || fabs(sub - sizer) < raccel){
					info->lshift = SHIFT_NONE;
					laccel = 1.0;
				}
			}
		}
		break;
	case CH_MIX_MONO:
		for (i = 0; i < count; i++)
		{
			tmp = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			x = delayL->buf[(int)index20] * feedback;
			sample_filter_left(&info->fc, &x);
			bufL[delayL->index] = tmp + x * feedback;
			tmp = bufL[index0];
			buf[i] = tmp;
			i++;
			buf[i] = tmp;
			if (++index0 >= sizel) {index0 = 0;}
			if (++delayL->index >= sizel) {delayL->index = 0;}
			if ((index20 += laccel)  >= sizel) {index20 -= sizel;}
			if(info->lshift){
				FLOAT_T sub = (FLOAT_T)index0 - index20;
				if(fabs((FLOAT_T)sub) < laccel || fabs(sub + sizel) < laccel || fabs(sub - sizel) < laccel){
					info->lshift = SHIFT_NONE;
					laccel = 1.0;
				}
			}
		}
		break;
	case CH_LEFT:
		for (i = 0; i < count; i++)
		{
			x = delayL->buf[(int)index20] * feedback;
			sample_filter_left(&info->fc, &x);
			bufL[delayL->index] = buf[i] + x * feedback;
			buf[i] = bufL[index0];
			i++;
			if (++index0 >= sizel) {index0 = 0;}
			if (++delayL->index >= sizel) {delayL->index = 0;}
			if ((index20 += laccel)  >= sizel) {index20 -= sizel;}
			if(info->lshift){
				FLOAT_T sub = (FLOAT_T)index0 - index20;
				if(fabs((FLOAT_T)sub) < laccel || fabs(sub + sizel) < laccel || fabs(sub - sizel) < laccel){
					info->lshift = SHIFT_NONE;
					laccel = 1.0;
				}
			}
		}
		break;
	case CH_RIGHT:
		for (i = 0; i < count; i++)
		{
			i++;
			x = delayR->buf[(int)index21] * feedback;
			sample_filter_right(&info->fc, &x);
			bufR[delayR->index] = buf[i] + x * feedback;
			buf[i] = bufR[index1];
			if (++index1 >= sizer) {index1 = 0;}
			if (++delayR->index >= sizer) {delayR->index = 0;}
			if ((index21 += raccel)  >= sizer) {index21 -= sizer;}
			if(info->rshift){
				FLOAT_T sub = (FLOAT_T)index1 - index21;
				if(fabs((FLOAT_T)sub) < raccel || fabs(sub + sizer) < raccel || fabs(sub - sizer) < raccel){
					info->lshift = SHIFT_NONE;
					laccel = 1.0;
				}
			}
		}
		break;
	}
	
	info->index[0] = index0, info->index[1] = index1, info->index2[0] = index20, info->index2[1] = index21;
	info->laccel = laccel, info->raccel = raccel;
}


// gate
static void init_gate(InfoGate *info, FLOAT_T thres_db, FLOAT_T attack_ms, FLOAT_T release_ms, FLOAT_T peak_ms)
{
	if(!info->init){	
		info->init = 1;
		info->peak_rate = 0.0;
		info->env_mode = 0;
		init_envelope3(&info->gate_env, 0.0, attack_ms * playmode_rate_ms);
		reset_envelope3(&info->gate_env, 0.0, ENVELOPE_KEEP);
	}
	info->attack_cnt = attack_ms * playmode_rate_ms;
	info->release_cnt = release_ms * playmode_rate_ms;
	info->gate_coef = 1.0 / (ins_level * DIV_4 * pow(10.0, -thres_db * DIV_10));	
	info->peak_count = (1000.0 / peak_ms) * div_playmode_rate;
}

static void uninit_gate(InfoGate *info)
{
	info->init = 0;
}

static void calc_gate_peak(InfoGate *info, DATA_T inputL, DATA_T inputR)
{
	FLOAT_T tmpm;

	if((tmpm = fabs((DATA_T)inputL)) > info->peak_level) // math abs
		info->peak_level = tmpm;
	if(inputR)
		if((tmpm = fabs((DATA_T)inputR)) > info->peak_level)
			info->peak_level = tmpm;	
	if((info->peak_rate += info->peak_count) >= 1.0){
		int gate_flg = (info->peak_level * info->gate_coef) > 1.0 ? 1 : 0;
		info->peak_rate -= floor(info->peak_rate); // reset count
		if(gate_flg && !info->env_mode){ 
			info->env_mode = 1; // attck
			reset_envelope3(&info->gate_env, 1.0, info->attack_cnt);
		}else if(!gate_flg && info->env_mode && !check_envelope3(&info->gate_env)){ // after attack time
			info->env_mode = 0; // release
			reset_envelope3(&info->gate_env, 0.0, info->release_cnt);
		}
		info->peak_level = 0;
	}
}

static FLOAT_T get_gate_level(InfoGate *info, int32 count)
{
	compute_envelope3(&info->gate_env, count);
	return info->gate_env.vol;
}


// gate reverb
#define GATE_REV_PEAK_TIME (3.0) // ms
#define GATE_REV_THRESHOLD (48.0) // dB 
#define GATE_REV_ATTACK_TIME (10.0) // ms
#define GATE_REV_ROOMSIZE_FCT (0.0029411764705882352941176470588235)
#define GATE_REV_FB_MLT_FCT (0.985) // 
#define GATE_REV_AP_TIME (0.2385) // sec
#define GATE_REV_LEVEL (1.0)
#define GATE_REV_ER_LEVEL (0.30 * GATE_REV_LEVEL)
#define GATE_REV_AP_LEVEL (0.60)
#define GATE_REV_RV_LEVEL (0.50 * GATE_REV_LEVEL * GATE_REV_AP_LEVEL)
#define GATE_REV_FEEDBACK (0.25)
#define GATE_REV_HPF_FREQ (137.73) // Hz

static void do_gate_reverb(DATA_T *buf, int32 count, InfoGateReverb *info)
{
	int32 i, j, k = 0, cnt = count / 2;
	FLOAT_T leveler = info->leveler, levelrv = info->levelrv, feedback = info->feedback, in_level = info->in_level;
	FilterCoefficients *fc = &(info->fc), *hpf = &info->hpf;
	DATA_T histL = info->histL, histR = info->histR;
	FLOAT_T gate_out, gateL, gateR;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		FLOAT_T pdelay_cnt, room_cnt, dtt, dtS, dtL, ww, fb, fba, bal, lfo_rate, lfo_depth, lenL, lenS;
		FLOAT_T div_er, div_rv;
		// static		
		info->er_norm = pow(1.0 / GATE_REV_ER, DIV_3_2);
		info->rv_norm = pow(1.0 / GATE_REV_RV, DIV_3_2);
		div_er = 1.0 / (GATE_REV_ER - 1);
		div_rv = 1.0 / (GATE_REV_RV - 1);
		// gate
		init_gate(&info->gate, GATE_REV_THRESHOLD, GATE_REV_ATTACK_TIME, info->gate_time_ms, GATE_REV_PEAK_TIME);
		info->in_level = otd.efx_CustomGRevLvIn;
		// er
		pdelay_cnt = info->er_time_ms * playmode_rate_ms;	
		room_cnt = REV_EX_ROOMSIZE_FCT * play_mode->rate;	
		dtt = room_cnt * info->room_size;
		if(pdelay_cnt < dtt)
			pdelay_cnt = 0;
		else
			pdelay_cnt -= dtt;
		dtS = pdelay_cnt + dtt;
		dtL = pdelay_cnt + room_cnt	* info->room_size * 1.7428 * 2.0;
		for (i = 0; i < GATE_REV_ER; i++) {
			FLOAT_T rate = i * div_er;
			FLOAT_T dt1 = dtS * (1.0 - rate) + dtL * rate; // dtS->dtL
			FLOAT_T dt2 = dt1 * 1.259921;
			int32 dtiL = dt1 * pow(1.05, sqrt(rate) * get_white_noise_p());
			int32 dtiR = dt1 * pow(1.05, sqrt(rate) * get_white_noise_p());
			init_fb_delay(&info->erL[i], dtiL, 0);
			init_fb_delay(&info->erR[i], dtiR, 0);
		}
		init_sample_filter(fc, info->er_damp_freq, 0, info->rev_damp_type);
		info->flt_wet = (info->rev_damp_bal + 2.0) * DIV_3;
		info->flt_dry = 1.0 - info->flt_wet;
		info->leveler = info->er_level * GATE_REV_ER_LEVEL * otd.efx_CustomGRevLvOut;
		// rv
		init_prime_list();
		dtL = info->room_size * 1.26345;
		ww = 1.25;
		dtL *= 3.0 * GATE_REV_ROOMSIZE_FCT;
		fb = pow(10.0, -3.0 * dtL / info->rev_time_sec) * GATE_REV_FB_MLT_FCT; // rev time to fb level
		fba = pow(10.0, -3.0 * dtL / (GATE_REV_AP_TIME)) * GATE_REV_FB_MLT_FCT * pow(0.7, GATE_REV_AP); // rev time to fb level
		dtL *= (FLOAT_T)play_mode->rate;
		dtS = dtL * DIV_4;
		for (i = 0; i < GATE_REV_AP; i++) {
			FLOAT_T ratio = i * div_rv;
			FLOAT_T dt = dtS * (1.0 - ratio) + dtL * ratio; // dtS->dtL
			int32 dtiL = dt * DIV_PI * pow(ww, get_white_noise_p());
			int32 dtiR = dt * DIV_PI * pow(ww, get_white_noise_p());
			find_prime(&dtiL);	find_prime(&dtiR);
			init_allpass2(&info->apL[i], dtiL, fba);
			init_allpass2(&info->apR[i], dtiR, fba);
		}
		for (i = 0; i < GATE_REV_RV; i++) {
			FLOAT_T ratio = i * div_rv;
			FLOAT_T dt = dtS * (1.0 - ratio) + dtL * ratio; // dtS->dtL
			int32 dtiL = dt * pow(ww, get_white_noise_p());
			int32 dtiR = dt * pow(ww, get_white_noise_p());
			find_prime(&dtiL);	find_prime(&dtiR);
			init_net_comb(&info->rvL[i], dtiL, fb, info->flt_wet, info->rev_damp_freq, info->rev_damp_type, info->density);
			init_net_comb(&info->rvR[i], dtiR, fb, info->flt_wet, info->rev_damp_freq, info->rev_damp_type, info->density);
			init_net_comb_fbc(info->rvL, i, GATE_REV_RV);
			init_net_comb_fbc(info->rvR, i, GATE_REV_RV);
		}
		info->levelrv = info->rev_level / (sqrt(1.0 + fba) * sqrt(1.0 + fb)) * GATE_REV_RV_LEVEL * otd.efx_CustomGRevLvOut;
		// out
		init_sample_filter(hpf, GATE_REV_HPF_FREQ, 0, FILTER_HPF_BW);
		// other
		info->feedback = info->rev_feedback * GATE_REV_FEEDBACK;
		info->histL = info->histR = 0;	
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		uninit_gate(&info->gate);
		for (i = 0; i < GATE_REV_ER; i++) {	
			free_fb_delay(&info->erL[i]);
			free_fb_delay(&info->erR[i]);
		}
		for (i = 0; i < GATE_REV_AP; i++) {
			free_allpass2(&info->apL[i]);
			free_allpass2(&info->apR[i]);
		}
		for (i = 0; i < GATE_REV_RV; i++) {	
			free_comb2(&info->rvL[i]);
			free_comb2(&info->rvR[i]);
		}
		return;
	} else if(count == 0) {
		return;
	}	
	// gate
	gate_out = get_gate_level(&info->gate, cnt);
	switch(info->type){
	default:
	case 0: // normal
		gateL = gate_out;
		gateR = gate_out;
		break;
	case 1: // reverse
		gateL = 1.0 - gate_out;
		gateR = 1.0 - gate_out;
		break;
	case 2: // sweepl (right to left
		gateL = 1.0 - gate_out;
		gateR = gate_out;
		break;
	case 3: // sweep2 (left to right
		gateL = gate_out;
		gateR = 1.0 - gate_out;
		break;
	}
	// reverb
	// CH_MIX_STEREO
	for (k = 0; k < count; k++)
	{		
		DATA_T dat_erL = 0, dat_erR = 0, dat_rvL = 0, dat_rvR = 0;	
		DATA_T inputL = buf[k] * in_level, inputR = buf[k + 1] * in_level;
		// peak
		calc_gate_peak(&info->gate, inputL, inputR);
		// er
		inputL = inputR = (inputL + inputR) * DIV_MIX_LEVEL + (histL + histR) * DIV_MIX_LEVEL * feedback;
		for (i = 0; i < GATE_REV_ER; i++) {	
			do_fb_delay_add(&info->erL[i], &inputL, &dat_erL);
			do_fb_delay_add(&info->erR[i], &inputR, &dat_erR);
		}
		inputL = dat_erL *= info->er_norm;
		inputR = dat_erR *= info->er_norm;
		sample_filter_stereo(fc, &dat_erL, &dat_erR);
		dat_erL = dat_erL * info->flt_wet + inputL * info->flt_dry;
		dat_erR = dat_erR * info->flt_wet + inputR * info->flt_dry;
		//rv
		inputL = dat_erL;
		inputR = dat_erR;
		for (i = 0; i < GATE_REV_AP; i++) {
			do_allpass2(&info->apL[i], &inputL);
			do_allpass2(&info->apR[i], &inputR);
		}
		for (i = 0; i < GATE_REV_RV; i++) {
			do_net_comb(&info->rvL[i], &inputL, &dat_rvL);
			do_net_comb(&info->rvR[i], &inputR, &dat_rvR);
		}
		for (i = 0; i < GATE_REV_RV; i++) {
			do_net_comb_fbc(&info->rvL[i]);
			do_net_comb_fbc(&info->rvR[i]);
		}
		dat_rvL = (dat_rvL * info->rv_norm) - dat_erL;
		dat_rvR = (dat_rvR * info->rv_norm) - dat_erR;
		// out
		histL = dat_erL * leveler + dat_rvL * levelrv;
		histR = dat_erR * leveler + dat_rvR * levelrv;
		sample_filter_stereo(hpf, &histL, &histR);
		// gate out
		buf[k] = histL * gateL;
		buf[++k] = histR * gateR;
	}
	info->histL = histL, info->histR = histR;
}


static void do_3d_auto(DATA_T *buf, int32 count, Info3DAuto *info)
{
	int i;
	FLOAT_T azimuth;
	DATA_T inout[2];

	if (count == MAGIC_INIT_EFFECT_INFO) {
		if(!info->init){
			info->init = 1;
			info->count = 0.5; // azimuth=0
		}
		info->rate = info->speed * div_playmode_rate;
		if(!info->clockwize)
			info->rate *= -1.0;
		info->stop = info->azimuth * DIV_2 + DIV_2; // -1.0~+1.0 to 0.0~1.0
		info->locate.out = info->out;
		init_3d_locate(&info->locate);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		uninit_3d_locate(&info->locate);
		return;
	}
	// CH_MIX_STEREO:
	info->count += info->rate * count;
	if(!info->turn && info->clockwize && info->count >= info->stop)
		info->count = info->stop;
	else if(!info->turn && !info->clockwize && info->count <= info->stop)
		info->count = info->stop;
	else
		info->count -= floor(info->count);
	azimuth = info->count * 2.0 - 1.0; // 0.0~1.0 to -1.0~+1.0
	for (i = 0; i < count; i++)
	{
		inout[1] = inout[0] = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
		do_3d_locate(&info->locate, inout, azimuth);
		buf[i] = inout[0];
		i++;
		buf[i] = inout[1];
	}
}

static void do_3d_manual(DATA_T *buf, int32 count, Info3DManual *info)
{
	int i;
	DATA_T inout[2];

	if (count == MAGIC_INIT_EFFECT_INFO) {
		info->locate.out = info->out;
		init_3d_locate(&info->locate);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		uninit_3d_locate(&info->locate);
		return;
	}
	// CH_MIX_STEREO:
	for (i = 0; i < count; i++)
	{
		inout[1] = inout[0] = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
		do_3d_locate(&info->locate, inout, info->azimuth);
		buf[i] = inout[0];
		i++;
		buf[i] = inout[1];
	}
}



/********************************** XG EFFECT core ************************************/


#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void do_echo(int32 *buf, int32 count, InfoEcho *info)
{
	int32 i;
	simple_delay *delayL = &(info->delayL), *delayR = &(info->delayR);
	FilterCoefficients *lpf = &(info->lpf);
	int32 *bufL = delayL->buf, *bufR = delayR->buf;
	int32 indexl = delayL->index, sizel = delayL->size,
		indexr = delayR->index, sizer = delayR->size,
		indexl2 = info->index[0], indexr2 = info->index[1];
	int32 lfeedbacki = info->lfeedbacki, rfeedbacki = info->rfeedbacki, level2i = info->delay2_leveli;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		int32 size;
		info->size[0] = info->ldelay2 * playmode_rate_ms;
		size = info->ldelay1 * playmode_rate_ms;
		if (info->size[0] > size) {info->size[0] = size;}
		size++;
		set_delay(&(info->delayL), size);
		info->index[0] = size - info->size[0];
		info->size[1] = info->rdelay2 * playmode_rate_ms;
		size = info->rdelay1 * playmode_rate_ms;
		if (info->size[1] > size) {info->size[1] = size;}
		size++;
		set_delay(&(info->delayR), size);
		info->index[1] = size - info->size[1];
		info->delay2_leveli =  TIM_FSCALE(info->delay2_level, 24);
		info->lfeedbacki = TIM_FSCALE(info->lfeedback, 24);
		info->rfeedbacki = TIM_FSCALE(info->rfeedback, 24);
		init_sample_filter(lpf, info->high_damp, 0, FILTER_LPF6); // damp Hz
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_delay(&(info->delayL));
		free_delay(&(info->delayR));
		return;
	}
	for (i = 0; i < count; i++)
	{
		int32 tmp, outL1 = bufL[indexl], outL2 = bufL[indexl2], outR1 = bufR[indexr], outR2 = bufR[indexr2];
		tmp = imuldiv24(outL1, lfeedbacki);
		sample_filter_left(lpf, &tmp);
		bufL[indexl] = buf[i] + tmp;
		buf[i] = outL1 + imuldiv24(outL2, level2i);
		++i;
		tmp = imuldiv24(outR1, rfeedbacki);
		sample_filter_right(lpf, &tmp);
		bufR[indexr] = buf[i] + tmp;
		buf[i] = outR1 + imuldiv24(outR2, level2i);
		
		if (++indexl >= sizel) {indexl = 0;}
		if (++indexr >= sizer) {indexr = 0;}
		if (++indexl2 >= sizel) {indexl2 = 0;}
		if (++indexr2 >= sizer) {indexr2 = 0;}
	}
	info->index[0] = indexl2, info->index[1] = indexr2;
	delayL->index = indexl, delayR->index = indexr;
}
#else /* floating-point implementation */
static void do_echo(DATA_T *buf, int32 count, InfoEcho *info)
{
	int32 i;
	simple_delay *delayL = &(info->delayL), *delayR = &(info->delayR);
	FilterCoefficients *lpf = &(info->lpf);
	DATA_T *bufL = delayL->buf, *bufR = delayR->buf;
	int32 indexl = delayL->index, sizel = delayL->size,
		indexr = delayR->index, sizer = delayR->size;
	int32 indexl2 = info->index[0], indexr2 = info->index[1];
	FLOAT_T lfeedback = info->lfeedback, rfeedback = info->rfeedback, level2 = info->delay2_level;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		int32 size;
		info->size[0] = info->ldelay2 * playmode_rate_ms;
		size = info->ldelay1 * playmode_rate_ms;
		if (info->size[0] > size) {info->size[0] = size;}
		size++;
		set_delay(&(info->delayL), size);
		info->index[0] = size - info->size[0];
		info->size[1] = info->rdelay2 * playmode_rate_ms;
		size = info->rdelay1 * playmode_rate_ms;
		if (info->size[1] > size) {info->size[1] = size;}
		size++;
		set_delay(&(info->delayR), size);
		info->index[1] = size - info->size[1];
		init_sample_filter(lpf, info->high_damp, 0, FILTER_LPF6); // damp Hz
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		free_delay(&(info->delayL));
		free_delay(&(info->delayR));
		return;
	}
	for (i = 0; i < count; i++)
	{
		DATA_T tmp, outL1 = bufL[indexl], outL2 = bufL[indexl2], outR1 = bufR[indexr], outR2 = bufR[indexr2];
		tmp = outL1 * lfeedback;
		sample_filter_left(lpf, &tmp);
		bufL[indexl] = buf[i] + tmp;
		buf[i] = outL1 + outL2 * level2;
		++i;
		tmp = outR1 * rfeedback;
		sample_filter_right(lpf, &tmp);
		bufR[indexr] = buf[i] + tmp;
		buf[i] = outR1 + outR2 * level2;

		if (++indexl >= sizel) {indexl = 0;}
		if (++indexr >= sizer) {indexr = 0;}
		if (++indexl2 >= sizel) {indexl2 = 0;}
		if (++indexr2 >= sizer) {indexr2 = 0;}
	}
	info->index[0] = indexl2, info->index[1] = indexr2;
	delayL->index = indexl, delayR->index = indexr;
}
#endif /* OPT_MODE != 0 */




///r
#define XG_OD_DRIVE 1.75
#define XG_OD_CLIP_LEVEL 0.75
#define XG_OD_PDL0_GAIN 1.00 // overdrive
#define XG_OD_PDL1_GAIN 1.00 // distortion
#define XG_OD_PDL2_GAIN 1.00 // overdrive2
#define XG_OD_PDL3_GAIN 1.00 // distortion2
#define XG_OD_PDL4_GAIN 1.00 // solid od
#define XG_OD_PDL5_GAIN 1.00 // solid ds
#define XG_OD_PDL6_GAIN 1.00 // tube od
#define XG_OD_PDL7_GAIN 1.00 // tube ds
#define XG_OD_PDL8_GAIN 1.00 // vintage
#define XG_OD_PDL9_GAIN 1.00 // fuzz
#define XG_OD_AMP_DRIVE (1.0)
#define XG_OD_AMP0_GAIN (1.250 * XG_OD_AMP_DRIVE) // off
#define XG_OD_AMP1_GAIN (1.250 * XG_OD_AMP_DRIVE) // stack
#define XG_OD_AMP2_GAIN (1.250 * XG_OD_AMP_DRIVE) // combo
#define XG_OD_AMP3_GAIN (1.250 * XG_OD_AMP_DRIVE) // tube
#define XG_OD_AMP4_GAIN (1.100 * XG_OD_AMP_DRIVE) // crunch
#define XG_OD_AMP5_GAIN (1.300 * XG_OD_AMP_DRIVE) // stack higain
#define XG_OD_AMP6_GAIN (1.250 * XG_OD_AMP_DRIVE) // british
#define XG_OD_AMP0_LEVEL 0.8
#define XG_OD_AMP1_LEVEL 1.00
#define XG_OD_AMP2_LEVEL 1.00
#define XG_OD_AMP3_LEVEL 1.00
#define XG_OD_AMP4_LEVEL 1.00
#define XG_OD_AMP5_LEVEL 1.00
#define XG_OD_AMP6_LEVEL 1.00
#define XG_OD_LEVEL 1.0
#define XG_OD_FF1 150.0f
#define XG_OD_FF2 5500.0f
#define XG_OD_FF3 4800.0f
#define XG_OD_FF4_COEF (1.025)
#define XG_OD_FF4_TYPE0 (5999.0f * XG_OD_FF4_COEF) // off
#define XG_OD_FF4_TYPE1 (5300.0f * XG_OD_FF4_COEF) // stack
#define XG_OD_FF4_TYPE2 (5450.0f * XG_OD_FF4_COEF) // combo
#define XG_OD_FF4_TYPE3 (5600.0f * XG_OD_FF4_COEF) // small
#define XG_OD_FF4_TYPE4 (5600.0f * XG_OD_FF4_COEF) // 
#define XG_OD_FF5 9800.0f
#define XG_OD_FQ1 0.0f
#define XG_OD_FQ2 1.0f
#define XG_OD_FQ3 2.0f
#define XG_OD_FQ4 0.0f
#define XG_OD_FQ5 0.85f

static inline double calc_xg_drive_gain(double val)
{
	return ((double)val * DIV_127 * XG_OD_DRIVE + 1.0) * otd.xgefx_CustomODDrive;
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void do_stereo_od(int32 *buf, int32 count, InfoStereoOD *info)
{
	int32 i, high;
	int32 tmp, inputl, inputr, weti = info->weti;
	FilterCoefficients *bw1l = &(info->bw1l), *bw2l = &(info->bw2l), *bw3l = &(info->bw3l), *bw4l = &(info->bw4l),
				*bw1r = &(info->bw1r), *bw2r = &(info->bw2r), *bw3r = &(info->bw3r), *bw4r = &(info->bw4r);
	FilterCoefficients *bq = &(info->bq);

	if (count == MAGIC_INIT_EFFECT_INFO) {
		FLOAT_T bw1r_freq, bw1l_freq, bw2r_freq, bw2l_freq, bw3r_freq, bw3l_freq, bw4r_freq, bw4l_freq;
		int bw2_type;
		/* decompositor anti-aliasing */
		switch (info->od_type) {
		default:
		case 0: // overdrive
			init_drive(&info->drv1, 4, 0.8, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL0_GAIN);
			init_drive(&info->drv2, 4, 0.6, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL0_GAIN);
			bw2_type = FILTER_NONE;
			break;
		case 1: // distortion
			init_drive(&info->drv1, 8, 0.4, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL1_GAIN);
			init_drive(&info->drv2, 8, 0.2, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL1_GAIN);
			bw2_type = FILTER_LPF_BW;
			break;
		case 2: // overdrive2
			init_drive(&info->drv1, 4, 0.7, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL2_GAIN);
			init_drive(&info->drv2, 4, 0.7, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL2_GAIN);
			bw2_type = FILTER_NONE;
			break;
		case 3: // distortion2
			init_drive(&info->drv1, 8, 0.3, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL3_GAIN);
			init_drive(&info->drv2, 8, 0.3, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL3_GAIN);
			bw2_type = FILTER_LPF_BW;
			break;
		case 4: // solid od
			init_drive(&info->drv1, 4, 0.5, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL4_GAIN);
			init_drive(&info->drv2, 4, 0.5, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL4_GAIN);
			bw2_type = FILTER_NONE;
			break;
		case 5: // solid ds
			init_drive(&info->drv1, 6, 0.5, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL5_GAIN);
			init_drive(&info->drv2, 6, 0.2, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL5_GAIN);
			bw2_type = FILTER_LPF_BW;
			break;
		case 6: // tube od
			init_drive(&info->drv1, 4, 1.0, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL6_GAIN);
			init_drive(&info->drv2, 4, 0.6, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL6_GAIN);
			bw2_type = FILTER_NONE;
			break;
		case 7: // tube ds
			init_drive(&info->drv1, 9, 0.4, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL7_GAIN);
			init_drive(&info->drv2, 9, 0.2, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL7_GAIN);
			bw2_type = FILTER_LPF_BW;
			break;
		case 8: // vintage
			init_drive(&info->drv1, 4, 0.3, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL8_GAIN);
			init_drive(&info->drv2, 4, 0.3, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL8_GAIN);
			bw2_type = FILTER_NONE;
			break;
		case 9: // fuzz
			init_drive(&info->drv1, 4, 0.1, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL9_GAIN);
			init_drive(&info->drv2, 9, 0.2, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL9_GAIN);
			bw2_type = FILTER_LPF_BW;
			break;
		}
		switch(info->amp_type){
		default:
		case 0: // off
			init_drive(&info->drv3, 0, 0.0, XG_OD_CLIP_LEVEL, XG_OD_AMP0_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP0_LEVEL;
			break;
		case 1: // stack
			init_drive(&info->drv3, 4, 0.7, XG_OD_CLIP_LEVEL, XG_OD_AMP1_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP1_LEVEL;
			break;
		case 2: // combo 
			init_drive(&info->drv3, 4, 0.6, XG_OD_CLIP_LEVEL, XG_OD_AMP2_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP2_LEVEL;
			break;
		case 3: // tube
			init_drive(&info->drv3, 4, 1.0, XG_OD_CLIP_LEVEL, XG_OD_AMP3_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP3_LEVEL;
			break;
		case 4: // crunch
			init_drive(&info->drv3, 4, 0.2, XG_OD_CLIP_LEVEL, XG_OD_AMP4_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP4_LEVEL;
			break;
		case 5: // stack higain
			init_drive(&info->drv3, 8, 0.3, XG_OD_CLIP_LEVEL, XG_OD_AMP5_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP4_LEVEL;
			break;
		case 6: // british
			init_drive(&info->drv3, 9, 0.2, XG_OD_CLIP_LEVEL, XG_OD_AMP6_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP4_LEVEL;
			break;
		}
		bw1r_freq =   bw1l_freq =   XG_OD_FF1;
		bw2r_freq =   bw2l_freq =   XG_OD_FF2;
		bw3r_freq =   bw3l_freq =   XG_OD_FF3;	
		switch(info->cab_type){
		default:
		case 0: // off	// other
			bw4r_freq =   bw4l_freq =  XG_OD_FF4_TYPE0 * otd.xgefx_CustomODFreq;
			break;
		case 1: // stack
			bw4r_freq =   bw4l_freq =  XG_OD_FF4_TYPE1 * otd.xgefx_CustomODFreq;
			break;
		case 2: // combo
			bw4r_freq =   bw4l_freq =  XG_OD_FF4_TYPE2 * otd.xgefx_CustomODFreq;
			break;
		case 3: // small
			bw4r_freq =   bw4l_freq =  XG_OD_FF4_TYPE3 * otd.xgefx_CustomODFreq;
			break;
		case 4: // 
			bw4r_freq =   bw4l_freq =  XG_OD_FF4_TYPE4 * otd.xgefx_CustomODFreq;
			break;
		}
		switch(info->mode){
		case CH_STEREO:
			// L
			bw1l_freq += 5.0;
			bw2l_freq -= 20.0;
			bw3l_freq += 20.0;
			bw4l_freq -= 20;
			// R			
			bw1r_freq -= 5.0;
			bw2r_freq += 20.0;
			bw3r_freq -= 20;
			bw4r_freq += 20.0;
			break;
		case CH_MIX_MONO:
		case CH_MONO:
			break;
		}
		init_sample_filter(bw1l, bw1l_freq, XG_OD_FQ1, FILTER_HPF_BW);
		init_sample_filter(bw1r, bw1r_freq, XG_OD_FQ1, FILTER_HPF_BW);
		init_sample_filter(bw2l, bw2l_freq, XG_OD_FQ2, bw2_type);
		init_sample_filter(bw2r, bw2r_freq, XG_OD_FQ2, bw2_type);
		init_sample_filter(bw3l, bw3l_freq, XG_OD_FQ3, FILTER_LPF_BW);
		init_sample_filter(bw3r, bw3r_freq, XG_OD_FQ3, FILTER_LPF_BW);
		init_sample_filter(bw4l, bw4l_freq, XG_OD_FQ4, FILTER_LPF_BW);
		init_sample_filter(bw4r, bw4r_freq, XG_OD_FQ4, FILTER_LPF_BW);
		// cutoff
	//	init_sample_filter2(bq, info->cutoff, 0, XG_OD_FQ5, FILTER_BIQUAD_LOW);
		init_sample_filter(bq, info->cutoff, XG_OD_FQ5, FILTER_LPF6);
		info->wetd *= otd.xgefx_CustomODLv * XG_OD_LEVEL;
		info->weti = TIM_FSCALE(info->wetd, 24);
		return;
	} else if (count == MAGIC_FREE_EFFECT_INFO) {
		return;
	}
	switch (info->mode) {
	case CH_STEREO:
		for (i = 0; i < count; i++) {
			DATA_T input_d[2] = {buf[i], buf[i + 1]};
			/* waveshaping amp simulation anti-aliasing */
			sample_filter(bw1l, &input_d[0]);
			sample_filter(bw1r, &input_d[1]);
			do_drive_stereo(&info->drv1, input_d);
			sample_filter(bw2l, &input_d[0]);
			sample_filter(bw2r, &input_d[1]);
			do_drive_stereo(&info->drv2, input_d);
			sample_filter(bw3l, &input_d[0]);
			sample_filter(bw3r, &input_d[1]);
			do_drive_stereo(&info->drv3, input_d);
			sample_filter(bw4l, &input_d[0]);
			sample_filter(bw4r, &input_d[1]);
			sample_filter_left(bq, &input_d[0]);
			sample_filter_right(bq, &input_d[1]);
			buf[i] = imuldiv24(input_d[0], weti);
			i++;
			buf[i] = imuldiv24(input_d[1], weti);
		}
		break;
	case CH_MIX_MONO:
		for (i = 0; i < count; i++) {
			/* mix */
			DATA_T input = imuldiv24(buf[i] + buf[i + 1], DIV_MIX_LEVELi);
			/* waveshaping amp simulation anti-aliasing */
			sample_filter(bw1l, &input);
			do_drive_mono(&info->drv1, &input);
			sample_filter(bw2l, &input);
			do_drive_mono(&info->drv2, &input);
			sample_filter(bw3l, &input);
			do_drive_mono(&info->drv3, &input);
			sample_filter(bw4l, &input);
			sample_filter_left(bq, &input);
			tmp = imuldiv24(input, weti);
			buf[i] = tmp;
			i++;
			buf[i] = tmp;
		}
		break;
	case CH_MONO:
		for (i = 0; i < count; i++) {
			/* left */
			DATA_T input = buf[i];
			/* waveshaping amp simulation anti-aliasing */
			sample_filter(bw1l, &input);
			do_drive_mono(&info->drv1, &input);
			sample_filter(bw2l, &input);
			do_drive_mono(&info->drv2, &input);
			sample_filter(bw3l, &input);
			do_drive_mono(&info->drv3, &input);
			sample_filter(bw4l, &input);
			sample_filter_left(bq, &input);
			tmp = imuldiv24(input, weti);
			buf[i] = tmp;
			i++;
			buf[i] = tmp;
		}
		break;
	}
}
#else /* floating-point implementation */
static void do_stereo_od(DATA_T *buf, int32 count, InfoStereoOD *info)
{
	int32 i, high; 
	double wetd = info->wetd;
	FilterCoefficients *bw1l = &(info->bw1l), *bw2l = &(info->bw2l), *bw3l = &(info->bw3l), *bw4l = &(info->bw4l),
				*bw1r = &(info->bw1r), *bw2r = &(info->bw2r), *bw3r = &(info->bw3r), *bw4r = &(info->bw4r);
	FilterCoefficients *bq = &(info->bq);
	DATA_T inputl, inputr;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		FLOAT_T bw1r_freq, bw1l_freq, bw2r_freq, bw2l_freq, bw3r_freq, bw3l_freq, bw4r_freq, bw4l_freq;
		int bw2_type;
		/* decompositor anti-aliasing */
		switch (info->od_type) {
		default:
		case 0: // overdrive
			init_drive(&info->drv1, 4, 0.8, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL0_GAIN);
			init_drive(&info->drv2, 4, 0.6, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL0_GAIN);
			bw2_type = FILTER_NONE;
			break;
		case 1: // distortion
			init_drive(&info->drv1, 8, 0.4, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL1_GAIN);
			init_drive(&info->drv2, 8, 0.2, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL1_GAIN);
			bw2_type = FILTER_LPF_BW;
			break;
		case 2: // overdrive2
			init_drive(&info->drv1, 4, 0.7, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL2_GAIN);
			init_drive(&info->drv2, 4, 0.7, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL2_GAIN);
			bw2_type = FILTER_NONE;
			break;
		case 3: // distortion2
			init_drive(&info->drv1, 8, 0.3, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL3_GAIN);
			init_drive(&info->drv2, 8, 0.3, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL3_GAIN);
			bw2_type = FILTER_LPF_BW;
			break;
		case 4: // solid od
			init_drive(&info->drv1, 4, 0.5, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL4_GAIN);
			init_drive(&info->drv2, 4, 0.5, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL4_GAIN);
			bw2_type = FILTER_NONE;
			break;
		case 5: // solid ds
			init_drive(&info->drv1, 6, 0.5, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL5_GAIN);
			init_drive(&info->drv2, 6, 0.2, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL5_GAIN);
			bw2_type = FILTER_LPF_BW;
			break;
		case 6: // tube od
			init_drive(&info->drv1, 4, 1.0, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL6_GAIN);
			init_drive(&info->drv2, 4, 0.6, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL6_GAIN);
			bw2_type = FILTER_NONE;
			break;
		case 7: // tube ds
			init_drive(&info->drv1, 9, 0.4, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL7_GAIN);
			init_drive(&info->drv2, 9, 0.2, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL7_GAIN);
			bw2_type = FILTER_LPF_BW;
			break;
		case 8: // vintage
			init_drive(&info->drv1, 4, 0.3, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL8_GAIN);
			init_drive(&info->drv2, 4, 0.3, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL8_GAIN);
			bw2_type = FILTER_NONE;
			break;
		case 9: // fuzz
			init_drive(&info->drv1, 4, 0.1, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL9_GAIN);
			init_drive(&info->drv2, 9, 0.2, XG_OD_CLIP_LEVEL, calc_xg_drive_gain(info->drive) * XG_OD_PDL9_GAIN);
			bw2_type = FILTER_LPF_BW;
			break;
		}
		switch(info->amp_type){
		default:
		case 0: // off
			init_drive(&info->drv3, 0, 0.0, XG_OD_CLIP_LEVEL, XG_OD_AMP0_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP0_LEVEL;
			break;
		case 1: // stack
			init_drive(&info->drv3, 4, 0.7, XG_OD_CLIP_LEVEL, XG_OD_AMP1_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP1_LEVEL;
			break;
		case 2: // combo 
			init_drive(&info->drv3, 4, 0.6, XG_OD_CLIP_LEVEL, XG_OD_AMP2_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP2_LEVEL;
			break;
		case 3: // tube
			init_drive(&info->drv3, 4, 1.0, XG_OD_CLIP_LEVEL, XG_OD_AMP3_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP3_LEVEL;
			break;
		case 4: // crunch
			init_drive(&info->drv3, 4, 0.2, XG_OD_CLIP_LEVEL, XG_OD_AMP4_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP4_LEVEL;
			break;
		case 5: // stack higain
			init_drive(&info->drv3, 8, 0.3, XG_OD_CLIP_LEVEL, XG_OD_AMP5_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP4_LEVEL;
			break;
		case 6: // british
			init_drive(&info->drv3, 9, 0.2, XG_OD_CLIP_LEVEL, XG_OD_AMP6_GAIN * otd.xgefx_CustomODDrive);
			info->wetd = XG_OD_AMP4_LEVEL;
			break;
		}
		bw1r_freq =   bw1l_freq =   XG_OD_FF1;
		bw2r_freq =   bw2l_freq =   XG_OD_FF2;
		bw3r_freq =   bw3l_freq =   XG_OD_FF3;	
		switch(info->cab_type){
		default:
		case 0: // off	// other
			bw4r_freq =   bw4l_freq =  XG_OD_FF4_TYPE0 * otd.xgefx_CustomODFreq;
			break;
		case 1: // stack
			bw4r_freq =   bw4l_freq =  XG_OD_FF4_TYPE1 * otd.xgefx_CustomODFreq;
			break;
		case 2: // combo
			bw4r_freq =   bw4l_freq =  XG_OD_FF4_TYPE2 * otd.xgefx_CustomODFreq;
			break;
		case 3: // small
			bw4r_freq =   bw4l_freq =  XG_OD_FF4_TYPE3 * otd.xgefx_CustomODFreq;
			break;
		case 4: // 
			bw4r_freq =   bw4l_freq =  XG_OD_FF4_TYPE4 * otd.xgefx_CustomODFreq;
			break;
		}
		switch(info->mode){
		case CH_STEREO:
			// L
			bw1l_freq += 5.0;
			bw2l_freq -= 20.0;
			bw3l_freq += 20.0;
			bw4l_freq -= 20;
			// R			
			bw1r_freq -= 5.0;
			bw2r_freq += 20.0;
			bw3r_freq -= 20;
			bw4r_freq += 20.0;
			break;
		case CH_MIX_MONO:
		case CH_MONO:
			break;
		}
		init_sample_filter(bw1l, bw1l_freq, XG_OD_FQ1, FILTER_HPF_BW);
		init_sample_filter(bw1r, bw1r_freq, XG_OD_FQ1, FILTER_HPF_BW);
		init_sample_filter(bw2l, bw2l_freq, XG_OD_FQ2, bw2_type);
		init_sample_filter(bw2r, bw2r_freq, XG_OD_FQ2, bw2_type);
		init_sample_filter(bw3l, bw3l_freq, XG_OD_FQ3, FILTER_LPF_BW);
		init_sample_filter(bw3r, bw3r_freq, XG_OD_FQ3, FILTER_LPF_BW);
		init_sample_filter(bw4l, bw4l_freq, XG_OD_FQ4, FILTER_LPF_BW);
		init_sample_filter(bw4r, bw4r_freq, XG_OD_FQ4, FILTER_LPF_BW);
		// cutoff
	//	init_sample_filter2(bq, info->cutoff, 0, XG_OD_FQ5, FILTER_BIQUAD_LOW);
		init_sample_filter(bq, info->cutoff, XG_OD_FQ5, FILTER_LPF6);
		info->wetd *= otd.xgefx_CustomODLv * XG_OD_LEVEL;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		return;
	}
	switch(info->mode){
	case CH_STEREO:
		for(i = 0; i < count; i++) {
			DATA_T input_d[2] = {buf[i], buf[i + 1]};
			/* waveshaping amp simulation anti-aliasing */
			sample_filter(bw1l, &input_d[0]);
			sample_filter(bw1r, &input_d[1]);
			do_drive_stereo(&info->drv1, input_d);
			sample_filter(bw2l, &input_d[0]);
			sample_filter(bw2r, &input_d[1]);
			do_drive_stereo(&info->drv2, input_d);
			sample_filter(bw3l, &input_d[0]);
			sample_filter(bw3r, &input_d[1]);
			do_drive_stereo(&info->drv3, input_d);
			sample_filter(bw4l, &input_d[0]);
			sample_filter(bw4r, &input_d[1]);
			sample_filter_left(bq, &input_d[0]);
			sample_filter_right(bq, &input_d[1]);
			buf[i] = input_d[0] * wetd;
			i++;
			buf[i] = input_d[1] * wetd;
		}
		break;
	case CH_MIX_MONO:
		for(i = 0; i < count; i++) {
			/* mix */
			DATA_T input = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
			/* waveshaping amp simulation anti-aliasing */
			sample_filter(bw1l, &input);
			do_drive_mono(&info->drv1, &input);
			sample_filter(bw2l, &input);
			do_drive_mono(&info->drv2, &input);
			sample_filter(bw3l, &input);
			do_drive_mono(&info->drv3, &input);
			sample_filter(bw4l, &input);
			sample_filter_left(bq, &input);
			input *= wetd;
			buf[i] = input;
			i++;
			buf[i] = input;
		}
		break;
	case CH_MONO:
		for(i = 0; i < count; i++) {
			/* left */
			DATA_T input = buf[i];
			/* waveshaping amp simulation anti-aliasing */
			sample_filter(bw1l, &input);
			do_drive_mono(&info->drv1, &input);
			sample_filter(bw2l, &input);
			do_drive_mono(&info->drv2, &input);
			sample_filter(bw3l, &input);
			do_drive_mono(&info->drv3, &input);
			sample_filter(bw4l, &input);
			sample_filter_left(bq, &input);
			input *= wetd;
			buf[i] = input;
			i++;
			buf[i] = input;
		}
		break;
	}
}		
#endif /* OPT_MODE != 0 */




#define NG_PEAK_TIME (3.0) // ms
static void do_noise_gate(DATA_T *buf, int32 count, InfoNoiseGate *info)
{
	int32 i, cnt = count / 2;
	FLOAT_T gate_out;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		init_gate(&info->gate, info->threshold, info->attack_ms, info->release_ms, NG_PEAK_TIME);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO){
		uninit_gate(&info->gate);
		return;
	}else if(count == 0)
		return;
	gate_out = get_gate_level(&info->gate, cnt);
	for (i = 0; i < count; i++)
	{
		DATA_T inputL = buf[i], inputR = buf[i + 1];
		calc_gate_peak(&info->gate, inputL, inputR);
		buf[i] = inputL * gate_out;
		i++;
		buf[i] = inputR * gate_out;
	}
}

#define AMBIENCE_TIME (3000.0) // ms
#define AMBIENCE_LEVEL (1.0)
#define AMBIENCE_FEEDBACK (0.98)
static void do_ambience(DATA_T *buf, int32 count, InfoAmbience *info)
{
	int32 i;
	simple_delay *delay = &(info->delay);
	int32 index = delay->index, size = delay->size, delay_cnt = info->delay_cnt;
	DATA_T *dbuf = delay->buf;
	FLOAT_T feedbackd = info->feedbackd, wetd = info->wetd;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		if(!info->init){
			info->init = 1;
			// 50ms : XG max delay time
			set_delay(&(info->delay), 50.0 * playmode_rate_ms + 1);
		}			
		info->delay_cnt = info->delay_ms * playmode_rate_ms;
		if(info->delay_cnt < 1)
			info->delay_cnt = 1;
		info->feedbackd = pow(10.0, -3.0 * info->delay_ms / AMBIENCE_TIME) * AMBIENCE_FEEDBACK; // time to feedback
		info->wetd = 1.0 / sqrt(1.0 + info->feedbackd);
		info->sign = info->phase ? (-1) : 1;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		info->init = 0;
		free_delay(&(info->delay));
		return;
	}
	// CH_MIX_STEREO:
	for (i = 0; i < count; i++)
	{
		DATA_T tmp, bufout;
		DATA_T input = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL;
		int32 r_index = index - delay_cnt;
		if(r_index < 0)
			r_index += size;
		bufout = dbuf[r_index];
		dbuf[index] = input + bufout * feedbackd;
		tmp = (bufout + input * info->sign) * wetd;		
		buf[i] = tmp;
		buf[++i] = tmp;
		if (++index >= size) {index = 0;}
	}	
	delay->index = index;
}


///r
#define INS_LOFI_BIT (SAMPLE_BITS + AMP_BITS - 4) // must INS_LOFI_BIT > 16bit
#define NZ_GEN_LEVEL (0.5)
const FLOAT_T nz_gen_max = (double)((1<<(INS_LOFI_BIT))-1) * NZ_GEN_LEVEL;

static void do_lofi(DATA_T *buf, int32 count, InfoLoFi *info)
{
	int32 i;
	FilterCoefficients *sr_fil = &(info->sr_fil), *pre_fil = &(info->pre_fil), *post_fil = &(info->post_fil)
		, *wpf = &(info->wp_lpf), *humf = &(info->hum_lpf), *dscf = &(info->disc_lpf);
	pink_noise *pnzl = &(info->pnzl), *pnzr = &(info->pnzr);
	FLOAT_T level_in = info->level_in, level_out = info->level_out,	level_down = info->level_down, level_up = info->level_up;
	DATA_T x, wpt;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		// sample rate
		if(info->sr_rate < play_mode->rate)
			init_sample_filter2(sr_fil, info->sr_rate * DIV_2, 0.0, 0.0, FILTER_LPF24_2x2);
		else
			init_sample_filter2(sr_fil, 0, 0, 0, FILTER_NONE);	
		// pre filter
		init_sample_filter2(pre_fil, info->pre_fil_freq, info->pre_fil_reso, 0.0, info->pre_fil_type);
		// post filter
		init_sample_filter2(post_fil, info->post_fil_freq, info->post_fil_reso, 0.0, info->post_fil_type);
		info->level_up = pow(2.0, INS_LOFI_BIT - info->bit_length);
		info->level_down = 1.0 / info->level_up;
		if(info->nz_gen){
			if(info->wp_sel){
				init_pink_noise(pnzl);
				init_pink_noise(pnzr);
			}
			init_sample_filter(wpf, info->wp_freq, 0, FILTER_LPF24_2);
		//	init_sample_filter(humf, info->hum_freq, 8, FILTER_PEAK1);
		//	init_sample_filter(dscf, info->disc_freq, 8, FILTER_LPF6);
		}
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		return;
	} else if(count <= 0) {
		return;
	}	
	if(info->nz_gen){ // use noise generator
		switch(info->mode){
		case CH_STEREO:
			for (i = 0; i < count; i++)
			{
				// left
				x = buf[i] * level_in;
				sample_filter_left(sr_fil, &x);
				sample_filter_left(pre_fil, &x);			
				x = floor((FLOAT_T)x * level_down) * level_up;
				sample_filter_left(post_fil, &x);
				if(info->wp_sel)
					wpt = get_pink_noise(pnzl) * nz_gen_max;
				else
					wpt = get_white_noise() * nz_gen_max;			
				sample_filter_left(wpf, &wpt);
				x += wpt * info->wp_level * NZ_GEN_LEVEL;
				buf[i] = x * level_out;			
				// right
				x = buf[++i] * level_in;
				sample_filter_right(sr_fil, &x);
				sample_filter_right(pre_fil, &x);
				x = floor((FLOAT_T)x * level_down) * level_up;
				sample_filter_right(post_fil, &x);
				if(info->wp_sel)
					wpt = get_pink_noise(pnzr) * nz_gen_max;
				else
					wpt = get_white_noise() * nz_gen_max;
				sample_filter_right(wpf, &wpt);
				x += wpt * info->wp_level * NZ_GEN_LEVEL;
				buf[i] = x * level_out;
			}
			break;
		case CH_MIX_MONO:
			for (i = 0; i < count; i++)
			{
				// mix (left
				x = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL * level_in;
				sample_filter_left(sr_fil, &x);
				sample_filter_left(pre_fil, &x);
				x = floor((FLOAT_T)x * level_down) * level_up;
				sample_filter_left(post_fil, &x);
				if(info->wp_sel)
					wpt = get_pink_noise(pnzl) * nz_gen_max;
				else
					wpt = get_white_noise() * nz_gen_max;			
				sample_filter_left(wpf, &wpt);
				x += wpt * info->wp_level * NZ_GEN_LEVEL;
				x *= level_out;
				buf[i] = x;
				++i;
				buf[i] = x;
			}
			break;
		}
	}else{ // not use noise generator
		switch(info->mode){
		case CH_STEREO:
			for (i = 0; i < count; i++)
			{
				// left
				x = buf[i] * level_in;
				sample_filter_left(sr_fil, &x);
				sample_filter_left(pre_fil, &x);			
				x = floor((FLOAT_T)x * level_down) * level_up;
				sample_filter_left(post_fil, &x);
				buf[i] = x * level_out;			
				// right
				x = buf[++i] * level_in;
				sample_filter_right(sr_fil, &x);
				sample_filter_right(pre_fil, &x);
				x = floor((FLOAT_T)x * level_down) * level_up;
				sample_filter_right(post_fil, &x);
				buf[i] = x * level_out;
			}
			break;
		case CH_MIX_MONO:
			for (i = 0; i < count; i++)
			{
				// mix (left
				x = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL * level_in;
				sample_filter_left(sr_fil, &x);
				sample_filter_left(pre_fil, &x);
				x = floor((FLOAT_T)x * level_down) * level_up;
				sample_filter_left(post_fil, &x);
				x *= level_out;
				buf[i] = x;
				++i;
				buf[i] = x;
			}
			break;
		}
	}
}











/********************************** SD EFFECT core ************************************/



/*
clipping point :  -1.0,1.0
input level :  -1.0~1.0 x ~4.0
*/
static inline void do_clipping_var_dummy(DATA_T *in, FLOAT_T gain, FLOAT_T curve){}

static inline void do_clipping_var1(DATA_T *in, FLOAT_T gain, FLOAT_T curve)
{
	DATA_T cv1, cv2, out, linear, pole = (*in < 0) ? -1.0 : 1.0;

	cv1 = linear = *in * pole * gain;
	cv2 = sqrt(linear);
	out = (cv1 * (1.0 - cv1) + cv2 * cv1); // mix(linear,curve,var);
	if(out > 2.0)
		out = 2.0;
	*in = pole * out;
}

static inline void do_clipping_var2(DATA_T *in, FLOAT_T gain, FLOAT_T curve)
{
	DATA_T cv1, cv2, out, linear, pole = (*in < 0) ? -1.0 : 1.0;

	cv1 = linear = *in * pole * gain;
	if(linear > 1.0){
		cv2 = sqrt(linear);
	}else{
		cv2 = linear * linear * (1.0 - linear) + sqrt(linear) * (linear); // mix(sq(in),sqrt(in),in);	
	}
	out = (cv1 * (1.0 - cv1) + cv2 * cv1); // mix(linear,curve,var);
	if(out > 2.0)
		out = 2.0;
	*in = pole * out;
}

static inline void do_clipping_var3(DATA_T *in, FLOAT_T gain, FLOAT_T curve)
{
	DATA_T cv1, cv2, out, linear, pole = (*in < 0) ? -1.0 : 1.0;

	linear = *in * pole * gain;
	cv1 = sqrt(linear);
	cv2 = linear > 1.0 ? 1.0 : linear;
	out = (cv1 * (1.0 - cv1) + cv2 * cv1); // mix(linear,curve,var);
	if(out > 2.0)
		out = 2.0;
	*in = pole * out;
}

static inline void do_clipping_var4(DATA_T *in, FLOAT_T gain, FLOAT_T curve)
{
	DATA_T cv1, cv2, out, linear, pole = (*in < 0) ? -1.0 : 1.0;

	linear = *in * pole * gain;

	if(linear > 1.0){
		cv1 = 1.0 + sqrt((linear - 1.0));
		cv2 = 1.0;
	}else{
		cv1 = linear * linear * (1.0 - linear) + sqrt(linear) * (linear); // mix(sq(in),sqrt(in),in);	
		cv2 = linear;
	}
	out = (cv1 * (1.0 - cv1) + cv2 * cv1); // mix(linear,curve,var);
	if(out > 2.0)
		out = 2.0;
	*in = pole * out;
}

static inline void do_clipping_var5(DATA_T *in, FLOAT_T gain, FLOAT_T curve)
{
	DATA_T cv1, cv2, out, linear, sub, pole = (*in < 0) ? -1.0 : 1.0;

	linear = *in * pole * gain;
	if(linear > 1.0){
		sub = (linear - 1.0) * DIV_4;
		cv1 = 1.0 + sqrt(sub);
		cv2 = 1.0 - sub;
	}else{
		cv1 = linear * linear * (1.0 - linear) + sqrt(linear) * (linear); // mix(sq(in),sqrt(in),in);	
		cv2 = linear;
	}
	out = (cv1 * (1.0 - cv1) + cv2 * cv1); // mix(linear,curve,var);
	if(out > 2.0)
		out = 2.0;
	*in = pole * out;
}

static inline void do_clipping_var6(DATA_T *in, FLOAT_T gain, FLOAT_T curve)
{
	DATA_T cv1, cv2, out, linear, sub, pole = (*in < 0) ? -1.0 : 1.0;

	linear = *in * pole * gain;
	
	if(linear > 1.0){
		cv1 = 1.0 + sqrt((linear - 1.0) * DIV_4);
	}else{
		cv1 = linear * linear * (1.0 - linear) + sqrt(linear) * (linear); // mix(sq(in),sqrt(in),in);	
	}
	if(linear > 2.0){
		cv2 = linear - 1.0;
	}else if(linear > 1.0){
		cv2 = 2.0 - linear;
	}else{
		cv2= linear;
	}
	out = (cv1 * (1.0 - cv1) + cv2 * cv1); // mix(linear,curve,var);
	if(out > 2.0)
		out = 2.0;
	*in = pole * out;
}




#define DISTORTION_GAIN (2.0 * 4.0)
#define DISTORTION_LEVEL (2.0 * DIV_4)

static void do_distortion(DATA_T *buf, int32 count, InfoDistortion *info)
{
	int32 i;
	DATA_T input, hpf_freq, lpf_freq;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		hpf_freq = info->bass_od ? 50 : 140;
		switch(info->od_type){
		case 0: // off
			info->curve1 = info->curve2 = 1.0;
			info->do_od1 = do_clipping_var_dummy;
			info->do_od2 = do_clipping_var_dummy;
			init_sample_filter(&info->od_fc1, hpf_freq, 0, FILTER_NONE);
			init_sample_filter(&info->od_fc2, hpf_freq, 0, FILTER_NONE);
			break;
		default:
		case 1: // overdrive
			info->curve1 = info->curve2 = info->edge;
			info->do_od1 = do_clipping_var3;
			info->do_od2 = do_clipping_var_dummy;
			init_sample_filter(&info->od_fc1, hpf_freq, 0, FILTER_HPF6);
			init_sample_filter(&info->od_fc2, hpf_freq, 0, FILTER_NONE);
			break;
		case 2: // distortion
			info->curve1 = info->curve2 = info->edge;
			info->do_od1 = do_clipping_var3;
			info->do_od2 = do_clipping_var3;
			init_sample_filter(&info->od_fc1, hpf_freq, 0, FILTER_HPF6);
			init_sample_filter(&info->od_fc2, hpf_freq, 0, FILTER_HPF6);
			break;
		case 3: // trangistor
			info->curve1 = info->curve2 = 0.97;
			info->do_od1 = do_clipping_var3;
			info->do_od2 = do_clipping_var3;
			init_sample_filter(&info->od_fc1, hpf_freq, 0, FILTER_HPF6);
			init_sample_filter(&info->od_fc2, hpf_freq, 0, FILTER_HPF6);
			break;
		case 4: // vintage
			info->curve1 = 0.27;
			info->curve2 = 0.77;
			info->do_od1 = do_clipping_var4;
			info->do_od1 = do_clipping_var4;
			init_sample_filter(&info->od_fc1, hpf_freq, 0, FILTER_HPF6);
			init_sample_filter(&info->od_fc2, hpf_freq, 0, FILTER_HPF6);
			break;
		case 5: // tube
			info->curve1 = info->curve2 = 0.07;
			info->do_od1 = do_clipping_var4;
			info->do_od2 = do_clipping_var_dummy;
			init_sample_filter(&info->od_fc1, hpf_freq, 0, FILTER_HPF6);
			init_sample_filter(&info->od_fc2, hpf_freq, 0, FILTER_HPF6);
			break;
		case 6: // dist1
			info->curve1 = 0.27;
			info->curve2 = 0.77;
			info->do_od1 = do_clipping_var4;
			info->do_od2 = do_clipping_var3;
			init_sample_filter(&info->od_fc1, hpf_freq, 0, FILTER_HPF6);
			init_sample_filter(&info->od_fc2, hpf_freq, 0, FILTER_HPF6);
			break;
		case 7: // dist2
			info->curve1 = 0.77;
			info->curve2 = 0.27;
			info->do_od1 = do_clipping_var5;
			info->do_od2 = do_clipping_var3;
			init_sample_filter(&info->od_fc1, hpf_freq, 0, FILTER_HPF6);
			init_sample_filter(&info->od_fc2, hpf_freq, 0, FILTER_HPF6);
			break;
		case 8: // fuzz
			info->curve1 = 0.5;
			info->curve2 = 0.27;
			info->do_od1 = do_clipping_var6;
			info->do_od2 = do_clipping_var_dummy;
			init_sample_filter(&info->od_fc1, hpf_freq, 0, FILTER_HPF6);
			init_sample_filter(&info->od_fc2, hpf_freq, 0, FILTER_HPF6);
			break;
		}
		switch(play_system_mode){
		default:
		case 0x41: // GS_SYSTEM_MODE
			lpf_freq = info->tone * otd.gsefx_CustomODFreq;	
			info->drived = sqrt(info->drive * DISTORTION_GAIN) * otd.gsefx_CustomODDrive;
			info->leveld = info->level * DISTORTION_LEVEL * ins_level * otd.gsefx_CustomODLv;
			break;
		case 0x43: // XG_SYSTEM_MODE
			lpf_freq = info->tone * otd.xgefx_CustomODFreq;
			info->drived = sqrt(info->drive * DISTORTION_GAIN) * otd.xgefx_CustomODDrive;
			info->leveld = info->level * DISTORTION_LEVEL * ins_level * otd.xgefx_CustomODLv;
			break;
		case 0x7d: // GM2_SYSTEM_MODE
		case 0x60: // SD_SYSTEM_MODE
			lpf_freq = info->tone * otd.sdefx_CustomODFreq;
			info->drived = sqrt(info->drive * DISTORTION_GAIN) * otd.sdefx_CustomODDrive;
			info->leveld = info->level * DISTORTION_LEVEL * ins_level * otd.sdefx_CustomODLv;
			break;
		}		
		init_sample_filter(&info->od_fc3, lpf_freq, 0, FILTER_LPF12_2);
		return;
	}else if(count <= 0)
		return;
	switch(info->mode){
	case CH_STEREO:
		for(i = 0; i < count; i++) {
			DATA_T input_d[2] = {buf[i] * div_ins_level, buf[i + 1] * div_ins_level};
			/* od_ds */
			sample_filter_stereo2(&info->od_fc1, input_d);
			info->do_od1(&input_d[0], info->drived, info->curve1);
			info->do_od1(&input_d[1], info->drived, info->curve1);
			sample_filter_stereo2(&info->od_fc2, input_d);
			info->do_od2(&input_d[0], info->drived, info->curve2);
			info->do_od2(&input_d[1], info->drived, info->curve2);
			sample_filter_stereo2(&info->od_fc3, input_d);
			/* mixing */
			buf[i] = input_d[0] * info->leveld;
			++i;
			buf[i] = input_d[1] * info->leveld;
		}
		break;
	case CH_MIX_STEREO:
	case CH_MIX_MONO:
		for(i = 0; i < count; i++) {
			input = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL * div_ins_level;
			/* od_ds */
			sample_filter_left(&info->od_fc1, &input);
			info->do_od1(&input, info->drived, info->curve1);
			sample_filter_left(&info->od_fc2, &input);
			info->do_od2(&input, info->drived, info->curve2);
			sample_filter_left(&info->od_fc3, &input);
			/* mixing */
			input *= info->leveld;
			buf[i] = input;
			++i;
			buf[i] = input;
		}
		break;
	case CH_MONO:
		for(i = 0; i < count; i++) {
			input = buf[i] * div_ins_level;
			/* od_ds */
			sample_filter_left(&info->od_fc1, &input);
			info->do_od1(&input, info->drived, info->curve1);
			sample_filter_left(&info->od_fc2, &input);
			info->do_od2(&input, info->drived, info->curve2);
			sample_filter_left(&info->od_fc3, &input);
			/* panning */
			input *= info->leveld;
			buf[i] = input;
			++i;
			buf[i] = input;
		}
		break;
	case CH_LEFT:
		for(i = 0; i < count; i++) {
			input = buf[i] * div_ins_level;
			/* od_ds */
			sample_filter_left(&info->od_fc1, &input);
			info->do_od1(&input, info->drived, info->curve1);
			sample_filter_left(&info->od_fc2, &input);
			info->do_od2(&input, info->drived, info->curve2);
			sample_filter_left(&info->od_fc3, &input);
			/* panning */
			buf[i] = input * info->leveld;// + high
			i++;
		}
		break;
	case CH_RIGHT:
		for(i = 0; i < count; i++) {
			i++;
			input = buf[i] * div_ins_level;
			/* od_ds */
			sample_filter_right(&info->od_fc1, &input);
			info->do_od1(&input, info->drived, info->curve1);
			sample_filter_right(&info->od_fc2, &input);
			info->do_od2(&input, info->drived, info->curve2);
			sample_filter_right(&info->od_fc3, &input);
			/* panning */
			buf[i] = input * info->leveld;// + high
		}
		break;
	}

}

#define AMP_SIM_GAIN1 (8.0)
#define AMP_SIM_GAIN2 (4.0)
#define AMP_SIM_EQ_GAIN (0.25)
#define AMP_SIM_LEVEL (2.0 * DIV_4)
#define CABINET_FCT (0.0029411764705882352941176470588235)
#define CABNET_DELAY_SIZE (M_12BIT)
#define CABNET_DELAY_MASK (M_12BIT - 1)
#define CABNET_DELAY_COEF (0.86)

static void do_amp_simulator(DATA_T *buf, int32 count, InfoAmpSimulator *info)
{
	int32 i, j;
	DATA_T hpf_freq, lpf_freq;
	const DATA_T phase[] = {-0.7, 0.5, -0.4,};

	if(count == MAGIC_INIT_EFFECT_INFO) {
		double tmp, mcnt = (double)play_mode->rate * CABINET_FCT * CABNET_DELAY_COEF;

		//info->cab_sw = 0;
		if(!info->init){
			// CABNET_DELAY_SIZE : max 384kHz 2.21ms 2ch 
			int32 byte = sizeof(DATA_T) * CABNET_DELAY_SIZE;
#ifdef ALIGN_SIZE
			info->ptr1 = (DATA_T *)aligned_malloc(byte, ALIGN_SIZE);
			info->ptr2 = (DATA_T *)aligned_malloc(byte, ALIGN_SIZE);
			info->ptr3 = (DATA_T *)aligned_malloc(byte, ALIGN_SIZE);
#else
			info->ptr1 = (DATA_T *)safe_malloc(byte);
			info->ptr2 = (DATA_T *)safe_malloc(byte);
			info->ptr3 = (DATA_T *)safe_malloc(byte);
#endif
			if(info->ptr1)
				memset(info->ptr1, 0, byte);
			if(info->ptr2)
				memset(info->ptr2, 0, byte);
			if(info->ptr3)
				memset(info->ptr3, 0, byte);
			info->init = 1;
		}
		switch(info->amp_type){
		case 0: // off
			info->gain1d = 1.0;
			info->gain2d = 1.0;
			info->curve1 = info->curve2 = info->curve3 = 1.0;
			info->do_amp1 = do_clipping_var_dummy;
			info->do_amp2 = do_clipping_var_dummy;
			info->do_amp3 = do_clipping_var_dummy;
			init_sample_filter(&info->amp_fc1, 0, 0, FILTER_NONE);
			init_sample_filter(&info->amp_fc2, 0, 0, FILTER_NONE);
			init_sample_filter(&info->amp_fc3, 0, 0, FILTER_NONE);
			break;
		default:
		case 1: // jc120
			info->gain1d = sqrt(info->gain1 * 2.0);
			info->gain2d = sqrt(info->gain2 * 2.0);
			info->curve1 = 0.50;
			info->curve2 = 0.55;
			info->curve3 = 0.50;
			info->do_amp1 = do_clipping_var1;
			info->do_amp2 = do_clipping_var1;
			info->do_amp3 = do_clipping_var1;
			init_sample_filter(&info->amp_fc1, 180, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 580, 0, FILTER_HPF6);
			init_sample_filter2(&info->amp_fc3, 8000, 1.0, 0, FILTER_SHELVING_HI);
			break;
		case 2: // clean twin
			info->gain1d = sqrt(info->gain1 * 2.0);
			info->gain2d = sqrt(info->gain2 * 2.0);
			info->curve1 = 0.70;
			info->curve2 = 0.50;
			info->curve3 = 0.70;
			info->do_amp1 = do_clipping_var1;
			info->do_amp2 = do_clipping_var1;
			info->do_amp3 = do_clipping_var2;
			init_sample_filter(&info->amp_fc1, 80, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 580, 0, FILTER_HPF6);
			init_sample_filter2(&info->amp_fc3, 4000, 1.0, 0, FILTER_PEAKING);
			break;
		case 3: // match drive
			info->gain1d = sqrt(info->gain1 * 2.0);
			info->gain2d = sqrt(info->gain2 * 2.0);
			info->curve1 = 0.95;
			info->curve2 = 0.90;
			info->curve3 = 0.90;
			info->do_amp1 = do_clipping_var1;
			info->do_amp2 = do_clipping_var1;
			info->do_amp3 = do_clipping_var2;
			init_sample_filter(&info->amp_fc1, 100, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 980, 0, FILTER_HPF6);
			init_sample_filter2(&info->amp_fc3, 5000, 3.0, 0, FILTER_PEAKING);
			break;
		case 4: // bg lead
			info->gain1d = sqrt(info->gain1 * 4.0);
			info->gain2d = sqrt(info->gain2 * 2.0);
			info->curve1 = 0.95;
			info->curve2 = 0.50;
			info->curve3 = 0.50;
			info->do_amp1 = do_clipping_var2;
			info->do_amp2 = do_clipping_var1;
			info->do_amp3 = do_clipping_var2;
			init_sample_filter(&info->amp_fc1, 150, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 1580, 0, FILTER_HPF6);
			init_sample_filter2(&info->amp_fc3, 3000, 3.0, 0, FILTER_PEAKING);
			break;
		case 5: // ms1959I
			info->gain1d = sqrt(info->gain1 * 4.0);
			info->gain2d = sqrt(info->gain2 * 2.0);
			info->curve1 = 0.95;
			info->curve2 = 0.50;
			info->curve3 = 0.50;
			info->do_amp1 = do_clipping_var2;
			info->do_amp2 = do_clipping_var1;
			info->do_amp3 = do_clipping_var2;
			init_sample_filter(&info->amp_fc1, 150, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 1580, 0, FILTER_HPF6);
			init_sample_filter2(&info->amp_fc3, 4000, 3.0, 0, FILTER_PEAKING);
			break;
		case 6: // ms1959II
			info->gain1d = sqrt(info->gain1 * 4.5);
			info->gain2d = sqrt(info->gain2 * 2.0);
			info->curve1 = 0.95;
			info->curve2 = 0.50;
			info->curve3 = 0.50;
			info->do_amp1 = do_clipping_var2;
			info->do_amp2 = do_clipping_var1;
			info->do_amp3 = do_clipping_var2;
			init_sample_filter(&info->amp_fc1, 150, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 2580, 0, FILTER_HPF6);
			init_sample_filter2(&info->amp_fc3, 5000, 3.0, 0, FILTER_PEAKING);
			break;
		case 7: // ms1959I+II
			info->gain1d = sqrt(info->gain1 * 5.0);
			info->gain2d = sqrt(info->gain2 * 2.0);
			info->curve1 = 0.99;
			info->curve2 = 0.99;
			info->curve3 = 0.80;
			info->do_amp1 = do_clipping_var2;
			info->do_amp2 = do_clipping_var1;
			info->do_amp3 = do_clipping_var2;
			init_sample_filter(&info->amp_fc1, 150, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 2580, 0, FILTER_HPF6);
			init_sample_filter2(&info->amp_fc3, 4500, 3.0, 0, FILTER_PEAKING);
			break;
		case 8: // sldn lead
			info->gain1d = sqrt(info->gain1 * 7.0);
			info->gain2d = sqrt(info->gain2 * 3.0);
			info->curve1 = 0.75;
			info->curve2 = 0.80;
			info->curve3 = 0.80;
			info->do_amp1 = do_clipping_var3;
			info->do_amp2 = do_clipping_var2;
			info->do_amp3 = do_clipping_var3;
			init_sample_filter(&info->amp_fc1, 180, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 3580, 0, FILTER_HPF6);
			init_sample_filter2(&info->amp_fc3, 2500, 6.0, 0, FILTER_SHELVING_HI);
			break;
		case 9: // metal5150
			info->gain1d = sqrt(info->gain1 * 8.0);
			info->gain2d = sqrt(info->gain2 * 4.0);
			info->curve1 = 0.75;
			info->curve2 = 0.70;
			info->curve3 = 0.50;
			info->do_amp1 = do_clipping_var3;
			info->do_amp2 = do_clipping_var4;
			info->do_amp3 = do_clipping_var3;
			init_sample_filter(&info->amp_fc1, 150, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 4580, 0, FILTER_HPF6);
			init_sample_filter2(&info->amp_fc3, 3500, 6.0, 0, FILTER_SHELVING_HI);
			break;
		case 10: // metal lead
			info->gain1d = sqrt(info->gain1 * 8.0);
			info->gain2d = sqrt(info->gain2 * 4.0);
			info->curve1 = 0.95;
			info->curve2 = 0.90;
			info->curve3 = 0.50;
			info->do_amp1 = do_clipping_var3;
			info->do_amp2 = do_clipping_var4;
			info->do_amp3 = do_clipping_var4;
			init_sample_filter(&info->amp_fc1, 150, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 4580, 0, FILTER_HPF6);
			init_sample_filter2(&info->amp_fc3, 4500, 6.0, 0, FILTER_SHELVING_HI);
			break;
		case 11: // OD-1
			info->gain1d = sqrt(info->gain1 * 2.0);
			info->gain2d = sqrt(info->gain2 * 2.0);
			info->curve1 = 0.50;
			info->curve2 = 0.30;
			info->curve3 = 0.30;
			info->do_amp1 = do_clipping_var3;
			info->do_amp2 = do_clipping_var_dummy;
			info->do_amp3 = do_clipping_var2;
			init_sample_filter(&info->amp_fc1, 120, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 0, 0, FILTER_NONE);
			init_sample_filter(&info->amp_fc3, 120, 0, FILTER_HPF6);
			break;
		case 12: // OD-2 turbo
			info->gain1d = sqrt(info->gain1 * 3.0);
			info->gain2d = sqrt(info->gain2 * 2.0);
			info->curve1 = 0.50;
			info->curve2 = 0.70;
			info->curve3 = 0.70;
			info->do_amp1 = do_clipping_var3;
			info->do_amp2 = do_clipping_var_dummy;
			info->do_amp3 = do_clipping_var2;
			init_sample_filter(&info->amp_fc1, 110, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 0, 0, FILTER_NONE);
			init_sample_filter(&info->amp_fc3, 110, 0, FILTER_HPF6);
			break;
		case 13: // distortion
			info->gain1d = sqrt(info->gain1 * 4.0);
			info->gain2d = sqrt(info->gain2 * 2.0);
			info->curve1 = 0.70;
			info->curve2 = 0.50;
			info->curve3 = 0.70;
			info->do_amp1 = do_clipping_var4;
			info->do_amp2 = do_clipping_var_dummy;
			info->do_amp3 = do_clipping_var4;
			init_sample_filter(&info->amp_fc1, 150, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 0, 0, FILTER_NONE);
			init_sample_filter(&info->amp_fc3, 110, 0, FILTER_HPF6);
			break;
		case 14: // fuzz
			info->gain1d = sqrt(info->gain1 * 6.0);
			info->gain2d = sqrt(info->gain2 * 2.0);
			info->curve1 = 0.90;
			info->curve2 = 0.80;
			info->curve3 = 0.80;
			info->do_amp1 = do_clipping_var6;
			info->do_amp2 = do_clipping_var_dummy;
			info->do_amp3 = do_clipping_var2;
			init_sample_filter(&info->amp_fc1, 150, 0, FILTER_HPF6);
			init_sample_filter(&info->amp_fc2, 0, 0, FILTER_NONE);
			init_sample_filter2(&info->amp_fc3, 2500, 3.0, 0, FILTER_PEAKING);
			break;
		}
		switch(play_system_mode){
		default:
		case 0x41: // GS_SYSTEM_MODE
			lpf_freq = info->tone * otd.gsefx_CustomODFreq;	
			info->gain1d *= otd.gsefx_CustomODDrive;
			info->gain2d *= otd.gsefx_CustomODDrive;
			info->leveld = info->level * AMP_SIM_LEVEL * ins_level * otd.gsefx_CustomODLv;
			break;
		case 0x43: // XG_SYSTEM_MODE
			lpf_freq = info->tone * otd.xgefx_CustomODFreq;
			info->gain1d *= otd.xgefx_CustomODDrive;
			info->gain2d *= otd.xgefx_CustomODDrive;
			info->leveld = info->level * AMP_SIM_LEVEL * ins_level * otd.xgefx_CustomODLv;
			break;
		case 0x7d: // GM2_SYSTEM_MODE
		case 0x60: // SD_SYSTEM_MODE
			lpf_freq = info->tone * otd.sdefx_CustomODFreq;
			info->gain1d *= otd.sdefx_CustomODDrive;
			info->gain2d *= otd.sdefx_CustomODDrive;
			info->leveld = info->level * AMP_SIM_LEVEL * ins_level * otd.sdefx_CustomODLv;
			break;
		}
		init_sample_filter(&info->amp_fc4, lpf_freq, 0, FILTER_LPF6);
		init_sample_filter2(&info->eq_fc1, 500, info->eq1_gain * AMP_SIM_EQ_GAIN, 0, info->eq1_gain ? FILTER_PEAKING : FILTER_NONE);
		init_sample_filter2(&info->eq_fc2, 2200, info->eq2_gain * AMP_SIM_EQ_GAIN, 0, info->eq2_gain ? FILTER_PEAKING : FILTER_NONE);
		init_sample_filter2(&info->eq_fc3, 4500, info->eq3_gain * AMP_SIM_EQ_GAIN, 0, info->eq3_gain ? FILTER_PEAKING : FILTER_NONE);
		init_sample_filter2(&info->eq_fc4, 9300, info->eq4_gain * AMP_SIM_EQ_GAIN, 0, info->eq4_gain ? FILTER_PEAKING : FILTER_NONE);
		switch(info->cab_type){
		default:
		case 0: // off	// other
			info->speaker_num = 1;
			info->stack_num = 1;
			info->offset1 = 0; // back
			init_sample_filter(&info->cab_fc1, 0, 0, FILTER_NONE); // speaker
			init_sample_filter(&info->cab_fc2, 0, 0, FILTER_NONE); // open/close
			init_sample_filter(&info->cab_fc3, 0, 0, FILTER_NONE); // mic
			break;
		case 1: // small1
			info->speaker_num = 1;
			info->stack_num = 1;
			info->offset1 = mcnt * 0.5; // back
			init_sample_filter(&info->cab_fc1, 8500, 0, FILTER_LPF12_2); // speaker
			init_sample_filter(&info->cab_fc2, 1500, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 15000, 0, FILTER_LPF12_2); // mic
			break;
		case 2: // small2
			info->speaker_num = 1;
			info->stack_num = 1;
			info->offset1 = mcnt * 0.55; // back
			init_sample_filter(&info->cab_fc1, 8500, 0, FILTER_LPF12_2); // speaker
			init_sample_filter(&info->cab_fc2, 1500, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 15000, 0, FILTER_LPF12_2); // mic
			break;
		case 3: // middle
			info->speaker_num = 1;
			info->stack_num = 1;
			info->offset1 = mcnt * 0.6; // back
			init_sample_filter(&info->cab_fc1, 6000, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 1500, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 15000, 0, FILTER_LPF12_2); // mic
			break;
		case 4: // jc-120
			info->speaker_num = 2;
			info->stack_num = 1;
			info->offset1 = mcnt * 0.6; // back
			info->offset2[0] = mcnt * 0.37; // cab size
			init_sample_filter(&info->cab_fc1, 6000, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 1500, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 15000, 0, FILTER_LPF12_2); // mic
			break;
		case 5: // built-in1
			info->speaker_num = 2;
			info->stack_num = 1;
			info->offset1 = mcnt * 0.5; // back
			info->offset2[0] = mcnt * 0.36; // cab size
			init_sample_filter(&info->cab_fc1, 6000, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 1500, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 15000, 0, FILTER_LPF12_2); // mic
			break;
		case 6: // built-in2
			info->speaker_num = 2;
			info->stack_num = 1;
			info->offset1 = mcnt * 0.5; // back
			info->offset2[0] = mcnt * 0.38; // cab size
			init_sample_filter(&info->cab_fc1, 6000, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 1500, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 19000, 0, FILTER_LPF6); // mic
			break;
		case 7: // built-in3
			info->speaker_num = 2;
			info->stack_num = 1;
			info->offset1 = mcnt * 0.55; // back
			info->offset2[0] = mcnt * 0.40; // cab size
			init_sample_filter(&info->cab_fc1, 6000, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 1500, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 19000, 0, FILTER_LPF6); // mic
			break;
		case 8: // built-in4
			info->speaker_num = 2;
			info->stack_num = 1;
			info->offset1 = mcnt * 0.55; // back
			info->offset2[0] = mcnt * 0.42; // cab size
			init_sample_filter(&info->cab_fc1, 6000, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 1500, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 19000, 0, FILTER_LPF6); // mic
			break;
		case 9: // built-in5
			info->speaker_num = 2;
			info->stack_num = 1;
			info->offset1 = mcnt * 0.6; // back
			info->offset2[0] = mcnt * 0.46; // cab size
			init_sample_filter(&info->cab_fc1, 6000, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 1500, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 19000, 0, FILTER_LPF6); // mic
			break;
		case 10: // bg stack1
			info->speaker_num = 2;
			info->stack_num = 1;
			info->offset1 = mcnt * 0.3; // back
			info->offset2[0] = mcnt * 0.36; // cab size
			init_sample_filter(&info->cab_fc1, 6000, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 600, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 19000, 0, FILTER_LPF6); // mic
			break;
		case 11: // bg stack2
			info->speaker_num = 2;
			info->stack_num = 1;
			info->offset1 = mcnt * 0.3; // back
			info->offset2[0] = mcnt * 0.42; // cab size
			init_sample_filter(&info->cab_fc1, 5000, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 600, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 19000, 0, FILTER_LPF6); // mic
			break;
		case 12: // ms stack1
			info->speaker_num = 4;
			info->stack_num = 1;
			info->offset1 = mcnt * 0.35; // back
			info->offset2[0] = mcnt * 0.36; // cab size
			info->offset2[1] = mcnt * 0.38; // cab size
			info->offset2[2] = mcnt * 0.54; // cab size
			init_sample_filter(&info->cab_fc1, 6000, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 600, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 19000, 0, FILTER_LPF6); // mic
			break;
		case 13: // ms stack2
			info->speaker_num = 4;
			info->stack_num = 1;
			info->offset1 = mcnt * 0.35; // back
			info->offset2[0] = mcnt * 0.37; // cab size
			info->offset2[1] = mcnt * 0.39; // cab size
			info->offset2[2] = mcnt * 0.54; // cab size
			init_sample_filter(&info->cab_fc1, 6000, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 600, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 19000, 0, FILTER_LPF6); // mic
			break;
		case 14: // metal stack
			info->speaker_num = 4;
			info->stack_num = 2;
			info->offset1 = mcnt * 0.4; // back
			info->offset2[0] = mcnt * 0.39; // cab size
			info->offset2[1] = mcnt * 0.41; // cab size
			info->offset2[2] = mcnt * 0.57; // cab size
			info->offset3[0] = mcnt * 0.89; // cab tall
			init_sample_filter(&info->cab_fc1, 5500, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 600, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 19000, 0, FILTER_LPF6); // mic
			break;
		case 15: // 2stack
			info->speaker_num = 4;
			info->stack_num = 2;
			info->offset1 = mcnt * 0.35; // back
			info->offset2[0] = mcnt * 0.37; // cab size
			info->offset2[1] = mcnt * 0.39; // cab size
			info->offset2[2] = mcnt * 0.54; // cab size
			info->offset3[0] = mcnt * 0.85; // cab tall
			init_sample_filter(&info->cab_fc1, 6000, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 600, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 19000, 0, FILTER_LPF6); // mic
			break;
		case 16: // 3stack
			info->speaker_num = 4;
			info->stack_num = 3;
			info->offset1 = mcnt * 0.35; // back
			info->offset2[0] = mcnt * 0.37; // cab size
			info->offset2[1] = mcnt * 0.39; // cab size
			info->offset2[2] = mcnt * 0.54; // cab size
			info->offset3[0] = mcnt * 0.85; // cab tall
			info->offset3[1] = mcnt * 1.70; // cab tall
			init_sample_filter(&info->cab_fc1, 6000, 0, FILTER_LPF_BW); // speaker
			init_sample_filter(&info->cab_fc2, 600, 0, FILTER_LPF6); // open/close
			init_sample_filter(&info->cab_fc3, 19000, 0, FILTER_LPF6); // mic
			break;
		}	
		info->offset1 *= 2;
		for(j = 1; j < info->speaker_num - 1; j++)
			info->offset2[j] *= 2;
		for(j = 1; j < info->stack_num - 1; j++)
			info->offset3[j] *= 2;
		tmp = sqrt((double)info->mic_pos * DIV_4);
		info->flevel = 1.0 - tmp * 0.5;
		info->blevel = tmp;	
		info->mwet = info->mic_level;
		info->mdry = info->mic_direct;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		if(info->ptr1){
#ifdef ALIGN_SIZE
			aligned_free(info->ptr1);	
#else
			safe_free(info->ptr1);	
#endif
			info->ptr1 = NULL;
		}
		if(info->ptr2){
#ifdef ALIGN_SIZE
			aligned_free(info->ptr2);	
#else
			safe_free(info->ptr2);	
#endif
			info->ptr2 = NULL;
		}
		if(info->ptr3){
#ifdef ALIGN_SIZE
			aligned_free(info->ptr3);	
#else
			safe_free(info->ptr3);	
#endif
			info->ptr3 = NULL;
		}
		info->init = 0;
		return;
	} else if(count <= 0) {
		return;
	}	
	switch(info->mode){
	case CH_STEREO:
		for(i = 0; i < count; i++) {
			int32 indexL, indexR;
			DATA_T tmp_d[2], input_d[2] = {buf[i] * div_ins_level, buf[i + 1] * div_ins_level};
			/* pre_amp */
			if(info->amp_sw){
				tmp_d[0] = input_d[0];
				tmp_d[1] = input_d[1];
				sample_filter_stereo2(&info->amp_fc1, input_d);
				info->do_amp1(&input_d[0], info->gain1d, info->curve1);
				info->do_amp1(&input_d[1], info->gain1d, info->curve1);
				sample_filter_stereo2(&info->amp_fc2, tmp_d);
				info->do_amp2(&tmp_d[0], info->gain1d, info->curve2);
				info->do_amp2(&tmp_d[1], info->gain1d, info->curve2);
				input_d[0] += tmp_d[0];
				input_d[1] += tmp_d[1];
				sample_filter_stereo2(&info->amp_fc3, input_d);	
				info->do_amp3(&input_d[0], info->gain2d, info->curve3);
				info->do_amp3(&input_d[1], info->gain2d, info->curve3);
				sample_filter_stereo2(&info->amp_fc4, input_d);			
				sample_filter_stereo2(&info->eq_fc1, input_d);
				sample_filter_stereo2(&info->eq_fc2, input_d);
				sample_filter_stereo2(&info->eq_fc3, input_d);
				sample_filter_stereo2(&info->eq_fc4, input_d);
			}
			/* cabinet */	
			if(info->cab_sw){
				indexL = info->index = (info->index + 2) & CABNET_DELAY_MASK;
				indexR = indexL + 1;
				sample_filter_stereo2(&info->cab_fc1, input_d);
				tmp_d[0] = input_d[0]; 
				tmp_d[1] = input_d[1]; 			
				sample_filter_stereo2(&info->cab_fc2, tmp_d);
				info->ptr1[indexL] = tmp_d[0]; 
				info->ptr1[indexR] = tmp_d[1];				
				input_d[0] = input_d[0] * info->flevel + info->ptr1[(indexL - info->offset1) & CABNET_DELAY_MASK] * info->blevel;
				input_d[1] = input_d[1] * info->flevel + info->ptr1[(indexR - info->offset1) & CABNET_DELAY_MASK] * info->blevel;			
				info->ptr2[indexL] = input_d[0]; 
				info->ptr2[indexR] = input_d[1]; 	
				for(j = 0; j < info->speaker_num - 1; j++){
					input_d[0] += info->ptr2[(indexL - info->offset2[j]) & CABNET_DELAY_MASK] * phase[j];
					input_d[1] += info->ptr2[(indexR - info->offset2[j]) & CABNET_DELAY_MASK] * phase[j];
				}	
				info->ptr3[indexL] = input_d[0]; 
				info->ptr3[indexR] = input_d[1];
				for(j = 0; j < info->stack_num - 1; j++){
					input_d[0] += info->ptr3[(indexL - info->offset3[j]) & CABNET_DELAY_MASK] * phase[j];
					input_d[1] += info->ptr3[(indexR - info->offset3[j]) & CABNET_DELAY_MASK] * phase[j];
				}	
				tmp_d[0] = input_d[0]; 
				tmp_d[1] = input_d[1]; 				
				sample_filter_stereo2(&info->cab_fc3, tmp_d);
				input_d[0] = tmp_d[0] * info->mwet + input_d[0] * info->mdry;
				input_d[1] = tmp_d[1] * info->mwet + input_d[1] * info->mdry;
			}
			/* mixing */
			buf[i] = input_d[0] * info->leveld;
			++i;
			buf[i] = input_d[1] * info->leveld;
		}
		break;
	case CH_MIX_STEREO:
	case CH_MIX_MONO:
		for(i = 0; i < count; i++) {
			int32 indexL;
			DATA_T tmp, input = (buf[i] + buf[i + 1]) * DIV_MIX_LEVEL * div_ins_level;
			/* pre_amp */
			if(info->amp_sw){
				tmp = input;
				sample_filter_left(&info->amp_fc1, &input);
				info->do_amp1(&input, info->gain1d, info->curve1);
				sample_filter_left(&info->amp_fc2, &tmp);
				info->do_amp2(&tmp, info->gain1d, info->curve2);
				input += tmp;
				sample_filter_left(&info->amp_fc3, &input);	
				info->do_amp3(&input, info->gain2d, info->curve3);
				sample_filter_left(&info->amp_fc4, &input);			
				sample_filter_left(&info->eq_fc1, &input);
				sample_filter_left(&info->eq_fc2, &input);
				sample_filter_left(&info->eq_fc3, &input);
				sample_filter_left(&info->eq_fc4, &input);
			}
			/* cabinet */	
			if(info->cab_sw){
				indexL = info->index = (info->index + 2) & CABNET_DELAY_MASK;
				sample_filter_left(&info->cab_fc1, &input);
				tmp = input; 			
				sample_filter_left(&info->cab_fc2, &tmp);
				info->ptr1[indexL] = tmp; 			
				input = input * info->flevel + info->ptr1[(indexL - info->offset1) & CABNET_DELAY_MASK] * info->blevel;		
				info->ptr2[indexL] = input; 
				for(j = 0; j < info->speaker_num - 1; j++)
					input += info->ptr2[(indexL - info->offset2[j]) & CABNET_DELAY_MASK] * phase[j];
				info->ptr3[indexL] = input; 
				for(j = 0; j < info->stack_num - 1; j++)
					input += info->ptr3[(indexL - info->offset3[j]) & CABNET_DELAY_MASK] * phase[j];
				sample_filter_left(&info->cab_fc3, &input);
				tmp = input; 	
				sample_filter_left(&info->cab_fc3, &tmp);
				input = tmp * info->mwet + input * info->mdry;
			}
			/* mixing */
			input *= info->leveld;
			buf[i] = input;
			++i;
			buf[i] = input;
		}
		break;
	case CH_MONO:
		for(i = 0; i < count; i++) {
			int32 indexL;
			DATA_T tmp, input = buf[i] * div_ins_level;
			/* pre_amp */
			if(info->amp_sw){
				tmp = input;
				sample_filter_left(&info->amp_fc1, &input);
				info->do_amp1(&input, info->gain1d, info->curve1);
				sample_filter_left(&info->amp_fc2, &tmp);
				info->do_amp2(&tmp, info->gain1d, info->curve2);
				input += tmp;
				sample_filter_left(&info->amp_fc3, &input);
				info->do_amp3(&input, info->gain2d, info->curve3);
				sample_filter_left(&info->amp_fc4, &input);
				sample_filter_left(&info->eq_fc1, &input);
				sample_filter_left(&info->eq_fc2, &input);
				sample_filter_left(&info->eq_fc3, &input);
				sample_filter_left(&info->eq_fc4, &input);
			}
			/* cabinet */	
			if(info->cab_sw){
				indexL = info->index = (info->index + 2) & CABNET_DELAY_MASK;
				sample_filter_left(&info->cab_fc1, &input);
				tmp = input; 			
				sample_filter_left(&info->cab_fc2, &tmp);
				info->ptr1[indexL] = tmp; 			
				input = input * info->flevel + info->ptr1[(indexL - info->offset1) & CABNET_DELAY_MASK] * info->blevel;		
				info->ptr2[indexL] = input; 
				for(j = 0; j < info->speaker_num - 1; j++)
					input += info->ptr2[(indexL - info->offset2[j]) & CABNET_DELAY_MASK] * phase[j];
				info->ptr3[indexL] = input; 
				for(j = 0; j < info->stack_num - 1; j++)
					input += info->ptr3[(indexL - info->offset3[j]) & CABNET_DELAY_MASK] * phase[j];
				sample_filter_left(&info->cab_fc3, &input);
				tmp = input; 	
				sample_filter_left(&info->cab_fc3, &tmp);
				input = tmp * info->mwet + input * info->mdry;
			}
			/* panning */
			input *= info->leveld;
			buf[i] = input;
			++i;
			buf[i] = input;
		}
		break;
	case CH_LEFT:
		for(i = 0; i < count; i++) {
			int32 indexL;
			DATA_T tmp, input = buf[i] * div_ins_level;
			/* pre_amp */
			if(info->amp_sw){
				tmp = input;
				sample_filter_left(&info->amp_fc1, &input);
				info->do_amp1(&input, info->gain1d, info->curve1);
				sample_filter_left(&info->amp_fc2, &tmp);
				info->do_amp2(&tmp, info->gain1d, info->curve2);
				input += tmp;
				sample_filter_left(&info->amp_fc3, &input);
				info->do_amp3(&input, info->gain2d, info->curve3);
				sample_filter_left(&info->amp_fc4, &input);
				sample_filter_left(&info->eq_fc1, &input);
				sample_filter_left(&info->eq_fc2, &input);
				sample_filter_left(&info->eq_fc3, &input);
				sample_filter_left(&info->eq_fc4, &input);
			}
			/* cabinet */	
			if(info->cab_sw){
				indexL = info->index = (info->index + 2) & CABNET_DELAY_MASK;
				sample_filter_left(&info->cab_fc1, &input);
				tmp = input; 			
				sample_filter_left(&info->cab_fc2, &tmp);
				info->ptr1[indexL] = tmp; 			
				input = input * info->flevel + info->ptr1[(indexL - info->offset1) & CABNET_DELAY_MASK] * info->blevel;		
				info->ptr2[indexL] = input; 
				for(j = 0; j < info->speaker_num - 1; j++)
					input += info->ptr2[(indexL - info->offset2[j]) & CABNET_DELAY_MASK] * phase[j];
				info->ptr3[indexL] = input; 
				for(j = 0; j < info->stack_num - 1; j++)
					input += info->ptr3[(indexL - info->offset3[j]) & CABNET_DELAY_MASK] * phase[j];
				sample_filter_left(&info->cab_fc3, &input);
				tmp = input; 	
				sample_filter_left(&info->cab_fc3, &tmp);
				input = tmp * info->mwet + input * info->mdry;
			}
			/* panning */
			buf[i] = input * info->leveld;
			i++;
		}
		break;
	case CH_RIGHT:
		for(i = 0; i < count; i++) {
			int32 indexR;
			DATA_T tmp, input;
			i++;
			input = buf[i] * div_ins_level;
			/* pre_amp */
			if(info->amp_sw){
				tmp = input;
				sample_filter_right(&info->amp_fc1, &input);
				info->do_amp1(&input, info->gain1d, info->curve1);
				sample_filter_right(&info->amp_fc2, &tmp);
				info->do_amp2(&tmp, info->gain1d, info->curve2);
				input += tmp;
				sample_filter_right(&info->amp_fc3, &input);
				info->do_amp3(&input, info->gain2d, info->curve3);
				sample_filter_right(&info->amp_fc4, &input);
				sample_filter_left(&info->eq_fc1, &input);
				sample_filter_left(&info->eq_fc2, &input);
				sample_filter_left(&info->eq_fc3, &input);
				sample_filter_left(&info->eq_fc4, &input);
			}
			/* cabinet */	
			if(info->cab_sw){
				indexR = info->index = (info->index + 2) & CABNET_DELAY_MASK;
				sample_filter_right(&info->cab_fc1, &input);
				tmp = input; 			
				sample_filter_right(&info->cab_fc2, &tmp);
				info->ptr1[indexR] = tmp; 			
				input = input * info->flevel + info->ptr1[(indexR - info->offset1) & CABNET_DELAY_MASK] * info->blevel;		
				info->ptr2[indexR] = input; 
				for(j = 0; j < info->speaker_num - 1; j++)
					input += info->ptr2[(indexR - info->offset2[j]) & CABNET_DELAY_MASK] * phase[j];
				info->ptr3[indexR] = input;
				for(j = 01; j < info->stack_num - 1; j++)
					input += info->ptr3[(indexR - info->offset3[j]) & CABNET_DELAY_MASK] * phase[j];
				sample_filter_right(&info->cab_fc3, &input);
				tmp = input; 	
				sample_filter_right(&info->cab_fc3, &tmp);
				input = tmp * info->mwet + input * info->mdry;
			}
			/* panning */
			buf[i] = input * info->leveld;
		}
		break;
	}
}







/************************************** SYSTEM EFFECT **************************************/


/*              */
/*  Dry Signal  */
/*              */
static ALIGN DATA_T direct_buffer[AUDIO_BUFFER_SIZE * 2];
static int32 direct_bufsize = sizeof(direct_buffer);

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
#if defined(IX86CPU) && defined(SUPPORT_ASM_INTEL)
void set_dry_signal(int32 *buf, int32 count)
{
	int32 *dbuf = direct_buffer;
	_asm {
		mov		ecx, [count]
		mov		esi, [buf]
		test		ecx, ecx
		jz		short L2
		mov		edi, [dbuf]
L1:		mov		eax, [esi]
		mov		ebx, [edi]
		add		esi, 4
		add		ebx, eax
		mov		[edi], ebx
		add		edi, 4
		dec		ecx
		jnz		L1
L2:
	}
}
#elif defined(IX86CPU) && defined(SUPPORT_ASM_AT_AND_T)
void set_dry_signal(int32 *buf, int32 count)
{
	int32 *dbuf = direct_buffer;

	__asm__ __volatile__("\
		testl		%%ecx, %%ecx;\
		jz		L2_DRY_%=;\
L1_DRY_%=:	movl		(%%esi), %%eax;\
		movl		(%%edi), %%ebx;\
		addl		$4, %%esi;\
		addl		%%eax, %%ebx;\
		movl		%%ebx, (%%edi);\
		addl		$4, %%edi;\
		decl		%%ecx;\
		jnz		L1_DRY_%=;\
L2_DRY_%=:	"
		: "=S"(buf), "=c"(count), "=D"(dbuf)
		: "0"(buf), "1"(count), "2"(dbuf)
		: "eax", "ebx", "memory"
	);
}
#else
void set_dry_signal(register int32 *buf, int32 n)
{
#if USE_ALTIVEC
  if(is_altivec_available()) {
    v_set_dry_signal(direct_buffer, buf, n);
  } else {
#endif
    register int32 i;
	register int32 *dbuf = direct_buffer;

    for(i = n - 1; i >= 0; i--)
    {
        dbuf[i] += buf[i];
    }
#if USE_ALTIVEC
  }
#endif
}
#endif

#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
void set_dry_signal(DATA_T *buf, int32 n)
{
    int32  i;
	for(i = 0; i < n; i += 8){
		MM256_LS_ADD_PD(&direct_buffer[i], _mm256_load_pd(&buf[i]));
		MM256_LS_ADD_PD(&direct_buffer[i + 4], _mm256_load_pd(&buf[i + 4]));
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
void set_dry_signal(DATA_T *buf, int32 n)
{
    int32  i;
	for(i = 0; i < n; i += 8)
		MM256_LS_ADD_PS(&direct_buffer[i], _mm256_load_ps(&buf[i]));
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
void set_dry_signal(DATA_T *buf, int32 n)
{
    int32  i;
	for(i = 0; i < n; i += 8){
		MM_LS_ADD_PD(&direct_buffer[i], _mm_load_pd(&buf[i]));
		MM_LS_ADD_PD(&direct_buffer[i + 2], _mm_load_pd(&buf[i + 2]));
		MM_LS_ADD_PD(&direct_buffer[i + 4], _mm_load_pd(&buf[i + 4]));
		MM_LS_ADD_PD(&direct_buffer[i + 6], _mm_load_pd(&buf[i + 6]));
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
void set_dry_signal(DATA_T *buf, int32 n)
{
    int32  i;
	for(i = 0; i < n; i += 8){
		MM_LS_ADD_PS(&direct_buffer[i], _mm_load_ps(&buf[i]));
		MM_LS_ADD_PS(&direct_buffer[i + 4], _mm_load_ps(&buf[i + 4]));
	}
}
#else /* floating-point implementation */
void set_dry_signal(DATA_T *buf, int32 n)
{
    int32 i;
	DATA_T *dbuf = direct_buffer;

    for(i = n - 1; i >= 0; i--)
    {
        dbuf[i] += buf[i];
    }
}
#endif /* OPT_MODE != 0 */

///r
void set_dry_signal_int32(int32 *buf, int32 n)
{
    int32 i;
	DATA_T *dbuf = direct_buffer;

    for(i = n - 1; i >= 0; i--)
    {
#ifdef EFFECT_LEVEL_FLOAT // level float
        dbuf[i] += (double)buf[i] * div_int_max;		
#else
        dbuf[i] += (double)buf[i];		
#endif
    }
}


/* XG has "dry level". */
#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
#if defined(IX86CPU) && defined(SUPPORT_ASM_INTEL)
void set_dry_signal_xg(int32 *buf, int32 count, int32 level)
{
	int32 *dbuf = direct_buffer;
	if (!level) { return; }
	level = CONV_LV_16BIT(level);
	_asm {
		mov		ecx, [count]
		mov		esi, [buf]
		mov		ebx, [level]
		test		ecx, ecx
		jz		short L2
		mov		edi, [dbuf]
L1:		mov		eax, [esi]
		imul		ebx
		shr		eax, 16
		shl		edx, 16
		or		eax, edx	/* u */
		mov		edx, [edi]	/* v */
		add		esi, 4		/* u */
		add		edx, eax	/* v */
		mov		[edi], edx	/* u */
		add		edi, 4		/* v */
		dec		ecx		/* u */
		jnz		L1		/* v */
L2:
	}
}
#elif defined(IX86CPU) && defined(SUPPORT_ASM_AT_AND_T)
void set_dry_signal_xg(int32 *buf, int32 count, int32 level)
{
	int32 *dbuf = direct_buffer;

	if (!level) { return; }
	level = CONV_LV_16BIT(level);
	__asm__ __volatile__("\
		testl		%%ecx, %%ecx;\
		jz		L2_DRYXG_%=;\
L1_DRYXG_%=:	movl		(%%esi), %%eax;\
		imull		%%ebx;\
		shrl		$16, %%eax;	/* 16.16 */\
		shll		$16, %%edx;\
		orl		%%edx, %%eax;	/* u */\
		movl		(%%edi), %%edx;	/* v */\
		addl		$4, %%esi;	/* u */\
		addl		%%eax, %%edx;	/* v */\
		movl		%%edx, (%%edi);	/* u */\
		addl		$4, %%edi;	/* v */\
		decl		%%ecx;		/* u */\
		jnz		L1_DRYXG_%=;	/* v */\
L2_DRYXG_%=:	"
		: "=S"(buf), "=c"(count), "=D"(dbuf)
		: "0"(buf), "1"(count), "2"(dbuf), "b"(level)
		: "eax", "edx", "memory"
	);
}
#else
void set_dry_signal_xg(int32 *buf, int32 count, int32 level)
{
	int32 *dbuf = direct_buffer;

	if (level)
	{
		const int32 send_leveli = CONV_LV_16BIT(level);
#if 1
		register const int32 * const ebuf = buf + count;

		do
		{
			(*(dbuf++)) += imuldiv16((*(buf++)), send_leveli);
		} while (buf < ebuf);
#else
		register int32 i;

		for (i = count - 1; i >= 0; i--)
		{
			dbuf[i] += imuldiv16(buf[i], send_leveli);
		}
#endif
	}
}
#endif /* IX86CPU */
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
void set_dry_signal_xg(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
	__m256d send_level = _mm256_set1_pd((double)level * DIV_127);
	for(i = 0; i < n; i += 8){
		MM256_LS_FMA_PD(&direct_buffer[i], _mm256_load_pd(&sbuffer[i]), send_level);
		MM256_LS_FMA_PD(&direct_buffer[i + 4], _mm256_load_pd(&sbuffer[i + 4]), send_level);
	}
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
void set_dry_signal_xg(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
	__m256 send_level = _mm256_set1_ps((float)level * DIV_127);
	for(i = 0; i < n; i += 8){
		MM256_LS_FMA_PS(&direct_buffer[i], _mm256_load_ps(&sbuffer[i]), send_level);
	}
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
void set_dry_signal_xg(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
	__m128d send_level = _mm_set1_pd((double)level * DIV_127);
	for(i = 0; i < n; i += 8){
		MM_LS_FMA_PD(&direct_buffer[i],	_mm_load_pd(&sbuffer[i]), send_level);
		MM_LS_FMA_PD(&direct_buffer[i + 2],	_mm_load_pd(&sbuffer[i + 2]), send_level);
		MM_LS_FMA_PD(&direct_buffer[i + 4],	_mm_load_pd(&sbuffer[i + 4]), send_level);
		MM_LS_FMA_PD(&direct_buffer[i + 6],	_mm_load_pd(&sbuffer[i + 6]), send_level);
	}
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
void set_dry_signal_xg(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
	__m128 send_level = _mm_set_ps1((float)level * DIV_127);
	for(i = 0; i < n; i += 8){
		MM_LS_FMA_PS(&direct_buffer[i], _mm_load_ps(&sbuffer[i]), send_level);
		MM_LS_FMA_PS(&direct_buffer[i + 4], _mm_load_ps(&sbuffer[i + 4]), send_level);
	}
	}
}
#else	/* floating-point implementation */
void set_dry_signal_xg(DATA_T *sbuffer, int32 n, int32 level)
{
    int32 i;
    int32 count = n;
    FLOAT_T send_level;

	if(!level) {return;}
	send_level = (FLOAT_T)level * DIV_127;
    for(i = 0; i < count; i++)
    {
		direct_buffer[i] += sbuffer[i] * send_level;
    }
}
#endif /* OPT_MODE != 0 */

#ifdef SYS_EFFECT_CLIP
void mix_dry_signal(DATA_T *buf, int32 n)
{
	int32 i;
	DATA_T x;
	for (i = 0; i < n; i++) {
		x = direct_buffer[i];
		buf[i] = (x > CLIP_AMP_MAX) ? CLIP_AMP_MAX : (x < CLIP_AMP_MIN) ? CLIP_AMP_MIN : x;
	}
	memset(direct_buffer, 0, sizeof(DATA_T) * n);
}
#else /* SYS_EFFECT_CLIP */
void mix_dry_signal(DATA_T *buf, int32 n)
{
 	memcpy(buf, direct_buffer, sizeof(DATA_T) * n);
	memset(direct_buffer, 0, sizeof(DATA_T) * n);
}
#endif /* SYS_EFFECT_CLIP */



/*                         */
/*      Reverb Effect      */
/*                         */

static ALIGN DATA_T reverb_effect_buffer[AUDIO_BUFFER_SIZE * 2];
static int32 reverb_effect_bufsize = sizeof(reverb_effect_buffer);

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
#if defined(IX86CPU) && defined(SUPPORT_ASM_INTEL)
void set_ch_reverb(int32 *buf, int32 count, int32 level)
{
	int32 *dbuf = reverb_effect_buffer;
	if (!level) { return; }
	level = CONV_LV_24BIT(level);
	_asm {
		mov		ecx, [count]
		mov		esi, [buf]
		mov		ebx, [level]
		test		ecx, ecx
		jz		short L2
		mov		edi, [dbuf]
L1:		mov		eax, [esi]
		imul		ebx
		shr		eax, 24
		shl		edx, 8
		or		eax, edx	/* u */
		mov		edx, [edi]	/* v */
		add		esi, 4		/* u */
		add		edx, eax	/* v */
		mov		[edi], edx	/* u */
		add		edi, 4		/* v */
		dec		ecx		/* u */
		jnz		L1		/* v */
L2:
	}
}
#elif defined(IX86CPU) && defined(SUPPORT_ASM_AT_AND_T)
void set_ch_reverb(int32 *buf, int32 count, int32 level)
{
	int32 *dbuf = reverb_effect_buffer;

	if (!level) { return; }
	level = CONV_LV_24BIT(level);
	__asm__ __volatile__("\
		testl		%%ecx, %%ecx;\
		jz		L2_REVRB_%=;\
L1_REVRB_%=:	movl		(%%esi), %%eax;\
		imull		%%ebx;\
		shrl		$24, %%eax;	/* 8.24 */\
		shll		$8, %%edx;\
		orl		%%edx, %%eax;	/* u */\
		movl		(%%edi), %%edx;	/* v */\
		addl		$4, %%esi;	/* u */\
		addl		%%eax, %%edx;	/* v */\
		movl		%%edx, (%%edi);	/* u */\
		addl		$4, %%edi;	/* v */\
		decl		%%ecx;		/* u */\
		jnz		L1_REVRB_%=;	/* v */\
L2_REVRB_%=:	"
		: "=S"(buf), "=c"(count), "=D"(dbuf)
		: "0"(buf), "1"(count), "2"(dbuf), "b"(level)
		: "eax", "edx", "memory"
	);
}
#else
void set_ch_reverb(int32 *buf, int32 count, int32 level)
{
	register int32 i;
	int32 *dbuf = reverb_effect_buffer;

	if (level)
	{
		const int32 send_leveli = CONV_LV_24BIT(level);
#if 1
		register const int32 * const ebuf = buf + count;

		do
		{
			(*(dbuf++)) += imuldiv24((*(buf++)), send_leveli);
		} while (buf < ebuf);
#else
		for (i = count - 1; i >= 0; i--)
		{
			dbuf[i] += imuldiv24(buf[i], send_leveli);
		}
#endif
	}
}
#endif /* IX86CPU */
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
void set_ch_reverb(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		__m256d send_level = _mm256_set1_pd((double)level * DIV_127);
		for(i = 0; i < n; i += 8){
			MM256_LS_FMA_PD(&reverb_effect_buffer[i], _mm256_load_pd(&sbuffer[i]), send_level);
			MM256_LS_FMA_PD(&reverb_effect_buffer[i + 4], _mm256_load_pd(&sbuffer[i + 4]), send_level);
		}
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
void set_ch_reverb(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		__m256 send_level = _mm256_set1_ps((float)level * DIV_127);
		for(i = 0; i < n; i += 8)
			MM256_LS_FMA_PS(&reverb_effect_buffer[i], _mm256_load_ps(&sbuffer[i]), send_level);
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
void set_ch_reverb(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		__m128d send_level = _mm_set1_pd((double)level * DIV_127);
		for(i = 0; i < n; i += 8){
			MM_LS_FMA_PD(&reverb_effect_buffer[i], _mm_load_pd(&sbuffer[i]), send_level);
			MM_LS_FMA_PD(&reverb_effect_buffer[i + 2], _mm_load_pd(&sbuffer[i + 2]), send_level);
			MM_LS_FMA_PD(&reverb_effect_buffer[i + 4], _mm_load_pd(&sbuffer[i + 4]), send_level);
			MM_LS_FMA_PD(&reverb_effect_buffer[i + 6], _mm_load_pd(&sbuffer[i + 6]), send_level);
		}
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
void set_ch_reverb(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		__m128 send_level = _mm_set_ps1((float)level * DIV_127);
		for(i = 0; i < n; i += 8){
			MM_LS_FMA_PS(&reverb_effect_buffer[i], _mm_load_ps(&sbuffer[i]), send_level);
			MM_LS_FMA_PS(&reverb_effect_buffer[i + 4], _mm_load_ps(&sbuffer[i + 4]), send_level);
		}
	}
}
#else
void set_ch_reverb(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;
	FLOAT_T send_level;

	if(!level) {return;}
    send_level = (FLOAT_T)level * DIV_127;
	for(i = 0; i < n; i++)
    {
        reverb_effect_buffer[i] += sbuffer[i] * send_level;
    }
}
#endif /* OPT_MODE != 0 */


#if (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static inline void mix_reverb_buffer(DATA_T *buf, int32 count)
{
    int32  i;
	for(i = 0; i < count; i += 8){
		MM256_LS_ADD_PD(&buf[i], _mm256_load_pd(&reverb_effect_buffer[i]));
		MM256_LS_ADD_PD(&buf[i + 4], _mm256_load_pd(&reverb_effect_buffer[i + 4]));
	}
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static inline void mix_reverb_buffer(DATA_T *buf, int32 count)
{
    int32  i;
	for(i = 0; i < count; i += 8)
		MM256_LS_ADD_PS(&buf[i], _mm256_load_ps(&reverb_effect_buffer[i]));
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static inline void mix_reverb_buffer(DATA_T *buf, int32 count)
{
    int32  i;
	for(i = 0; i < count; i += 8){
		MM_LS_ADD_PD(&buf[i], _mm_load_pd(&reverb_effect_buffer[i]));
		MM_LS_ADD_PD(&buf[i + 2], _mm_load_pd(&reverb_effect_buffer[i + 2]));
		MM_LS_ADD_PD(&buf[i + 4], _mm_load_pd(&reverb_effect_buffer[i + 4]));
		MM_LS_ADD_PD(&buf[i + 6], _mm_load_pd(&reverb_effect_buffer[i + 6]));
	}
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static inline void mix_reverb_buffer(DATA_T *buf, int32 count)
{
    int32  i;
	for(i = 0; i < count; i += 8){
		MM_LS_ADD_PS(&buf[i], _mm_load_ps(&reverb_effect_buffer[i]));
		MM_LS_ADD_PS(&buf[i + 4], _mm_load_ps(&reverb_effect_buffer[i + 4]));
	}
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#else
static inline void mix_reverb_buffer(DATA_T *buf, int32 count)
{
	int32 i;
	for (i = 0; i < count; i++)
		buf[i] += reverb_effect_buffer[i];
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#endif


/* dummy */
void reverb_rc_event(int rc, int32 val)
{
    switch(rc)
    {
      case RC_CHANGE_REV_EFFB:
        break;
      case RC_CHANGE_REV_TIME:
        break;
    }
}

static void setup_ch_standard_reverb(InfoStandardReverb *info)
{
	info->mode = CH_STEREO;
	info->rev_time_sec = reverb_time_table[reverb_status_gs.time];
	info->rev_rt = gs_revchar_to_rt(reverb_status_gs.character);
//	info->rev_wet = (double)reverb_status_gs.level * DIV_127 * gs_revchar_to_level(reverb_status_gs.character);
	info->rev_wet = calc_gs_level(reverb_status_gs.level) * gs_revchar_to_level(reverb_status_gs.character);
	info->rev_roomsize = gs_revchar_to_roomsize(reverb_status_gs.character);
	info->rev_width = 0.125;
	info->rev_damp = 0.5;
	info->rev_feedback = 0.125;
	info->rev_level = 1.0;
	info->er_time_ms = reverb_status_gs.pre_delay_time;
	info->er_level = 0.25;
}

static void CALLINGCONV do_ch_standard_reverb(DATA_T *buf, int32 count, struct reverb_status_gs_t *rs)
{
	InfoStandardReverb *info = &(rs->info_standard_reverb);
	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_standard_reverb(info);
		do_standard_reverb(buf, count, info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		do_standard_reverb(buf, count, info);
		return;
	} else if(count <= 0) {
		return;
	} 
	do_standard_reverb(buf, count, info);
}

static void do_ch_standard_reverb_mono(DATA_T *buf, int32 count, InfoStandardReverb *info)
{
	int32 i;

	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_standard_reverb(info);
		do_standard_reverb_mono(buf, count, info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		do_standard_reverb_mono(buf, count, info);
		return;
	} else if(count <= 0) {
		return;
	} 
	do_standard_reverb_mono(buf, count, info);
}


static void setup_ch_freeverb(InfoFreeverb *info)
{
	info->mode = CH_STEREO;
	info->rev_time_sec = reverb_time_table[reverb_status_gs.time];
	info->rev_rt = gs_revchar_to_rt(reverb_status_gs.character);
//	info->rev_wet = (double)reverb_status_gs.level * DIV_127;// * gs_revchar_to_level(reverb_status_gs.character);
	info->rev_wet = gs_revchar_to_level(reverb_status_gs.character);
	info->rev_roomsize = gs_revchar_to_roomsize(reverb_status_gs.character);
	info->er_roomsize = pow(0.9 / info->rev_roomsize, 3.0);
	info->rev_width = initialwidth;
	info->rev_damp = initialdamp;
	info->rev_feedback = 0.0;
	info->rev_level = 0.85 * calc_gs_level(reverb_status_gs.level);
	info->rev_dif = 1.0;
	info->er_time_ms = reverb_status_gs.pre_delay_time;
	info->er_level = 0.25 * calc_gs_level(reverb_status_gs.level);
	info->er_damp_freq = HF_damp_freq_table_gs[0x7F];
}

static void CALLINGCONV do_ch_freeverb(DATA_T *buf, int32 count, struct reverb_status_gs_t *rs)
{
	InfoFreeverb *info = &(rs->info_freeverb);
	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_freeverb(info);
		do_freeverb(buf, count, info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		do_freeverb(buf, count, info);
		return;
	} else if(count <= 0) {
		return;
	} 
	do_freeverb(buf, count, info);
}



static void setup_ch_reverb_ex(InfoReverbEX *info)
{
	info->mode = CH_STEREO;

	switch(reverb_status_gs.character){
	case 0: // room1
		info->height = 3.0; // m
		info->width = 5.0; // m
		info->depth = 7.0; // m
		info->rev_damp_freq = 17000.0; // Hz
		info->rev_damp_type = FILTER_LPF6;
		info->rev_damp_bal = 0.5;
		info->er_level = 0.50;
		info->rev_level = 0.50;
		info->density = 1.0;
		break;
	case 1: // room2
		info->height = 4.0; // m
		info->width = 8.0; // m
		info->depth = 10.0; // m
		info->rev_damp_freq = 15000.0; // Hz
		info->rev_damp_type = FILTER_LPF6;
		info->rev_damp_bal = 0.85;
		info->er_level = 0.45;
		info->rev_level = 0.55;
		info->density = 0.75;
		break;
	case 2: // room3
		info->height = 8.0; // m
		info->width = 12.0; // m
		info->depth = 15.0; // m
		info->rev_damp_freq = 13000.0; // Hz
		info->rev_damp_type = FILTER_LPF6;
		info->rev_damp_bal = 1.0;
		info->er_level = 0.55;
		info->rev_level = 0.45;
		break;
	case 3: // hall1
		info->height = 12.0; // m
		info->width = 14.0; // m
		info->depth = 20.0; // m
		info->rev_damp_freq = 11000.0; // Hz
		info->rev_damp_type = FILTER_LPF6x2;
		info->rev_damp_bal = 0.75;
		info->er_level = 0.50;
		info->rev_level = 0.50;
		info->density = 1.0;
		break;
	default:
	case 4: // hall2
		info->height = 16.0; // m
		info->width = 18.0; // m
		info->depth = 31.0; // m
		info->rev_damp_freq = 9000.0; // Hz
		info->rev_damp_type = FILTER_LPF6x2;
		info->rev_damp_bal = 0.95;
		info->er_level = 0.45;
		info->rev_level = 0.55;
		info->density = 0.75;
		break;
	}
	info->er_time_ms = reverb_status_gs.pre_delay_time;
	info->er_damp_freq = HF_damp_freq_table_gs[0x7F];
	info->rev_time_sec = reverb_time_table[reverb_status_gs.time];	
	info->rev_feedback = 0.0; // reverb_status_gs.delay_feedback
	info->density = 1.0;
	info->level = calc_gs_level(reverb_status_gs.level);
	info->er_level *= info->level;
	info->rev_level *= info->level;
}

static void CALLINGCONV do_ch_reverb_ex(DATA_T *buf, int32 count, struct reverb_status_gs_t *rs)
{
	InfoReverbEX *info = &(rs->info_reverb_ex);
	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_reverb_ex(info);
		do_reverb_ex(buf, count, info);
		return;
	} else if (count <= 0){
		do_reverb_ex(buf, count, info);
		return;
	}
	do_reverb_ex(buf, count, info);
}

#ifdef REV_EX2	
static void setup_ch_reverb_ex2(InfoReverbEX2 *info)
{
	info->mode = CH_STEREO;

	switch(reverb_status_gs.character){
	case 0: // room1
		info->height = 3.0; // m
		info->width = 5.0; // m
		info->depth = 7.0; // m
		info->rev_damp_freq = 17000.0; // Hz
		info->rev_damp_type = FILTER_LPF6;
		info->rev_damp_bal = 0.5;
		info->er_level = 0.50;
		info->rev_level = 0.50;
		info->density = 1.0;
		break;
	case 1: // room2
		info->height = 4.0; // m
		info->width = 8.0; // m
		info->depth = 10.0; // m
		info->rev_damp_freq = 15000.0; // Hz
		info->rev_damp_type = FILTER_LPF6;
		info->rev_damp_bal = 0.85;
		info->er_level = 0.45;
		info->rev_level = 0.55;
		info->density = 0.75;
		break;
	case 2: // room3
		info->height = 8.0; // m
		info->width = 12.0; // m
		info->depth = 15.0; // m
		info->rev_damp_freq = 13000.0; // Hz
		info->rev_damp_type = FILTER_LPF6;
		info->rev_damp_bal = 1.0;
		info->er_level = 0.55;
		info->rev_level = 0.45;
		break;
	case 3: // hall1
		info->height = 12.0; // m
		info->width = 14.0; // m
		info->depth = 20.0; // m
		info->rev_damp_freq = 11000.0; // Hz
		info->rev_damp_type = FILTER_LPF6x2;
		info->rev_damp_bal = 0.75;
		info->er_level = 0.50;
		info->rev_level = 0.50;
		info->density = 1.0;
		break;
	default:
	case 4: // hall2
		info->height = 16.0; // m
		info->width = 18.0; // m
		info->depth = 31.0; // m
		info->rev_damp_freq = 9000.0; // Hz
		info->rev_damp_type = FILTER_LPF6x2;
		info->rev_damp_bal = 0.95;
		info->er_level = 0.45;
		info->rev_level = 0.55;
		info->density = 0.75;
		break;
	}
	info->er_time_ms = reverb_status_gs.pre_delay_time;
	info->er_damp_freq = HF_damp_freq_table_gs[0x7F];
	info->rev_time_sec = reverb_time_table[reverb_status_gs.time];	
	info->rev_feedback = 0.0; // reverb_status_gs.delay_feedback
	info->density = 1.0;
	info->level = calc_gs_level(reverb_status_gs.level);
	info->er_level *= info->level;
	info->rev_level *= info->level;
}

static void CALLINGCONV do_ch_reverb_ex2(DATA_T *buf, int32 count, struct reverb_status_gs_t *rs)
{
	InfoReverbEX2 *info = &(rs->info_reverb_ex2);
	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_reverb_ex2(info);
		do_reverb_ex2(buf, count, info);
		return;
	} else if (count <= 0){
		do_reverb_ex2(buf, count, info);
		return;
	}
	do_reverb_ex2(buf, count, info);
}
#else
#define do_ch_reverb_ex2 do_ch_reverb_ex
#endif


#define REVERB_DELAY_TIME_MAX (500.0) // ms // def 476.25 ?
#define REVERB_DELAY_LEVEL (1.00) // def 1.82 ?

static void setup_ch_reverb_delay(InfoDelay3 *info)
{
	info->time_ms[DELAY3_CH_C] = (double)((int)reverb_status_gs.time + 1) * DIV_128 * REVERB_DELAY_TIME_MAX;
	info->time_ms[DELAY3_CH_L] = info->time_ms[DELAY3_CH_R] = info->time_ms[DELAY3_CH_C]; // same all
	info->level[DELAY3_CH_L] = info->level[DELAY3_CH_R] = calc_gs_level(reverb_status_gs.level) * REVERB_DELAY_LEVEL;
	info->level[DELAY3_CH_C] = 0; // not use
	info->feedback = (double)reverb_status_gs.delay_feedback * DIV_127; // 0.0 ~ 1.0
}

static void CALLINGCONV do_ch_reverb_panning_delay(DATA_T *buf, int32 count, struct reverb_status_gs_t *rs)
{
	InfoDelay3 *info = &(rs->info_reverb_delay);
	if(count == MAGIC_INIT_EFFECT_INFO) {
		info->delay_type = DELAY3_TYPE_PANNING;
		setup_ch_reverb_delay(info);
		do_delay3(buf, count, info);
		return;
	} else if(count <= 0) {
		do_delay3(buf, count, info);
		return;
	} 
	do_delay3(buf, count, info);
}

static void CALLINGCONV do_ch_reverb_normal_delay(DATA_T *buf, int32 count, struct reverb_status_gs_t *rs)
{
	InfoDelay3 *info = &(rs->info_reverb_delay);
	if(count == MAGIC_INIT_EFFECT_INFO) {
		info->delay_type = DELAY3_TYPE_NORMAL;
		setup_ch_reverb_delay(info);
		do_delay3(buf, count, info);
		return;
	} else if(count <= 0) {
		do_delay3(buf, count, info);
		return;
	} 
	do_delay3(buf, count, info);
}


static void setup_ch_plate_reverb(InfoPlateReverb *info)
{
	info->mode = CH_STEREO;
	info->rev_time_sec = reverb_time_table[reverb_status_gs.time];
//	info->rev_rt = gs_revchar_to_rt(reverb_status_gs.character);
//	info->rev_wet = (double)reverb_status_gs.level * DIV_127;
	info->rev_wet = calc_gs_level(reverb_status_gs.level);
//	info->rev_roomsize = gs_revchar_to_roomsize(reverb_status_gs.character);
//	info->rev_width = 0.5;
	info->rev_damp = PLATE_DAMPING;
	info->rev_diff = 1.0;
	info->rev_feedback = 0.125;
	info->rev_level = 0.50;
	info->er_time_ms = reverb_status_gs.pre_delay_time;
	info->er_level = 0.50;
}

static void CALLINGCONV do_ch_plate_reverb(DATA_T *buf, int32 count, struct reverb_status_gs_t *rs)
{
	InfoPlateReverb *info = &(rs->info_plate_reverb);
	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_plate_reverb(info);
		do_plate_reverb(buf, count, info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		do_plate_reverb(buf, count, info);
		return;
	} else if(count <= 0) {
		return;
	} 
	do_plate_reverb(buf, count, info);
}


static void CALLINGCONV do_ch_dummy_reverb(DATA_T *buf, int32 count, struct reverb_status_gs_t *rs)
{
}

///// Reverb VST 
static void CALLINGCONV do_ch_reverb_vst_gs(DATA_T *buf, int32 count, struct reverb_status_gs_t *rs)
{
	if (count <= 0) {
		return;
	}
	do_reverb_vst(buf, count);
}


/*! initialize Reverb Effect */
static void (CALLINGCONV *p_do_ch_reverb)(DATA_T*, int32, struct reverb_status_gs_t*) = do_ch_dummy_reverb;

void init_ch_reverb(void)
{
#ifdef VST_LOADER_ENABLE
#if defined(VSTWRAP_EXT) // if support reverb VST
	if (hVSTHost != NULL && (opt_reverb_control >= 9 || opt_reverb_control <= -1024)){
		reverb_status_gs.pre_lpf = 0;
		init_pre_lpf(&(reverb_status_gs.lpf));
		p_do_ch_reverb = do_ch_reverb_vst_gs;
	}else
#endif
#endif
	if ((opt_reverb_control >= 3 || opt_reverb_control <= -256)) {
		init_pre_lpf(&(reverb_status_gs.lpf));
	/* Only initialize freeverb if stereo output */
	/* Old non-freeverb must be initialized for mono reverb not to crash */
		switch(reverb_status_gs.character) {	/* select reverb algorithm */
		case 5:	/* Plate Reverb */
			p_do_ch_reverb = do_ch_plate_reverb;
		//	REV_INP_LEV = reverb_status_gs.info_plate_reverb.wet;
			break;
		case 6:	/* Delay */
			p_do_ch_reverb = do_ch_reverb_normal_delay;
		//	REV_INP_LEV = 1.0;
			break;
		case 7: /* Panning Delay */
			p_do_ch_reverb = do_ch_reverb_panning_delay;
		//	REV_INP_LEV = 1.0;
			break;
		default: /* Freeverb */
			if (opt_reverb_control >= 7 || opt_reverb_control <= -768)
				p_do_ch_reverb = do_ch_reverb_ex2;
			else if (opt_reverb_control >= 5 || opt_reverb_control <= -512)
				p_do_ch_reverb = do_ch_reverb_ex;
			else
				p_do_ch_reverb = do_ch_freeverb;
		//	REV_INP_LEV = reverb_status_gs.info_freeverb.wet;
			break;
		}
	} else if(opt_reverb_control){	/* Old Reverb */
		p_do_ch_reverb = do_ch_standard_reverb;
	//	REV_INP_LEV = 1.0;
	} else {
		p_do_ch_reverb = do_ch_dummy_reverb;
	}
	(*p_do_ch_reverb)(NULL, MAGIC_INIT_EFFECT_INFO, &reverb_status_gs);
	do_ch_standard_reverb_mono(NULL, MAGIC_INIT_EFFECT_INFO, &(reverb_status_gs.info_standard_reverb));
	memset(reverb_effect_buffer, 0, reverb_effect_bufsize);
	memset(direct_buffer, 0, direct_bufsize);
}

void do_ch_reverb(DATA_T *buf, int32 count)
{
	if (opt_reverb_control >= 3 || opt_reverb_control <= -256){
#ifdef SYS_EFFECT_PRE_LPF
		if(reverb_status_gs.pre_lpf)
			do_pre_lpf(reverb_effect_buffer, count, &(reverb_status_gs.lpf));
#endif /* SYS_EFFECT_PRE_LPF */
	}
	(*p_do_ch_reverb)(reverb_effect_buffer, count, &reverb_status_gs);
	mix_reverb_buffer(buf, count);
}

void do_mono_reverb(DATA_T *buf, int32 count)
{
	do_ch_standard_reverb_mono(reverb_effect_buffer, count, &(reverb_status_gs.info_standard_reverb));
	mix_reverb_buffer(buf, count);
}



/*                   */
/*   Delay Effect    */
/*                   */

static ALIGN DATA_T delay_effect_buffer[AUDIO_BUFFER_SIZE * 2];

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
#if defined(IX86CPU) && defined(SUPPORT_ASM_INTEL)
void set_ch_delay(int32 *buf, int32 count, int32 level)
{
	int32 *dbuf = delay_effect_buffer;
	if (!level) { return; }
	level = CONV_LV_16BIT(level);
	_asm {
		mov		ecx, [count]
		mov		esi, [buf]
		mov		ebx, [level]
		test		ecx, ecx
		jz		short L2
		mov		edi, [dbuf]
L1:		mov		eax, [esi]
		imul		ebx
		shr		eax, 16
		shl		edx, 16
		or		eax, edx	/* u */
		mov		edx, [edi]	/* v */
		add		esi, 4		/* u */
		add		edx, eax	/* v */
		mov		[edi], edx	/* u */
		add		edi, 4		/* v */
		dec		ecx		/* u */
		jnz		L1		/* v */
L2:
	}
}
#elif defined(IX86CPU) && defined(SUPPORT_ASM_AT_AND_T)
void set_ch_delay(int32 *buf, int32 count, int32 level)
{
	int32 *dbuf = delay_effect_buffer;

	if (!level) { return; }
	level = CONV_LV_16BIT(level);
	__asm__ __volatile__("\
		testl		%%ecx, %%ecx;\
		jz		L2_DELAY_%=;\
L1_DELAY_%=:	movl		(%%esi), %%eax;\
		imull		%%ebx;\
		shrl		$16, %%eax;	/* 16.16 */\
		shll		$16, %%edx;\
		orl		%%edx, %%eax;	/* u */\
		movl		(%%edi), %%edx;	/* v */\
		addl		$4, %%esi;	/* u */\
		addl		%%eax, %%edx;	/* v */\
		movl		%%edx, (%%edi);	/* u */\
		addl		$4, %%edi;	/* v */\
		decl		%%ecx;		/* u */\
		jnz		L1_DELAY_%=;	/* v */\
L2_DELAY_%=:	"
		: "=S"(buf), "=c"(count), "=D"(dbuf)
		: "0"(buf), "1"(count), "2"(dbuf), "b"(level)
		: "eax", "edx", "memory"
	);
}
#else
void set_ch_delay(int32 *buf, int32 count, int32 level)
{
	int32 *dbuf = delay_effect_buffer;

	if (level)
	{
		const int32 send_leveli = CONV_LV_16BIT(level);
#if 1
		register const int32 * const ebuf = buf + count;

		do
		{
			(*(dbuf++)) += imuldiv16((*(buf++)), send_leveli);
		} while (buf < ebuf);
#else
		register int32 i;

		for (i = count - 1; i >= 0; i--)
		{
			dbuf[i] += imuldiv16(buf[i], send_leveli);
		}
#endif
	}
}
#endif /* IX86CPU */
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
void set_ch_delay(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		__m256d send_level = _mm256_set1_pd((double)level * DIV_127);
		for(i = 0; i < n; i += 8){
			MM256_LS_FMA_PD(&delay_effect_buffer[i], _mm256_load_pd(&sbuffer[i]), send_level);
			MM256_LS_FMA_PD(&delay_effect_buffer[i + 4], _mm256_load_pd(&sbuffer[i + 4]), send_level);
		}
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
void set_ch_delay(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		__m256 send_level = _mm256_set1_ps((float)level * DIV_127);
		for(i = 0; i < n; i += 8)
			MM256_LS_FMA_PS(&delay_effect_buffer[i], _mm256_load_ps(&sbuffer[i]), send_level);
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
void set_ch_delay(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		__m128d send_level = _mm_set1_pd((double)level * DIV_127);
		for(i = 0; i < n; i += 8){
			MM_LS_FMA_PD(&delay_effect_buffer[i], _mm_load_pd(&sbuffer[i]), send_level);
			MM_LS_FMA_PD(&delay_effect_buffer[i + 2], _mm_load_pd(&sbuffer[i + 2]), send_level);
			MM_LS_FMA_PD(&delay_effect_buffer[i + 4], _mm_load_pd(&sbuffer[i + 4]), send_level);
			MM_LS_FMA_PD(&delay_effect_buffer[i + 6], _mm_load_pd(&sbuffer[i + 6]), send_level);
		}
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
void set_ch_delay(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		__m128 send_level = _mm_set_ps1((float)level * DIV_127);
		for(i = 0; i < n; i += 8){
			MM_LS_FMA_PS(&delay_effect_buffer[i], _mm_load_ps(&sbuffer[i]), send_level);
			MM_LS_FMA_PS(&delay_effect_buffer[i + 4], _mm_load_ps(&sbuffer[i + 4]), send_level);
		}
	}
}
#else
void set_ch_delay(DATA_T *sbuffer, int32 n, int32 level)
{
    int32 i;
	FLOAT_T send_level;

	if(!level) {return;}
	send_level = (FLOAT_T)level * DIV_127;
    for(i = 0; i < n; i++)
    {
        delay_effect_buffer[i] += sbuffer[i] * send_level;
    }
}
#endif /* OPT_MODE != 0 */



#if (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static inline void mix_delay_buffer(DATA_T *buf, int32 count, InfoDelay3 *info)
{
    int32  i;

	__m256d delay_level = _mm256_set1_pd(info->delay_level),
		send_reverb = _mm256_set1_pd(info->send_reverb);
	for(i = 0; i < count; i += 8)	{
		__m256d out = _mm256_mul_pd(_mm256_load_pd(&delay_effect_buffer[i]), delay_level);
		MM256_LS_ADD_PD(&buf[i], out);
		MM256_LS_FMA_PD(&reverb_effect_buffer[i], out, send_reverb);
		out = _mm256_mul_pd(_mm256_load_pd(&delay_effect_buffer[i + 4]), delay_level);
		MM256_LS_ADD_PD(&buf[i + 4], out);
		MM256_LS_FMA_PD(&reverb_effect_buffer[i + 4], out, send_reverb);
	}
	memset(delay_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static inline void mix_delay_buffer(DATA_T *buf, int32 count, InfoDelay3 *info)
{
    int32  i;

	__m256 delay_level = _mm256_set1_ps(info->delay_level),
		send_reverb = _mm256_set1_ps(info->send_reverb);
	for(i = 0; i < count; i += 8)	{
		__m256 out = _mm256_mul_ps(_mm256_load_ps(&delay_effect_buffer[i]), delay_level);
		MM256_LS_ADD_PS(&buf[i], out);
		MM256_LS_FMA_PS(&reverb_effect_buffer[i], out, send_reverb);
	}
	memset(delay_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static inline void mix_delay_buffer(DATA_T *buf, int32 count, InfoDelay3 *info)
{
    int32  i;

	__m128d delay_level = _mm_set1_pd(info->delay_level),
		send_reverb = _mm_set1_pd(info->send_reverb);
	for(i = 0; i < count; i += 4)	{
		__m128d out = _mm_mul_pd(_mm_load_pd(&delay_effect_buffer[i]), delay_level);
		MM_LS_ADD_PD(&buf[i],  out);
		MM_LS_FMA_PD(&reverb_effect_buffer[i], out, send_reverb);
		out = _mm_mul_pd(_mm_load_pd(&delay_effect_buffer[i + 2]), delay_level);
		MM_LS_ADD_PD(&buf[i + 2], out);
		MM_LS_FMA_PD(&reverb_effect_buffer[i + 2], out, send_reverb);
	}
	memset(delay_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static inline void mix_delay_buffer(DATA_T *buf, int32 count, InfoDelay3 *info)
{
    int32  i;

	__m128 delay_level = _mm_set1_ps(info->delay_level),
		send_reverb = _mm_set1_ps(info->send_reverb);
	for(i = 0; i < count; i += 8)	{
		__m128 out = _mm_mul_ps(_mm_load_ps(&delay_effect_buffer[i]), delay_level);
		MM_LS_ADD_PS(&buf[i], out);
		MM_LS_FMA_PS(&reverb_effect_buffer[i], out, send_reverb);
		out = _mm_mul_ps(_mm_load_ps(&delay_effect_buffer[i + 4]), delay_level);
		MM_LS_ADD_PS(&buf[i + 4], out);
		MM_LS_FMA_PS(&reverb_effect_buffer[i + 4], out, send_reverb);
	}
	memset(delay_effect_buffer, 0, sizeof(DATA_T) * count);
}
#else
static inline void mix_delay_buffer(DATA_T *buf, int32 count, InfoDelay3 *info)
{
	int32 i;

	for (i = 0; i < count; i++) {
		DATA_T out = delay_effect_buffer[i] * info->delay_level;
		buf[i] += out;
		reverb_effect_buffer[i] += out * info->send_reverb;
	}
	memset(delay_effect_buffer, 0, sizeof(DATA_T) * count);
}
#endif

// GS system effect delay 共通
static void setup_ch_3tap_delay(DATA_T *buf, int32 count, InfoDelay3 *info)
{
	struct delay_status_gs_t *p = &delay_status_gs;

	info->delay_type = DELAY3_TYPE_3TAP; // 3tap
	info->time_ms[DELAY3_CH_C] = delay_time_center_table[p->time_c > 0x73 ? 0x73 : p->time_c] * otd.delay_param.delay; // elionadded
	info->time_ms[DELAY3_CH_L] = info->time_ms[DELAY3_CH_C] * (double)((int)p->time_l + 1) * DIV_128 * 5.0; // ratio 4% ~ 500% (3.9% ~ 500%
	info->time_ms[DELAY3_CH_R] = info->time_ms[DELAY3_CH_C] * (double)((int)p->time_r + 1) * DIV_128 * 5.0; // ratio 4% ~ 500% (3.9% ~ 500%
	if (info->time_ms[DELAY3_CH_C] > 1000.0) // >1sec
		info->time_ms[DELAY3_CH_C] = 1000.0;
	if (info->time_ms[DELAY3_CH_L] > 1000.0) // >1sec
		info->time_ms[DELAY3_CH_L] = 1000.0;
	if (info->time_ms[DELAY3_CH_R] > 1000.0) // >1sec
		info->time_ms[DELAY3_CH_R] = 1000.0;
	p->level_center = p->level_center & 0x7F;
	p->level_left = p->level_left & 0x7F;
	p->level_right = p->level_right & 0x7F;	
	info->level[DELAY3_CH_C] = calc_option_level(p->level_center);
	info->level[DELAY3_CH_L] = calc_option_level(p->level_left);
	info->level[DELAY3_CH_R] = calc_option_level(p->level_right);
	info->feedback = (double)(p->feedback - 64) * DIV_64 * otd.delay_param.feedback; // 0.763f/DIV_127
	info->send_reverb = (double)p->send_reverb * DIV_127; // * REV_INP_LEV;
	info->delay_level = calc_gs_level(p->level) * otd.delay_param.level;
}

static void CALLINGCONV do_ch_3tap_delay(DATA_T *buf, int32 count, InfoDelay3 *info)
{
	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_3tap_delay(buf, count, info);
		do_delay3(buf, count, info);	
		return;
	} else if(count <= 0) {
		do_delay3(delay_effect_buffer, count, info);
		return;
	}
	do_delay3(buf, count, info);	
}

static void (CALLINGCONV *p_do_ch_delay)(DATA_T*, int32, InfoDelay3*) = do_ch_3tap_delay;

void init_ch_delay(void)
{
	init_pre_lpf(&(delay_status_gs.lpf));
	do_ch_3tap_delay(NULL, MAGIC_INIT_EFFECT_INFO, &(delay_status_gs.info_delay));
	memset(delay_effect_buffer, 0, sizeof(delay_effect_buffer));
}

void do_ch_delay(DATA_T *buf, int32 count)
{
#ifdef SYS_EFFECT_PRE_LPF
	if ((opt_reverb_control >= 3	|| (opt_reverb_control < 0 && ! (opt_reverb_control & 0x100))) && delay_status_gs.pre_lpf)
		do_pre_lpf(delay_effect_buffer, count, &(delay_status_gs.lpf));
#endif /* SYS_EFFECT_PRE_LPF */
	//switch (delay_status_gs.type) {
	//case 1:
	//	do_ch_3tap_delay(buf, count, &(delay_status_gs.info_delay));
	//	break;
	//case 2:
	//	do_ch_cross_delay(buf, count, &(delay_status_gs.info_delay));
	//	break;
	//default:
	//	do_ch_normal_delay(buf, count, &(delay_status_gs.info_delay));
	//	break;
	//}
	do_ch_3tap_delay(delay_effect_buffer, count, &(delay_status_gs.info_delay));
	mix_delay_buffer(buf, count, &(delay_status_gs.info_delay));	
}


/*                             */
/*        Chorus Effect        */
/*                             */

static ALIGN DATA_T chorus_effect_buffer[AUDIO_BUFFER_SIZE * 2];

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
#if defined(IX86CPU) && defined(SUPPORT_ASM_INTEL)
void set_ch_chorus(int32 *buf, int32 count, int32 level)
{
	int32 *dbuf = chorus_effect_buffer;
	if (!level) { return; }
	level = CONV_LV_16BIT(level);
	_asm {
		mov		ecx, [count]
		mov		esi, [buf]
		mov		ebx, [level]
		test		ecx, ecx
		jz		short L2
		mov		edi, [dbuf]
L1:		mov		eax, [esi]
		imul		ebx
		shr		eax, 16
		shl		edx, 16
		or		eax, edx	/* u */
		mov		edx, [edi]	/* v */
		add		esi, 4		/* u */
		add		edx, eax	/* v */
		mov		[edi], edx	/* u */
		add		edi, 4		/* v */
		dec		ecx		/* u */
		jnz		L1		/* v */
L2:
	}
}
#elif defined(IX86CPU) && defined(SUPPORT_ASM_AT_AND_T)
void set_ch_chorus(int32 *buf, int32 count, int32 level)
{
	int32 *dbuf = chorus_effect_buffer;

	if (!level) { return; }
	level = CONV_LV_16BIT(level);
	__asm__ __volatile__("\
		testl		%%ecx, %%ecx;\
		jz		L2_CHORS_%=;\
L1_CHORS_%=:	movl		(%%esi), %%eax;\
		imull		%%ebx;\
		shrl		$16, %%eax;	/* 16.16 */\
		shll		$16, %%edx;\
		orl		%%edx, %%eax;	/* u */\
		movl		(%%edi), %%edx;	/* v */\
		addl		$4, %%esi;	/* u */\
		addl		%%eax, %%edx;	/* v */\
		movl		%%edx, (%%edi);	/* u */\
		addl		$4, %%edi;	/* v */\
		decl		%%ecx;		/* u */\
		jnz		L1_CHORS_%=;	/* v */\
L2_CHORS_%=:	"
		: "=S"(buf), "=c"(count), "=D"(dbuf)
		: "0"(buf), "1"(count), "2"(dbuf), "b"(level)
		: "eax", "edx", "memory"
	);
}
#else
void set_ch_chorus(int32 *buf, int32 count, int32 level)
{
	int32 *dbuf = chorus_effect_buffer;

	if (level)
	{
		const int32 send_leveli = CONV_LV_16BIT(level);
#if 1
		register const int32 * const ebuf = buf + count;

		do
		{
			(*(dbuf++)) += imuldiv16((*(buf++)), send_leveli);
		} while (buf < ebuf);
#else
		register int32 i;

		for (i = count - 1; i >= 0; i--)
		{
			dbuf[i] += imuldiv16(buf[i], send_leveli);
		}
#endif
	}
}
#endif /* IX86CPU */
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
void set_ch_chorus(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		__m256d send_level = _mm256_set1_pd((double)level * DIV_127);
		for(i = 0; i < n; i += 8){
			MM256_LS_FMA_PD(&chorus_effect_buffer[i], _mm256_load_pd(&sbuffer[i]), send_level);
			MM256_LS_FMA_PD(&chorus_effect_buffer[i + 4], _mm256_load_pd(&sbuffer[i + 4]), send_level);
		}
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
void set_ch_chorus(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		__m256 send_level = _mm256_set1_ps((float)level * DIV_127);
		for(i = 0; i < n; i += 8)
			MM256_LS_FMA_PS(&chorus_effect_buffer[i], _mm256_load_ps(&sbuffer[i]), send_level);
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
void set_ch_chorus(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		__m128d send_level = _mm_set1_pd((double)level * DIV_127);
		for(i = 0; i < n; i += 8){
			MM_LS_FMA_PD(&chorus_effect_buffer[i], _mm_load_pd(&sbuffer[i]), send_level);
			MM_LS_FMA_PD(&chorus_effect_buffer[i + 2], _mm_load_pd(&sbuffer[i + 2]), send_level);
			MM_LS_FMA_PD(&chorus_effect_buffer[i + 4], _mm_load_pd(&sbuffer[i + 4]), send_level);
			MM_LS_FMA_PD(&chorus_effect_buffer[i + 6], _mm_load_pd(&sbuffer[i + 6]), send_level);
		}
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
void set_ch_chorus(DATA_T *sbuffer, int32 n, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		__m128 send_level = _mm_set_ps1((float)level * DIV_127);
		for(i = 0; i < n; i += 8){
			MM_LS_FMA_PS(&chorus_effect_buffer[i], _mm_load_ps(&sbuffer[i]), send_level);
			MM_LS_FMA_PS(&chorus_effect_buffer[i + 4], _mm_load_ps(&sbuffer[i + 4]), send_level);
		}
	}
}
#else	/* floating-point implementation */
void set_ch_chorus(DATA_T *sbuffer, int32 n, int32 level)
{
    int32 i;
	FLOAT_T send_level;

	if(!level) {return;}
    send_level = (FLOAT_T)level * DIV_127;
    for(i = 0; i < n; i++)
    {
		chorus_effect_buffer[i] += sbuffer[i] * send_level;
    }
}
#endif /* OPT_MODE != 0 */


#if (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static inline void mix_chorus_buffer(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
    int32  i;

	__m256d cho_level = _mm256_set1_pd(info->level),
		send_reverb = _mm256_set1_pd(info->send_reverb),
		send_delay = _mm256_set1_pd(info->send_delay);
	for(i = 0; i < count; i += 8){
		__m256d out = _mm256_mul_pd(_mm256_load_pd(&chorus_effect_buffer[i]), cho_level);
		MM256_LS_ADD_PD(&buf[i], out);
		MM256_LS_FMA_PD(&reverb_effect_buffer[i], out, send_reverb);
		MM256_LS_FMA_PD(&delay_effect_buffer[i], out, send_delay);
		out = _mm256_mul_pd(_mm256_load_pd(&chorus_effect_buffer[i + 4]), cho_level);
		MM256_LS_ADD_PD(&buf[i + 4], out);
		MM256_LS_FMA_PD(&reverb_effect_buffer[i + 4], out, send_reverb);
		MM256_LS_FMA_PD(&delay_effect_buffer[i + 4], out, send_delay);
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static inline void mix_chorus_buffer(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
    int32  i;

	__m256 cho_level = _mm256_set1_ps(info->level),
		send_reverb = _mm256_set1_ps(info->send_reverb),
		send_delay = _mm256_set1_ps(info->send_delay);
	for(i = 0; i < count; i += 8){
		__m256 out = _mm256_mul_ps(_mm256_load_ps(&chorus_effect_buffer[i]), cho_level);
		MM256_LS_ADD_PS(&buf[i], out);
		MM256_LS_FMA_PS(&reverb_effect_buffer[i], out, send_reverb);
		MM256_LS_FMA_PS(&delay_effect_buffer[i], out, send_delay);
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static inline void mix_chorus_buffer(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
    int32  i;
	__m128d cho_level = _mm_set1_pd(info->level),
		send_reverb = _mm_set1_pd(info->send_reverb),
		send_delay = _mm_set1_pd(info->send_delay);
	for(i = 0; i < count; i += 4){
		__m128d out = _mm_mul_pd(_mm_load_pd(&chorus_effect_buffer[i]), cho_level);
		MM_LS_ADD_PD(&buf[i], out);
		MM_LS_FMA_PD(&reverb_effect_buffer[i], out, send_reverb);
		MM_LS_FMA_PD(&delay_effect_buffer[i], out, send_delay);
		out = _mm_mul_pd(_mm_load_pd(&chorus_effect_buffer[i + 2]), cho_level);
		MM_LS_ADD_PD(&buf[i + 2], out);
		MM_LS_FMA_PD(&reverb_effect_buffer[i + 2], out, send_reverb);
		MM_LS_FMA_PD(&delay_effect_buffer[i + 2], out, send_delay);
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static inline void mix_chorus_buffer(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
    int32  i;

	__m128 cho_level = _mm_set1_ps(info->level),
		send_reverb = _mm_set1_ps(info->send_reverb),
		send_delay = _mm_set1_ps(info->send_delay);
	for(i = 0; i < count; i += 8){
		__m128 out = _mm_mul_ps(_mm_load_ps(&chorus_effect_buffer[i]), cho_level);
		MM_LS_ADD_PS(&buf[i], out);
		MM_LS_FMA_PS(&reverb_effect_buffer[i], out, send_reverb);
		MM_LS_FMA_PS(&delay_effect_buffer[i], out, send_delay);
		out = _mm_mul_ps(_mm_load_ps(&chorus_effect_buffer[i + 4]), cho_level);
		MM_LS_ADD_PS(&buf[i + 4], out);
		MM_LS_FMA_PS(&reverb_effect_buffer[i + 4], out, send_reverb);
		MM_LS_FMA_PS(&delay_effect_buffer[i + 4], out, send_delay);
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#else
static inline void mix_chorus_buffer(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	int32 i;

	for (i = 0; i < count; i++) {
		DATA_T out = chorus_effect_buffer[i] * info->level;
		buf[i] += out;
		reverb_effect_buffer[i] += out * info->send_reverb;
		delay_effect_buffer[i] += out * info->send_delay;
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#endif


// GS/GM2 system effect chorus 共通
static inline void setup_ch_chorus(InfoStereoChorus *info)
{
	info->mode = CH_STEREO;
	if(ext_chorus_ex_phase < 1 || ext_chorus_ex_phase > 8) // 1 ~ 8
		info->phase = 3; // def 3
	else
		info->phase = ext_chorus_ex_phase;
	if(chorus_status_gs.system_mode){ // GM2_SYSTEM_MODE
		info->depth_type = 1; // ms
		info->rate = calc_chorus_rate_gm2(chorus_status_gs.rate); // Hz
		info->pdelay_ms = chorus_delay_time_table[chorus_status_gs.delay]; // ms
		info->depth_ms = calc_chorus_depth_gm2(chorus_status_gs.depth); // ms
		info->feedback = (double)chorus_status_gs.feedback * DIV_127 * 0.96901; // 0.0~1.0
		info->send_reverb = (double)chorus_status_gs.send_reverb * DIV_127 * 0.99949;
		info->send_delay = 0.0;
		info->level = (double)chorus_status_gs.level * DIV_127;
	}else{ // GS_SYSTEM_MODE + other
		info->depth_type = 0; // cent
		info->rate = (double)rate1_table[chorus_status_gs.rate];; // Hz
		info->pdelay_ms = chorus_delay_time_table[chorus_status_gs.delay]; // ms
		info->depth_cent = calc_chorus_depth_gs(chorus_status_gs.depth); // ms
		info->feedback = (double)chorus_status_gs.feedback * DIV_127; // 0.0~1.0
		info->send_reverb = (double)chorus_status_gs.send_reverb * DIV_127; // * REV_INP_LEV;
		info->send_delay = (double)chorus_status_gs.send_delay * DIV_127;
		info->level = calc_gs_level(chorus_status_gs.level);
	}
	info->phase_diff = 90; // deg
	info->pdelay_dev = 0; // 0~20
	info->depth_dev = 0; // -20~+20
	info->pan_dev = 20; // 0~20 // use CH_MIX_STEREO, CH_MONO_STEREO
	// int32
	info->send_reverbi = TIM_FSCALE(info->send_reverb, 24);
	info->send_delayi = TIM_FSCALE(info->send_delay, 24);
	info->leveli = TIM_FSCALE(info->level, 24);
}

static void CALLINGCONV do_ch_chorus_p1(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_chorus(info);
		do_chorus_p1(buf, count, info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		do_chorus_p1(buf, count, info);
		return;
	} else if(count <= 0) {
		return;
	} 
	do_chorus_p1(buf, count, info);
}

static void CALLINGCONV do_ch_chorus_wv(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_chorus(info);
		do_chorus_waver(buf, count, info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		do_chorus_waver(buf, count, info);
		return;
	} else if(count <= 0) {
		return;
	} 
	do_chorus_waver(buf, count, info);
}

static void CALLINGCONV do_ch_chorus_p2(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_chorus(info);
		do_chorus_p2(buf, count, info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		do_chorus_p2(buf, count, info);
		return;
	} else if(count <= 0) {
		return;
	} 
	do_chorus_p2(buf, count, info);
}

static void CALLINGCONV do_ch_chorus_p3(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_chorus(info);
		do_chorus_p3(buf, count, info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		do_chorus_p3(buf, count, info);
		return;
	} else if(count <= 0) {
		return;
	} 
	do_chorus_p3(buf, count, info);
}

static void CALLINGCONV do_ch_chorus_p6(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_chorus(info);
		do_chorus_p6(buf, count, info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		do_chorus_p6(buf, count, info);
		return;
	} else if(count <= 0) {
		return;
	} 
	do_chorus_p6(buf, count, info);
}

static void CALLINGCONV do_ch_chorus_ex(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_chorus(info);
		do_chorus_ex(buf, count, info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		do_chorus_ex(buf, count, info);
		return;
	} else if(count <= 0) {
		return;
	} 
	do_chorus_ex(buf, count, info);
}

///// Chorus VST 
static void CALLINGCONV do_ch_chorus_vst_gs(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
	if(count == MAGIC_INIT_EFFECT_INFO) {
		setup_ch_chorus(info);
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		return;
	} else if(count <= 0) {
		return;
	} 	
	do_chorus_vst(buf, count);
}

/*! initialize Chorus Effect */
static void (CALLINGCONV *p_do_ch_chorus)(DATA_T*, int32, InfoStereoChorus*) = do_ch_chorus_p1;

void init_ch_chorus(void)
{
#ifdef VST_LOADER_ENABLE
#if defined(VSTWRAP_EXT) // if support chorus VST
	if (hVSTHost != NULL && opt_normal_chorus_plus == 6){
		chorus_status_gs.pre_lpf = 0;
		init_pre_lpf(&(chorus_status_gs.lpf));
		p_do_ch_chorus = do_ch_chorus_vst_gs;
	}else
#endif
#endif
	{
		/* clear delay-line of LPF */
		init_pre_lpf(&(chorus_status_gs.lpf));
		switch (opt_normal_chorus_plus) {
		case 5:
			p_do_ch_chorus = do_ch_chorus_ex;
			break;
		case 4:
			p_do_ch_chorus = do_ch_chorus_p6;
			break;
		case 3:
			p_do_ch_chorus = do_ch_chorus_p3;
			break;
		case 2:
			p_do_ch_chorus = do_ch_chorus_p2;
			break;
		case 1:
			p_do_ch_chorus = do_ch_chorus_wv;
			break;
		default:
		case 0:
			p_do_ch_chorus = do_ch_chorus_p1;
			break;
		}
	}
	(*p_do_ch_chorus)(NULL, MAGIC_INIT_EFFECT_INFO, &(chorus_status_gs.info_stereo_chorus));
	memset(chorus_effect_buffer, 0, sizeof(chorus_effect_buffer));
}


void do_ch_chorus(DATA_T *buf, int32 count)
{
#ifdef SYS_EFFECT_PRE_LPF
	if ((opt_reverb_control >= 3 || (opt_reverb_control < 0 && ! (opt_reverb_control & 0x100))) && chorus_status_gs.pre_lpf)
		do_pre_lpf(chorus_effect_buffer, count, &(chorus_status_gs.lpf));
#endif /* SYS_EFFECT_PRE_LPF */	
	(*p_do_ch_chorus)(chorus_effect_buffer, count, &(chorus_status_gs.info_stereo_chorus));
	mix_chorus_buffer(buf, count, &(chorus_status_gs.info_stereo_chorus));
}

static void do_ch_chorus_free(DATA_T *buf, int32 count, InfoStereoChorus *info)
{
 // free buffer
	(*p_do_ch_chorus)(NULL, MAGIC_FREE_EFFECT_INFO, &(chorus_status_gs.info_stereo_chorus));
}



/*                             */
/*       EQ (Equalizer)        */
/*                             */
static ALIGN DATA_T eq_buffer[AUDIO_BUFFER_SIZE * 2];

void init_eq_gs()
{
	memset(eq_buffer, 0, sizeof(eq_buffer));
#ifdef GS_EQ_FIR
	eq_status_gs.eq_gs.init = -1;
	init_fir_eq(&(eq_status_gs.eq_gs));
#else
	init_sample_filter2(&(eq_status_gs.lsf), 0, 0, 0, FILTER_NONE);
	init_sample_filter2(&(eq_status_gs.hsf), 0, 0, 0, FILTER_NONE);
#endif
}

#if (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static inline void mix_eq_buffer_gs(DATA_T* buf, int32 count)
{
	int32 i;
	for(i = 0; i < count; i += 8){
		MM256_LS_ADD_PD(&buf[i], _mm256_load_pd(&eq_buffer[i]));
		MM256_LS_ADD_PD(&buf[i + 4], _mm256_load_pd(&eq_buffer[i + 4]));
	}
	memset(eq_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static inline void mix_eq_buffer_gs(DATA_T* buf, int32 count)
{
	int32 i;
	for(i = 0; i < count; i += 8){
		MM256_LS_ADD_PS(&buf[i], _mm256_load_ps(&eq_buffer[i]));
	}
	memset(eq_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static inline void mix_eq_buffer_gs(DATA_T* buf, int32 count)
{
	int32 i;
	for(i = 0; i < count; i += 8){
		MM_LS_ADD_PD(&buf[i], _mm_load_pd(&eq_buffer[i]));
		MM_LS_ADD_PD(&buf[i + 2], _mm_load_pd(&eq_buffer[i + 2]));
		MM_LS_ADD_PD(&buf[i + 4], _mm_load_pd(&eq_buffer[i + 4]));
		MM_LS_ADD_PD(&buf[i + 6], _mm_load_pd(&eq_buffer[i + 6]));
	}
	memset(eq_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static inline void mix_eq_buffer_gs(DATA_T* buf, int32 count)
{
	int32 i;	
	for(i = 0; i < count; i += 8){
		MM_LS_ADD_PS(&buf[i], _mm_load_ps(&eq_buffer[i]));
		MM_LS_ADD_PS(&buf[i + 4], _mm_load_ps(&eq_buffer[i + 4]));
	}
	memset(eq_buffer, 0, sizeof(DATA_T) * count);
}
#else
static inline void mix_eq_buffer_gs(DATA_T* buf, int32 count)
{
	int32 i;

	for(i = 0; i < count; i++) {
		buf[i] += eq_buffer[i];
	}
	memset(eq_buffer, 0, sizeof(DATA_T) * count);
}
#endif

void do_ch_eq_gs(DATA_T* buf, int32 count)
{
	int32 i;
	
	buffer_filter_stereo(&(eq_status_gs.lsf), eq_buffer, count);
	buffer_filter_stereo(&(eq_status_gs.hsf), eq_buffer, count);
	mix_eq_buffer_gs(buf, count);
}

void do_ch_eq_xg(DATA_T* buf, int32 count, struct part_eq_xg *p)
{
	if(!p->valid) return;
	buffer_filter_stereo(&(p->basss), buf, count);
	buffer_filter_stereo(&(p->trebles), buf, count);
	buffer_filter_stereo(&(p->mid_basss), buf, count);
	buffer_filter_stereo(&(p->mid_trebles), buf, count);
}

void do_multi_eq_xg(DATA_T* buf, int32 count)
{
	if(!multi_eq_xg.valid) return;
	buffer_filter_stereo(&(multi_eq_xg.eq1), buf, count);/* peaking *//* shelving */
	buffer_filter_stereo(&(multi_eq_xg.eq2), buf, count);/* peaking */
	buffer_filter_stereo(&(multi_eq_xg.eq3), buf, count);/* peaking */
	buffer_filter_stereo(&(multi_eq_xg.eq4), buf, count);/* peaking */
	buffer_filter_stereo(&(multi_eq_xg.eq5), buf, count);/* peaking *//* shelving */
}

void do_multi_eq_sd(DATA_T* buf, int32 count)
{
	buffer_filter_left(&(multi_eq_sd.eq_ll), buf, count); /* shelving */
	buffer_filter_right(&(multi_eq_sd.eq_lr), buf, count); /* shelving */
	buffer_filter_left(&(multi_eq_sd.eq_hl), buf, count); /* shelving */
	buffer_filter_right(&(multi_eq_sd.eq_hr), buf, count); /* shelving */
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
#if defined(IX86CPU) && defined(SUPPORT_ASM_INTEL)
void set_ch_eq_gs(int32 *buf, int32 count)
{
	int32 *dbuf = eq_buffer;
	_asm {
		mov		ecx, [count]
		mov		esi, [buf]
		test		ecx, ecx
		jz		short L2
		mov		edi, [dbuf]
L1:		mov		eax, [esi]
		mov		ebx, [edi]
		add		esi, 4
		add		ebx, eax
		mov		[edi], ebx
		add		edi, 4
		dec		ecx
		jnz		L1
L2:
	}
}
#elif defined(IX86CPU) && defined(SUPPORT_ASM_AT_AND_T)
void set_ch_eq_gs(int32 *buf, int32 count)
{
	int32 *dbuf = eq_buffer;

	__asm__ __volatile__("\
		testl		%%ecx, %%ecx;\
		jz		L2_EQGS_%=;\
L1_EQGS_%=:	movl		(%%esi), %%eax;\
		movl		(%%edi), %%ebx;\
		addl		$4, %%esi;\
		addl		%%eax, %%ebx;\
		movl		%%ebx, (%%edi);\
		addl		$4, %%edi;\
		decl		%%ecx;\
		jnz		L1_EQGS_%=;\
L2_EQGS_%=:	"
		: "=S"(buf), "=c"(count), "=D"(dbuf)
		: "0"(buf), "1"(count), "2"(dbuf)
		: "eax", "ebx", "memory"
	);
}
#else
void set_ch_eq_gs(register int32 *buf, int32 n)
{
    register int32 i;

    for (i = n - 1; i >= 0; i--) {
        eq_buffer[i] += buf[i];
    }
}
#endif /* IX86CPU */
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
void set_ch_eq_gs(DATA_T *sbuffer, int32 n)
{
    int32  i;
	for(i = 0; i < n; i += 8){
		MM256_LS_ADD_PD(&eq_buffer[i], _mm256_load_pd(&sbuffer[i]));
		MM256_LS_ADD_PD(&eq_buffer[i + 4], _mm256_load_pd(&sbuffer[i + 4]));
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
void set_ch_eq_gs(DATA_T *sbuffer, int32 n)
{
    int32  i;
	for(i = 0; i < n; i += 8){
		MM256_LS_ADD_PS(&eq_buffer[i], _mm256_load_ps(&sbuffer[i]));
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
void set_ch_eq_gs(DATA_T *sbuffer, int32 n)
{
    int32  i;
	for(i = 0; i < n; i += 8){
		MM_LS_ADD_PD(&eq_buffer[i], _mm_load_pd(&sbuffer[i]));
		MM_LS_ADD_PD(&eq_buffer[i + 2], _mm_load_pd(&sbuffer[i + 2]));
		MM_LS_ADD_PD(&eq_buffer[i + 4], _mm_load_pd(&sbuffer[i + 4]));
		MM_LS_ADD_PD(&eq_buffer[i + 6], _mm_load_pd(&sbuffer[i + 6]));
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
void set_ch_eq_gs(DATA_T *sbuffer, int32 n)
{
    int32  i;
	for(i = 0; i < n; i += 8){
		MM_LS_ADD_PS(&eq_buffer[i], _mm_load_ps(&sbuffer[i]));
		MM_LS_ADD_PS(&eq_buffer[i + 4], _mm_load_ps(&sbuffer[i + 4]));
	}
}
#else
void set_ch_eq_gs(DATA_T *sbuffer, int32 n)
{
    int32  i;
    
	for(i = 0; i < n; i++)  {
        eq_buffer[i] += sbuffer[i];
    }
}
#endif /* OPT_MODE != 0 */





/*                                     */
/*  Insertion and Variation Effect  */
/*                                     */

/* SD MFX */

static ALIGN DATA_T mfx_effect_buffer[SD_MFX_EFFECT_NUM][AUDIO_BUFFER_SIZE * 2];

DATA_T* get_mfx_buffer(int mfx_select)
{
	return mfx_effect_buffer[mfx_select];
}

void calc_mfx_send_level_sd(struct mfx_effect_sd_t *st){
	int ch = st->efx_source;

	if(ch == -1){		
		st->type = &st->common_type;
		st->set_param = st->common_param;
		st->ctrl_source = st->common_ctrl_source;
		st->ctrl_sens = st->common_ctrl_sens;
		st->ctrl_assign = st->common_ctrl_assign;
		st->dry_level = (FLOAT_T)st->common_dry_send * DIV_127;
		st->reverb_level = (FLOAT_T)st->common_send_reverb * DIV_127;
		st->chorus_level = (FLOAT_T)st->common_send_chorus * DIV_127;
	}else{
		st->type = &channel[ch].mfx_part_type;
		st->set_param = channel[ch].mfx_part_param;
		st->ctrl_source = channel[ch].mfx_part_ctrl_source;
		st->ctrl_sens = channel[ch].mfx_part_ctrl_sens;
		st->ctrl_assign = channel[ch].mfx_part_ctrl_assign;
		st->dry_level = (FLOAT_T)channel[ch].mfx_part_dry_send * DIV_127;
		st->reverb_level = (FLOAT_T)channel[ch].mfx_part_send_chorus * DIV_127;
		st->chorus_level = (FLOAT_T)channel[ch].mfx_part_send_chorus * DIV_127;
	}
	st->dry_leveli = TIM_FSCALE(st->dry_level, 24);
	st->reverb_leveli = TIM_FSCALE(st->reverb_level, 24);
	st->chorus_leveli = TIM_FSCALE(st->chorus_level, 24);
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
#if defined(IX86CPU) && defined(SUPPORT_ASM_INTEL)
void set_ch_mfx_sd(int32 *sbuffer, int32 n, int mfx_select, int32 level)
{
	int32 *dbuf = mfx_effect_buffer[mfx_select];
	if (!level) { return; }
	level = CONV_LV_16BIT(level);
	_asm {
		mov		ecx, [n]
		mov		esi, [sbuffer]
		mov		ebx, [level]
		test		ecx, ecx
		jz		short L2
		mov		edi, [dbuf]
L1:		mov		eax, [esi]
		imul		ebx
		shr		eax, 16
		shl		edx, 16
		or		eax, edx	/* u */
		mov		edx, [edi]	/* v */
		add		esi, 4		/* u */
		add		edx, eax	/* v */
		mov		[edi], edx	/* u */
		add		edi, 4		/* v */
		dec		ecx		/* u */
		jnz		L1		/* v */
L2:
	}
}
#elif defined(IX86CPU) && defined(SUPPORT_ASM_AT_AND_T)
void set_ch_mfx_sd(int32 *sbuffer, int32 n, int mfx_select, int32 level)
{
	int32 *dbuf = mfx_effect_buffer[mfx_select];
	if (!level) { return; }
	level = CONV_LV_16BIT(level);
	__asm__ __volatile__("\
		testl		%%ecx, %%ecx;\
		jz		L2_MFX_SD_%=;\
L1_MFX_SD_%=:	movl		(%%esi), %%eax;\
		imull		%%ebx;\
		shrl		$16, %%eax;	/* 16.16 */\
		shll		$16, %%edx;\
		orl		%%edx, %%eax;	/* u */\
		movl		(%%edi), %%edx;	/* v */\
		addl		$4, %%esi;	/* u */\
		addl		%%eax, %%edx;	/* v */\
		movl		%%edx, (%%edi);	/* u */\
		addl		$4, %%edi;	/* v */\
		decl		%%ecx;		/* u */\
		jnz		L1_MFX_SD_%=;	/* v */\
L2_MFX_SD_%=:	"
		: "=S"(sbuffer), "=c"(n), "=D"(dbuf)
		: "0"(sbuffer), "1"(n), "2"(dbuf), "b"(level)
		: "eax", "edx", "memory"
	);
}
#else
void set_ch_mfx_sd(int32 *sbuffer, int32 n, int mfx_select, int32 level)
{
	int32 *dbuf = mfx_effect_buffer[mfx_select];

	if (level)
	{
		const int32 send_leveli = CONV_LV_16BIT(level);
#if 1
		register const int32 * const ebuf = sbuffer + n;

		do
		{
			(*(dbuf++)) += imuldiv16((*(sbuffer++)), send_leveli);
		} while (sbuffer < ebuf);
#else
		register int32 i;

		for (i = n - 1; i >= 0; i--)
		{
			dbuf[i] += imuldiv16(sbuffer[i], send_leveli);
		}
#endif
	}
}
#endif /* IX86CPU */
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
void set_ch_mfx_sd(DATA_T *sbuffer, int32 n, int mfx_select, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		DATA_T *dbuf = mfx_effect_buffer[mfx_select];
		__m256d send_level = _mm256_set1_pd((double)level * DIV_127);
		for(i = 0; i < n; i += 8){
			MM256_LS_FMA_PD(&dbuf[i], _mm256_load_pd(&sbuffer[i]), send_level);
			MM256_LS_FMA_PD(&dbuf[i + 4], _mm256_load_pd(&sbuffer[i + 4]), send_level);
		}
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
void set_ch_mfx_sd(DATA_T *sbuffer, int32 n, int mfx_select, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		DATA_T *dbuf = mfx_effect_buffer[mfx_select];
		__m256 send_level = _mm256_set1_ps((float)level * DIV_127);
		for(i = 0; i < n; i += 8)
			MM256_LS_FMA_PS(&dbuf[i], _mm256_load_ps(&sbuffer[i]), send_level);
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
void set_ch_mfx_sd(DATA_T *sbuffer, int32 n, int mfx_select, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		DATA_T *dbuf = mfx_effect_buffer[mfx_select];
		__m128d send_level = _mm_set1_pd((double)level * DIV_127);
		for(i = 0; i < n; i += 8){
			MM_LS_FMA_PD(&dbuf[i], _mm_load_pd(&sbuffer[i]), send_level);
			MM_LS_FMA_PD(&dbuf[i + 2], _mm_load_pd(&sbuffer[i + 2]), send_level);
			MM_LS_FMA_PD(&dbuf[i + 4], _mm_load_pd(&sbuffer[i + 4]), send_level);
			MM_LS_FMA_PD(&dbuf[i + 6], _mm_load_pd(&sbuffer[i + 6]), send_level);
		}
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
void set_ch_mfx_sd(DATA_T *sbuffer, int32 n, int mfx_select, int32 level)
{
    int32  i;

	if(!level) {return;}
	{
		DATA_T *dbuf = mfx_effect_buffer[mfx_select];
		__m128 send_level = _mm_set_ps1((float)level * DIV_127);
		for(i = 0; i < n; i += 8){
			MM_LS_FMA_PS(&dbuf[i], _mm_load_ps(&sbuffer[i]), send_level);
			MM_LS_FMA_PS(&dbuf[i + 4], _mm_load_ps(&sbuffer[i + 4]), send_level);
		}
	}
}
#else	/* floating-point implementation */
void set_ch_mfx_sd(DATA_T *sbuffer, int32 n, int mfx_select, int32 level)
{
    int32 i;

	if(!level) {return;}
	{
		DATA_T *mfx_buf = mfx_effect_buffer[mfx_select];
		FLOAT_T send_level = (FLOAT_T)level * DIV_127;
		for(i = 0; i < n; i++)  {
			mfx_buf[i] += sbuffer[i] * send_level;
		}
	}
}
#endif /* OPT_MODE != 0 */


#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void mix_mfx_buffer_sd(DATA_T *buf, int32 count, int mfx_select)
{
	int32 i;
	DATA_T x, *out_ptr;
	int32 send_chorus =  mfx_effect_sd[mfx_select].chorus_leveli,
		send_reverb = mfx_effect_sd[mfx_select].reverb_leveli;

	if(!buf) // NULL
		out_ptr = direct_buffer;
	else
		out_ptr = buf;
	for (i = 0; i < count; i++) {
		x = mfx_effect_buffer[mfx_select][i];
		out_ptr[i] += x;
		chorus_effect_buffer[i] += imuldiv24(x, send_chorus);
		reverb_effect_buffer[i] += imuldiv24(x, send_reverb);
	}
	memset(mfx_effect_buffer[mfx_select], 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void mix_mfx_buffer_sd(DATA_T *buf, int32 count, int mfx_select)
{
	int32 i;
	DATA_T x, *out_ptr;
	__m256d send_chorus = _mm256_set1_pd(mfx_effect_sd[mfx_select].chorus_level),
		send_reverb = _mm256_set1_pd(mfx_effect_sd[mfx_select].reverb_level);
	if(!buf) // NULL
		out_ptr = direct_buffer;
	else
		out_ptr = buf;
	for(i = 0; i < count; i += 8){
		__m256d out = _mm256_load_pd(&mfx_effect_buffer[mfx_select][i]);
		MM256_LS_ADD_PD(&out_ptr[i], out);
		MM256_LS_FMA_PD(&chorus_effect_buffer[i], out, send_chorus);
		MM256_LS_FMA_PD(&reverb_effect_buffer[i], out, send_reverb);
		out = _mm256_load_pd(&mfx_effect_buffer[mfx_select][i + 4]);
		MM256_LS_ADD_PD(&out_ptr[i + 4], out);
		MM256_LS_FMA_PD(&chorus_effect_buffer[i + 4], out, send_chorus);
		MM256_LS_FMA_PD(&reverb_effect_buffer[i + 4], out, send_reverb);
	}
	memset(mfx_effect_buffer[mfx_select], 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void mix_mfx_buffer_sd(DATA_T *buf, int32 count, int mfx_select)
{
	int32 i;
	DATA_T x, *out_ptr;
	__m256 send_chorus = _mm256_set1_ps(mfx_effect_sd[mfx_select].chorus_level),
		send_reverb = _mm256_set1_ps(mfx_effect_sd[mfx_select].reverb_level);
	if(!buf) // NULL
		out_ptr = direct_buffer;
	else
		out_ptr = buf;
	for(i = 0; i < count; i += 8){
		__m256 out = _mm256_load_ps(&mfx_effect_buffer[mfx_select][i]);
		MM256_LS_ADD_PS(&out_ptr[i], out);
		MM256_LS_FMA_PS(&chorus_effect_buffer[i], out, send_chorus);
		MM256_LS_FMA_PS(&reverb_effect_buffer[i], out, send_reverb);
	}
	memset(mfx_effect_buffer[mfx_select], 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static void mix_mfx_buffer_sd(DATA_T *buf, int32 count, int mfx_select)
{
	int32 i;
	DATA_T x, *out_ptr;
	__m128d send_chorus = _mm_set1_pd(mfx_effect_sd[mfx_select].chorus_level),
		send_reverb = _mm_set1_pd(mfx_effect_sd[mfx_select].reverb_level);
	if(!buf) // NULL
		out_ptr = direct_buffer;
	else
		out_ptr = buf;
	for(i = 0; i < count; i += 4){
		__m128d out = _mm_load_pd(&mfx_effect_buffer[mfx_select][i]);
		MM_LS_ADD_PD(&out_ptr[i], out);
		MM_LS_FMA_PD(&chorus_effect_buffer[i], out, send_chorus);
		MM_LS_FMA_PD(&reverb_effect_buffer[i], out, send_reverb);
		MM_LS_ADD_PD(&out_ptr[i + 2], out);
		MM_LS_FMA_PD(&chorus_effect_buffer[i + 2], out, send_chorus);
		MM_LS_FMA_PD(&reverb_effect_buffer[i + 2], out, send_reverb);
	}
	memset(mfx_effect_buffer[mfx_select], 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void mix_mfx_buffer_sd(DATA_T *buf, int32 count, int mfx_select)
{
	int32 i;
	DATA_T x, *out_ptr;
	__m128 send_chorus = _mm_set1_ps(mfx_effect_sd[mfx_select].chorus_level),
		send_reverb = _mm_set1_ps(mfx_effect_sd[mfx_select].reverb_level);
	if(!buf) // NULL
		out_ptr = direct_buffer;
	else
		out_ptr = buf;
	for(i = 0; i < count; i += 8){
		__m128 out = _mm_load_ps(&mfx_effect_buffer[mfx_select][i]);
		MM_LS_ADD_PS(&out_ptr[i], out);
		MM_LS_FMA_PS(&chorus_effect_buffer[i], out, send_chorus);
		MM_LS_FMA_PS(&reverb_effect_buffer[i], out, send_reverb);
		MM_LS_ADD_PS(&out_ptr[i + 4], out);
		MM_LS_FMA_PS(&chorus_effect_buffer[i + 4], out, send_chorus);
		MM_LS_FMA_PS(&reverb_effect_buffer[i + 4], out, send_reverb);
	}
	memset(mfx_effect_buffer[mfx_select], 0, sizeof(DATA_T) * count);
}
#else
static void mix_mfx_buffer_sd(DATA_T *buf, int32 count, int mfx_select)
{
	int32 i;
	DATA_T x, *out_ptr;
	FLOAT_T send_chorus =  mfx_effect_sd[mfx_select].chorus_level,
		send_reverb = mfx_effect_sd[mfx_select].reverb_level;

	if(!buf) // NULL
		out_ptr = direct_buffer;
	else
		out_ptr = buf;

	for (i = 0; i < count; i++) {
		x = mfx_effect_buffer[mfx_select][i];
		out_ptr[i] += x;
		chorus_effect_buffer[i] += x * send_chorus;
		reverb_effect_buffer[i] += x * send_reverb;
	}
	memset(mfx_effect_buffer[mfx_select], 0, sizeof(DATA_T) * count);
}
#endif /* OPT_MODE != 0 */

void do_mfx_effect_sd(DATA_T *buf, int32 count, int mfx_select)
{
	do_effect_list(mfx_effect_buffer[mfx_select], count, mfx_effect_sd[mfx_select].ef);
	mix_mfx_buffer_sd(buf, count, mfx_select);
}

void set_chorus_send_reverb_sd(int send_level)
{
	struct mfx_effect_sd_t *st = &chorus_status_sd;
	int ch = st->efx_source;

	if(ch == -1){		
		st->common_send_reverb = clip_int(send_level, 0, 127);
		st->reverb_level = (FLOAT_T)st->common_send_reverb * DIV_127;
	}else{
		channel[ch].chorus_part_send_reverb = clip_int(send_level, 0, 127);
		st->reverb_level = (FLOAT_T)channel[ch].chorus_part_send_reverb * DIV_127;
	}
	st->reverb_leveli = TIM_FSCALE(st->reverb_level, 24);
}

void calc_chorus_level_sd(struct mfx_effect_sd_t *st)
{
	int ch = st->efx_source;

	if(ch == -1){		
		st->type = &st->common_type;
		st->set_param = st->common_param;
		st->chorus_level = (FLOAT_T)st->common_efx_level * DIV_127;
		st->reverb_level = (FLOAT_T)st->common_send_reverb * DIV_127;
	}else{
		st->type = &channel[ch].chorus_part_type;
		st->set_param = channel[ch].chorus_part_param;
		st->chorus_level = (FLOAT_T)channel[ch].chorus_part_efx_level * DIV_127;
		st->reverb_level = (FLOAT_T)channel[ch].chorus_part_send_reverb * DIV_127;
	}
	st->chorus_leveli = TIM_FSCALE(st->chorus_level, 24);
	st->reverb_leveli = TIM_FSCALE(st->reverb_level, 24);
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void mix_chorus_buffer_sd(DATA_T *buf, int32 count)
{
	int32 i, x;
	int32 cho_level = chorus_status_sd.chorus_leveli;
	int32 rev_level = chorus_status_sd.reverb_leveli;
	switch(*chorus_status_sd.output_select){
	case 0: // main
		for (i = 0; i < count; i++) {
			buf[i] += imuldiv24(chorus_effect_buffer[i], cho_level);
			reverb_effect_buffer[i] += imuldiv24(chorus_effect_buffer[i], rev_level);
		}
		break;
	case 1: // reverb
		for (i = 0; i < count; i++) {
			reverb_effect_buffer[i] += imuldiv24(chorus_effect_buffer[i], cho_level);
		}
		break;
	case 2: // main+reverb
		for (i = 0; i < count; i++) {
			x = imuldiv24(chorus_effect_buffer[i], cho_level);
			buf[i] += x;
			reverb_effect_buffer[i] += x;
		}
		break;
	}
	memset(chorus_effect_buffer, 0, sizeof(int32) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void mix_chorus_buffer_sd(DATA_T *buf, int32 count)
{
	int32 i;
	__m256d cho_level = _mm256_set1_pd(chorus_status_sd.chorus_level);
	__m256d rev_level = _mm256_set1_pd(chorus_status_sd.reverb_level);
	switch(*chorus_status_sd.output_select){
	case 0: // main
		for (i = 0; i < count; i += 8) {
			__m256d input = _mm256_load_pd(&chorus_effect_buffer[i]);
			MM256_LS_FMA_PD(&buf[i], input, cho_level);
			MM256_LS_FMA_PD(&reverb_effect_buffer[i], input, rev_level);
			input = _mm256_load_pd(&chorus_effect_buffer[i + 4]);
			MM256_LS_FMA_PD(&buf[i + 4], input, cho_level);
			MM256_LS_FMA_PD(&reverb_effect_buffer[i + 4], input, rev_level);
		}
		break;
	case 1: // reverb
		for (i = 0; i < count; i += 8) {
			MM256_LS_FMA_PD(&reverb_effect_buffer[i], _mm256_load_pd(&chorus_effect_buffer[i]), cho_level);
			MM256_LS_FMA_PD(&reverb_effect_buffer[i + 4], _mm256_load_pd(&chorus_effect_buffer[i + 4]), cho_level);
		}
		break;
	case 2: // main+reverb
		for (i = 0; i < count; i += 8) {
			__m256d out = _mm256_mul_pd(_mm256_load_pd(&chorus_effect_buffer[i]), cho_level);
			MM256_LS_ADD_PD(&buf[i], out);
			MM256_LS_ADD_PD(&reverb_effect_buffer[i], out);
			out = _mm256_mul_pd(_mm256_load_pd(&chorus_effect_buffer[i + 4]), cho_level);
			MM256_LS_ADD_PD(&buf[i + 4], out);
			MM256_LS_ADD_PD(&reverb_effect_buffer[i + 4], out);
		}
		break;
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void mix_chorus_buffer_sd(DATA_T *buf, int32 count)
{
	int32 i;
	__m256 cho_level = _mm256_set1_ps(chorus_status_sd.chorus_level);
	__m256 rev_level = _mm256_set1_ps(chorus_status_sd.reverb_level);
	switch(*chorus_status_sd.output_select){
	case 0: // main
		for (i = 0; i < count; i += 8) {
			__m256 input = _mm256_load_ps(&chorus_effect_buffer[i]);
			MM256_LS_FMA_PS(&buf[i], input, cho_level);
			MM256_LS_FMA_PS(&reverb_effect_buffer[i], input, rev_level);
		}
		break;
	case 1: // reverb
		for (i = 0; i < count; i += 8) {
			MM256_LS_FMA_PS(&reverb_effect_buffer[i], _mm256_load_ps(&chorus_effect_buffer[i]), cho_level);
		}
		break;
	case 2: // main+reverb
		for (i = 0; i < count; i += 8) {
			__m256 out = _mm256_mul_ps(_mm256_load_ps(&chorus_effect_buffer[i]), cho_level);
			MM256_LS_ADD_PS(&buf[i], out);
			MM256_LS_ADD_PS(&reverb_effect_buffer[i], out);
		}
		break;
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static void mix_chorus_buffer_sd(DATA_T *buf, int32 count)
{
	int32 i;
	__m128d cho_level = _mm_set1_pd(chorus_status_sd.chorus_level);	
	__m128d rev_level = _mm_set1_pd(chorus_status_sd.reverb_level);
	switch(*chorus_status_sd.output_select){
	case 0: // main
		for (i = 0; i < count; i += 4) {
			__m128d input = _mm_load_pd(&chorus_effect_buffer[i]);
			MM_LS_FMA_PD(&buf[i], input, cho_level);
			MM_LS_FMA_PD(&reverb_effect_buffer[i], input, rev_level);
			input = _mm_load_pd(&chorus_effect_buffer[i + 2]);
			MM_LS_FMA_PD(&buf[i + 2], input, cho_level);
			MM_LS_FMA_PD(&reverb_effect_buffer[i + 2], input, rev_level);
		}
		break;
	case 1: // reverb
		for (i = 0; i < count; i += 4) {
			MM_LS_FMA_PD(&reverb_effect_buffer[i], _mm_load_pd(&chorus_effect_buffer[i]), cho_level);
			MM_LS_FMA_PD(&reverb_effect_buffer[i + 2], _mm_load_pd(&chorus_effect_buffer[i + 2]), cho_level);
		}
		break;
	case 2: // main+reverb
		for (i = 0; i < count; i += 4) {
			__m128d out = _mm_mul_pd(_mm_load_pd(&chorus_effect_buffer[i]), cho_level);
			MM_LS_ADD_PD(&buf[i], out);
			MM_LS_ADD_PD(&reverb_effect_buffer[i], out);
			out = _mm_mul_pd(_mm_load_pd(&chorus_effect_buffer[i + 2]), cho_level);
			MM_LS_ADD_PD(&buf[i + 2], out);
			MM_LS_ADD_PD(&reverb_effect_buffer[i + 2], out);
		}
		break;
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void mix_chorus_buffer_sd(DATA_T *buf, int32 count)
{
	int32 i;
	__m128 cho_level = _mm_set1_ps(chorus_status_sd.chorus_level);
	__m128 rev_level = _mm_set1_ps(chorus_status_sd.reverb_level);
	switch(*chorus_status_sd.output_select){
	case 0: // main
		for (i = 0; i < count; i += 8) {
			__m128 input = _mm_load_ps(&chorus_effect_buffer[i]);
			MM_LS_FMA_PS(&buf[i], input, cho_level);
			MM_LS_FMA_PS(&reverb_effect_buffer[i], input, rev_level);
			input = _mm_load_ps(&chorus_effect_buffer[i + 4]);
			MM_LS_FMA_PS(&buf[i + 4], input, cho_level);
			MM_LS_FMA_PS(&reverb_effect_buffer[i + 4], input, rev_level);
		}
		break;
	case 1: // reverb
		for (i = 0; i < count; i += 8) {
			MM_LS_FMA_PS(&reverb_effect_buffer[i], _mm_load_ps(&chorus_effect_buffer[i]), cho_level);
			MM_LS_FMA_PS(&reverb_effect_buffer[i + 4], _mm_load_ps(&chorus_effect_buffer[i + 4]), cho_level);
		}
		break;
	case 2: // main+reverb
		for (i = 0; i < count; i += 8) {
			__m128 out = _mm_mul_ps(_mm_load_ps(&chorus_effect_buffer[i]), cho_level);
			MM_LS_ADD_PS(&buf[i], out);
			MM_LS_ADD_PS(&reverb_effect_buffer[i], out);
			out = _mm_mul_ps(_mm_load_ps(&chorus_effect_buffer[i + 4]), cho_level);
			MM_LS_ADD_PS(&buf[i + 4], out);
			MM_LS_ADD_PS(&reverb_effect_buffer[i + 4], out);
		}
		break;
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#else /* floating-point implementation */
static void mix_chorus_buffer_sd(DATA_T *buf, int32 count)
{
	int32 i;
	DATA_T x;
	FLOAT_T cho_level = chorus_status_sd.chorus_level;
	FLOAT_T rev_level = chorus_status_sd.reverb_level;
	switch(*chorus_status_sd.output_select){
	case 0: // main
		for (i = 0; i < count; i++) {
			buf[i] += chorus_effect_buffer[i] * cho_level;
			reverb_effect_buffer[i] += chorus_effect_buffer[i] * rev_level;
		}
		break;
	case 1: // reverb
		for (i = 0; i < count; i++) {
			reverb_effect_buffer[i] += chorus_effect_buffer[i] * cho_level;
		}
		break;
	case 2: // main+reverb
		for (i = 0; i < count; i++) {
			x = chorus_effect_buffer[i] * cho_level;
			buf[i] += x;
			reverb_effect_buffer[i] += x;
		}
		break;
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#endif /* OPT_MODE != 0 */

void do_ch_chorus_sd(DATA_T *buf, int32 count)
{
#ifdef VST_LOADER_ENABLE
#if defined(VSTWRAP_EXT) // if support chorus VST
	if (hVSTHost != NULL && opt_normal_chorus_plus == 6){
		do_chorus_vst(chorus_effect_buffer, count);
	}else
#endif
#endif
	do_effect_list(chorus_effect_buffer, count, chorus_status_sd.ef);
	mix_chorus_buffer_sd(buf, count);
}

void calc_reverb_level_sd(struct mfx_effect_sd_t *st){
	int ch = st->efx_source;

	if(ch == -1){		
		st->type = &st->common_type;
		st->set_param = st->common_param;
		st->reverb_level = (FLOAT_T)st->common_efx_level * DIV_127;
	}else{
		st->type = &channel[ch].reverb_part_type;
		st->set_param = channel[ch].reverb_part_param;
		st->reverb_level = (FLOAT_T)channel[ch].reverb_part_efx_level * DIV_127;
	}
	st->reverb_leveli = TIM_FSCALE(st->reverb_level, 24);
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static inline void mix_reverb_buffer_sd(DATA_T *buf, int32 count)
{
	int32 i;
	int32 rev_level = reverb_status_sd.reverb_leveli;
	for (i = 0; i < count; i++)
		buf[i] += imuldiv24(reverb_effect_buffer[i], rev_level);
	memset(reverb_effect_buffer, 0, sizeof(int32) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static inline void mix_reverb_buffer_sd(DATA_T *buf, int32 count)
{
	int32 i;
	__m256d rev_level = _mm256_set1_pd(reverb_status_sd.reverb_level);
	for (i = 0; i < count; i += 8){
		MM256_LS_FMA_PD(&buf[i], _mm256_load_pd(&reverb_effect_buffer[i]), rev_level);
		MM256_LS_FMA_PD(&buf[i + 4], _mm256_load_pd(&reverb_effect_buffer[i + 4]), rev_level);
	}
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static inline void mix_reverb_buffer_sd(DATA_T *buf, int32 count)
{
	int32 i;
	__m256 rev_level = _mm256_set1_ps(reverb_status_sd.reverb_level);
	for (i = 0; i < count; i += 8)
		MM256_LS_FMA_PS(&buf[i], _mm256_load_ps(&reverb_effect_buffer[i]), rev_level);
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static inline void mix_reverb_buffer_sd(DATA_T *buf, int32 count)
{
	int32 i;
	__m128d rev_level = _mm_set1_pd(reverb_status_sd.reverb_level);
	for (i = 0; i < count; i += 8){
		MM_LS_FMA_PD(&buf[i], _mm_load_pd(&reverb_effect_buffer[i]), rev_level);
		MM_LS_FMA_PD(&buf[i + 2], _mm_load_pd(&reverb_effect_buffer[i + 2]), rev_level);
		MM_LS_FMA_PD(&buf[i + 4], _mm_load_pd(&reverb_effect_buffer[i + 4]), rev_level);
		MM_LS_FMA_PD(&buf[i + 6], _mm_load_pd(&reverb_effect_buffer[i + 6]), rev_level);
	}
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static inline void mix_reverb_buffer_sd(DATA_T *buf, int32 count)
{
	int32 i;
	__m128 rev_level = _mm_set1_ps(reverb_status_sd.reverb_level);
	for (i = 0; i < count; i += 8){
		MM_LS_FMA_PS(&buf[i], _mm_load_ps(&reverb_effect_buffer[i]), rev_level);
		MM_LS_FMA_PS(&buf[i + 4], _mm_load_ps(&reverb_effect_buffer[i + 4]), rev_level);
	}
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#else /* floating-point implementation */
static inline void mix_reverb_buffer_sd(DATA_T *buf, int32 count)
{
	int32 i;
	DATA_T x;
	FLOAT_T rev_level = reverb_status_sd.reverb_level;
	for (i = 0; i < count; i++)
		buf[i] += reverb_effect_buffer[i] * rev_level;
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#endif

void do_ch_reverb_sd(DATA_T *buf, int32 count)
{
#ifdef VST_LOADER_ENABLE
#if defined(VSTWRAP_EXT) // if support reverb VST
	if (hVSTHost != NULL && (opt_reverb_control >= 9 || opt_reverb_control <= -1024)){
		do_reverb_vst(reverb_effect_buffer, count);
	}else
#endif
#endif
	do_effect_list(reverb_effect_buffer, count, reverb_status_sd.ef);
	mix_reverb_buffer_sd(buf, count);
}

void init_ch_effect_sd(void)
{
	memset(reverb_effect_buffer, 0, sizeof(reverb_effect_buffer));
	memset(chorus_effect_buffer, 0, sizeof(chorus_effect_buffer));
	memset(mfx_effect_buffer, 0, sizeof(mfx_effect_buffer));
}



static ALIGN DATA_T insertion_effect_buffer[AUDIO_BUFFER_SIZE * 2];

DATA_T* get_insertion_buffer(void)
{
	return insertion_effect_buffer;
}


#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
#if defined(IX86CPU) && defined(SUPPORT_ASM_INTEL)
void set_ch_insertion_gs(int32 *buf, int32 count)
{
	int32 *dbuf = insertion_effect_buffer;
	_asm {
		mov		ecx, [count]
		mov		esi, [buf]
		test		ecx, ecx
		jz		short L2
		mov		edi, [dbuf]
L1:		mov		eax, [esi]
		mov		ebx, [edi]
		add		esi, 4
		add		ebx, eax
		mov		[edi], ebx
		add		edi, 4
		dec		ecx
		jnz		L1
L2:
	}
}
#elif defined(IX86CPU) && defined(SUPPORT_ASM_AT_AND_T)
void set_ch_insertion_gs(int32 *buf, int32 count)
{
	int32 *dbuf = insertion_effect_buffer;

	__asm__ __volatile__("\
		testl		%%ecx, %%ecx;\
		jz		L2_INSGS_%=;\
L1_INSGS_%=:	movl		(%%esi), %%eax;\
		movl		(%%edi), %%ebx;\
		addl		$4, %%esi;\
		addl		%%eax, %%ebx;\
		movl		%%ebx, (%%edi);\
		addl		$4, %%edi;\
		decl		%%ecx;\
		jnz		L1_INSGS_%=;\
L2_INSGS_%=:	"
		: "=S"(buf), "=c"(count), "=D"(dbuf)
		: "0"(buf), "1"(count), "2"(dbuf)
		: "eax", "ebx", "memory"
	);
}
#else
void set_ch_insertion_gs(register int32 *buf, int32 n)
{
    register int32 i;

    for (i = n - 1; i >= 0; i--) {
        insertion_effect_buffer[i] += buf[i];
    }
}
#endif /* IX86CPU */
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
void set_ch_insertion_gs(DATA_T *sbuffer, int32 n)
{
    int32  i;
	for(i = 0; i < n; i += 8){
		MM256_LS_ADD_PD(&insertion_effect_buffer[i], _mm256_load_pd(&sbuffer[i]));
		MM256_LS_ADD_PD(&insertion_effect_buffer[i + 4], _mm256_load_pd(&sbuffer[i + 4]));
	}
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
void set_ch_insertion_gs(DATA_T *sbuffer, int32 n)
{
    int32  i;
	for(i = 0; i < n; i += 8){
		MM256_LS_ADD_PS(&insertion_effect_buffer[i], _mm256_load_ps(&sbuffer[i]));
	}
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
void set_ch_insertion_gs(DATA_T *sbuffer, int32 n)
{
    int32  i;
	for(i = 0; i < n; i += 8){
		MM_LS_ADD_PD(&insertion_effect_buffer[i], _mm_load_pd(&sbuffer[i]));
		MM_LS_ADD_PD(&insertion_effect_buffer[i + 2], _mm_load_pd(&sbuffer[i + 2]));
		MM_LS_ADD_PD(&insertion_effect_buffer[i + 4], _mm_load_pd(&sbuffer[i + 4]));
		MM_LS_ADD_PD(&insertion_effect_buffer[i + 6], _mm_load_pd(&sbuffer[i + 6]));
	}
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
void set_ch_insertion_gs(DATA_T *sbuffer, int32 n)
{
    int32  i;
	for(i = 0; i < n; i += 8){
		MM_LS_ADD_PS(&insertion_effect_buffer[i], _mm_load_ps(&sbuffer[i]));
		MM_LS_ADD_PS(&insertion_effect_buffer[i + 4], _mm_load_ps(&sbuffer[i + 4]));
	}
}
#else
void set_ch_insertion_gs(DATA_T *sbuffer, int32 n)
{
    int32  i;
    
	for(i = 0; i < n; i++)  {
        insertion_effect_buffer[i] += sbuffer[i];
    }
}
#endif /* OPT_MODE != 0 */


#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void mix_insertion_buffer_gs(DATA_T *buf, int32 count, int eq_enable)
{
	int32 i;
	DATA_T x, *out_ptr;
	int32 send_chorus =  TIM_FSCALE((double)insertion_effect_gs.send_chorus * DIV_127, 24),
		send_reverb = TIM_FSCALE((double)insertion_effect_gs.send_reverb * DIV_127, 24),
		send_delay = TIM_FSCALE((double)insertion_effect_gs.send_delay * DIV_127, 24);

	if(insertion_effect_gs.send_eq_switch && eq_enable)
		out_ptr = eq_buffer;
	else if(!buf) // NULL
		out_ptr = direct_buffer;
	else
		out_ptr = buf;
	for (i = 0; i < count; i++) {
		x = insertion_effect_buffer[i];
		out_ptr[i] += x;
		chorus_effect_buffer[i] += imuldiv24(x, send_chorus);
		reverb_effect_buffer[i] += imuldiv24(x, send_reverb);
		delay_effect_buffer[i] += imuldiv24(x, send_delay);
	}
	memset(insertion_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void mix_insertion_buffer_gs(DATA_T *buf, int32 count, int eq_enable)
{
	int32 i;
	DATA_T x, *out_ptr;
	__m256d send_chorus = _mm256_set1_pd((double)insertion_effect_gs.send_chorus * DIV_127),
		send_reverb = _mm256_set1_pd((double)insertion_effect_gs.send_reverb * DIV_127),
		send_delay = _mm256_set1_pd((double)insertion_effect_gs.send_delay * DIV_127);
	if(insertion_effect_gs.send_eq_switch && eq_enable)
		out_ptr = eq_buffer;
	else if(!buf) // NULL
		out_ptr = direct_buffer;
	else
		out_ptr = buf;
	for(i = 0; i < count; i += 8){
		__m256d out = _mm256_load_pd(&insertion_effect_buffer[i]);
		MM256_LS_ADD_PD(&out_ptr[i], out);
		MM256_LS_FMA_PD(&chorus_effect_buffer[i], out, send_chorus);
		MM256_LS_FMA_PD(&reverb_effect_buffer[i], out, send_reverb);
		MM256_LS_FMA_PD(&delay_effect_buffer[i], out, send_delay);
		out = _mm256_load_pd(&insertion_effect_buffer[i + 4]);
		MM256_LS_ADD_PD(&out_ptr[i + 4], out);
		MM256_LS_FMA_PD(&chorus_effect_buffer[i + 4], out, send_chorus);
		MM256_LS_FMA_PD(&reverb_effect_buffer[i + 4], out, send_reverb);
		MM256_LS_FMA_PD(&delay_effect_buffer[i + 4], out, send_delay);
	}
	memset(insertion_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void mix_insertion_buffer_gs(DATA_T *buf, int32 count, int eq_enable)
{
	int32 i;
	DATA_T x, *out_ptr;
	__m256 send_chorus = _mm256_set1_ps((double)insertion_effect_gs.send_chorus * DIV_127),
		send_reverb = _mm256_set1_ps((double)insertion_effect_gs.send_reverb * DIV_127),
		send_delay = _mm256_set1_ps((double)insertion_effect_gs.send_delay * DIV_127);
	if(insertion_effect_gs.send_eq_switch && eq_enable)
		out_ptr = eq_buffer;
	else if(!buf) // NULL
		out_ptr = direct_buffer;
	else
		out_ptr = buf;
	for(i = 0; i < count; i += 8){
		__m256 out = _mm256_load_ps(&insertion_effect_buffer[i]);
		MM256_LS_ADD_PS(&out_ptr[i], out);
		MM256_LS_FMA_PS(&chorus_effect_buffer[i], out, send_chorus);
		MM256_LS_FMA_PS(&reverb_effect_buffer[i], out, send_reverb);
		MM256_LS_FMA_PS(&delay_effect_buffer[i], out, send_delay);
	}
	memset(insertion_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static void mix_insertion_buffer_gs(DATA_T *buf, int32 count, int eq_enable)
{
	int32 i;
	DATA_T x, *out_ptr;
	__m128d send_chorus = _mm_set1_pd((double)insertion_effect_gs.send_chorus * DIV_127),
		send_reverb = _mm_set1_pd((double)insertion_effect_gs.send_reverb * DIV_127),
		send_delay = _mm_set1_pd((double)insertion_effect_gs.send_delay * DIV_127);
	if(insertion_effect_gs.send_eq_switch && eq_enable)
		out_ptr = eq_buffer;
	else if(!buf) // NULL
		out_ptr = direct_buffer;
	else
		out_ptr = buf;
	for(i = 0; i < count; i += 4){
		__m128d out = _mm_load_pd(&insertion_effect_buffer[i]);
		MM_LS_ADD_PD(&out_ptr[i], out);
		MM_LS_FMA_PD(&chorus_effect_buffer[i], out, send_chorus);
		MM_LS_FMA_PD(&reverb_effect_buffer[i], out, send_reverb);
		MM_LS_FMA_PD(&delay_effect_buffer[i], out, send_delay);
		out = _mm_load_pd(&insertion_effect_buffer[i + 2]);
		MM_LS_ADD_PD(&out_ptr[i + 2], out);
		MM_LS_FMA_PD(&chorus_effect_buffer[i + 2], out, send_chorus);
		MM_LS_FMA_PD(&reverb_effect_buffer[i + 2], out, send_reverb);
		MM_LS_FMA_PD(&delay_effect_buffer[i + 2], out, send_delay);
	}
	memset(insertion_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void mix_insertion_buffer_gs(DATA_T *buf, int32 count, int eq_enable)
{
	int32 i;
	DATA_T x, *out_ptr;
	__m128 send_chorus = _mm_set1_ps((double)insertion_effect_gs.send_chorus * DIV_127),
		send_reverb = _mm_set1_ps((double)insertion_effect_gs.send_reverb * DIV_127),
		send_delay = _mm_set1_ps((double)insertion_effect_gs.send_delay * DIV_127);
	if(insertion_effect_gs.send_eq_switch && eq_enable)
		out_ptr = eq_buffer;
	else if(!buf) // NULL
		out_ptr = direct_buffer;
	else
		out_ptr = buf;
	for(i = 0; i < count; i += 8){
		__m128 out = _mm_load_ps(&insertion_effect_buffer[i]);
		MM_LS_ADD_PS(&out_ptr[i], out);
		MM_LS_FMA_PS(&chorus_effect_buffer[i], out, send_chorus);
		MM_LS_FMA_PS(&reverb_effect_buffer[i], out, send_reverb);
		MM_LS_FMA_PS(&delay_effect_buffer[i], out, send_delay);
		out = _mm_load_ps(&insertion_effect_buffer[i + 4]);
		MM_LS_ADD_PS(&out_ptr[i + 4], out);
		MM_LS_FMA_PS(&chorus_effect_buffer[i + 4], out, send_chorus);
		MM_LS_FMA_PS(&reverb_effect_buffer[i + 4], out, send_reverb);
		MM_LS_FMA_PS(&delay_effect_buffer[i + 4], out, send_delay);
	}
	memset(insertion_effect_buffer, 0, sizeof(DATA_T) * count);
}
#else
static void mix_insertion_buffer_gs(DATA_T *buf, int32 count, int eq_enable)
{
	int32 i;
	DATA_T x, *out_ptr;
	FLOAT_T send_chorus =  (double)insertion_effect_gs.send_chorus * DIV_127,
		send_reverb = (double)insertion_effect_gs.send_reverb * DIV_127,
		send_delay = (double)insertion_effect_gs.send_delay * DIV_127;

	if(insertion_effect_gs.send_eq_switch && eq_enable)
		out_ptr = eq_buffer;
	else if(!buf) // NULL
		out_ptr = direct_buffer;
	else
		out_ptr = buf;

	for (i = 0; i < count; i++) {
		x = insertion_effect_buffer[i];
		out_ptr[i] += x;
		chorus_effect_buffer[i] += x * send_chorus;
		reverb_effect_buffer[i] += x * send_reverb;
		delay_effect_buffer[i] += x * send_delay;
	}
	memset(insertion_effect_buffer, 0, sizeof(DATA_T) * count);
}
#endif /* OPT_MODE != 0 */

void do_insertion_effect_gs(DATA_T *buf, int32 count, int eq_enable)
{
	do_effect_list(insertion_effect_buffer, count, insertion_effect_gs.ef);
	mix_insertion_buffer_gs(buf, count, eq_enable);
}



void do_insertion_effect_xg(DATA_T *buf, int32 count, struct effect_xg_t *st)
{
	do_effect_list(buf, count, st->ef);
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void mix_variation1_buffer_xg(DATA_T *buf, int32 count)
{
	if (variation_effect_xg[0].connection == XG_CONN_SYSTEM) {	
		int32 i, x;
		int32 panli = TIM_FSCALE((double)variation_effect_xg[0].pan_level[0], 24);
		int32 panri = TIM_FSCALE((double)variation_effect_xg[0].pan_level[1], 24);
		int32 send_reverbi = TIM_FSCALE((double)variation_effect_xg[0].reverb_level, 24),
			send_chorusi = TIM_FSCALE((double)variation_effect_xg[0].chorus_level, 24),
			var_returni = TIM_FSCALE((double)variation_effect_xg[0].return_level, 24);
		for (i = 0; i < count; i++) {
			x = imuldiv24(delay_effect_buffer[i], panli);
			buf[i] += imuldiv24(x, var_returni);
			reverb_effect_buffer[i] += imuldiv24(x, send_reverbi);
			chorus_effect_buffer[i] += imuldiv24(x, send_chorusi);
			++i;
			x = imuldiv24(delay_effect_buffer[i], panri);
			buf[i] += imuldiv24(x, var_returni);
			reverb_effect_buffer[i] += imuldiv24(x, send_reverbi);
			chorus_effect_buffer[i] += imuldiv24(x, send_chorusi);
		}
	}
	memset(delay_effect_buffer, 0, sizeof(int32) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void mix_variation1_buffer_xg(DATA_T *buf, int32 count)
{
	if (variation_effect_xg[0].connection == XG_CONN_SYSTEM) {	
		int32 i;
		FLOAT_T *pan = variation_effect_xg[0].pan_level;
		__m128d vpant = _mm_set_pd(pan[1], pan[0]);
		__m256d vpan = MM256_SET2X_PD(vpant, vpant);
		__m256d send_reverb = _mm256_set1_pd(variation_effect_xg[0].reverb_level),
			send_chorus = _mm256_set1_pd(variation_effect_xg[0].chorus_level),
			var_return = _mm256_set1_pd(variation_effect_xg[0].return_level);
		var_return = _mm256_mul_pd(var_return, vpan);
		send_reverb = _mm256_mul_pd(send_reverb, vpan);
		send_chorus = _mm256_mul_pd(send_chorus, vpan);
		for (i = 0; i < count; i += 8) {
			__m256d out = _mm256_load_pd(&delay_effect_buffer[i]);
			MM256_LS_FMA_PD(&buf[i], out, var_return);
			MM256_LS_FMA_PD(&reverb_effect_buffer[i], out, send_reverb);
			MM256_LS_FMA_PD(&chorus_effect_buffer[i], out, send_chorus);
			out = _mm256_load_pd(&delay_effect_buffer[i + 4]);
			MM256_LS_FMA_PD(&buf[i + 4], out, var_return);
			MM256_LS_FMA_PD(&reverb_effect_buffer[i + 4], out, send_reverb);
			MM256_LS_FMA_PD(&chorus_effect_buffer[i + 4], out, send_chorus);
		}
	}
	memset(delay_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void mix_variation1_buffer_xg(DATA_T *buf, int32 count)
{
	if (variation_effect_xg[0].connection == XG_CONN_SYSTEM) {	
		int32 i;
		FLOAT_T *pan = variation_effect_xg[0].pan_level;
		__m128 vpant = _mm_set_ps(pan[1], pan[0], pan[1], pan[0]);
		__m256 vpan = MM256_SET2X_PS(vpant, vpant);
		__m256 send_reverb = _mm256_set1_ps(variation_effect_xg[0].reverb_level),
			send_chorus = _mm256_set1_ps(variation_effect_xg[0].chorus_level),
			var_return = _mm256_set1_ps(variation_effect_xg[0].return_level);
		var_return = _mm256_mul_ps(var_return, vpan);
		send_reverb = _mm256_mul_ps(send_reverb, vpan);
		send_chorus = _mm256_mul_ps(send_chorus, vpan);
		for (i = 0; i < count; i += 8) {
			__m256 out = _mm256_load_ps(&delay_effect_buffer[i]);
			MM256_LS_FMA_PS(&buf[i], out, var_return);
			MM256_LS_FMA_PS(&reverb_effect_buffer[i], out, send_reverb);
			MM256_LS_FMA_PS(&chorus_effect_buffer[i], out, send_chorus);
		}
	}
	memset(delay_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static void mix_variation1_buffer_xg(DATA_T *buf, int32 count)
{
	if (variation_effect_xg[0].connection == XG_CONN_SYSTEM) {	
		int32 i;
		FLOAT_T *pan = variation_effect_xg[0].pan_level;
		__m128d vpan = _mm_set_pd(pan[1], pan[0]);
		__m128d send_reverb = _mm_set1_pd(variation_effect_xg[0].reverb_level),
			send_chorus = _mm_set1_pd(variation_effect_xg[0].chorus_level),
			var_return = _mm_set1_pd(variation_effect_xg[0].return_level);
		var_return = _mm_mul_pd(var_return, vpan);
		send_reverb = _mm_mul_pd(send_reverb, vpan);
		send_chorus = _mm_mul_pd(send_chorus, vpan);
		for (i = 0; i < count; i += 4) {
			__m128d out = _mm_load_pd(&delay_effect_buffer[i]);
			MM_LS_FMA_PD(&buf[i], out, var_return);
			MM_LS_FMA_PD(&reverb_effect_buffer[i], out, send_reverb);
			MM_LS_FMA_PD(&chorus_effect_buffer[i], out, send_chorus);
			out = _mm_load_pd(&delay_effect_buffer[i + 2]);
			MM_LS_FMA_PD(&buf[i + 2], out, var_return);
			MM_LS_FMA_PD(&reverb_effect_buffer[i + 2], out, send_reverb);
			MM_LS_FMA_PD(&chorus_effect_buffer[i + 2], out, send_chorus);
		}
	}
	memset(delay_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void mix_variation1_buffer_xg(DATA_T *buf, int32 count)
{
	if (variation_effect_xg[0].connection == XG_CONN_SYSTEM) {	
		int32 i;
		FLOAT_T *pan = variation_effect_xg[0].pan_level;
		__m128 vpan = _mm_set_ps(pan[1], pan[0], pan[1], pan[0]);
		__m128 send_reverb = _mm_set1_ps(variation_effect_xg[0].reverb_level),
			send_chorus = _mm_set1_ps(variation_effect_xg[0].chorus_level),
			var_return = _mm_set1_ps(variation_effect_xg[0].return_level);
		var_return = _mm_mul_ps(var_return, vpan);
		send_reverb = _mm_mul_ps(send_reverb, vpan);
		send_chorus = _mm_mul_ps(send_chorus, vpan);
		for (i = 0; i < count; i += 8) {
			__m128 out = _mm_load_ps(&delay_effect_buffer[i]);
			MM_LS_FMA_PS(&buf[i], out, var_return);
			MM_LS_FMA_PS(&reverb_effect_buffer[i], out, send_reverb);
			MM_LS_FMA_PS(&chorus_effect_buffer[i], out, send_chorus);
			out = _mm_load_ps(&delay_effect_buffer[i + 4]);
			MM_LS_FMA_PS(&buf[i + 4], out, var_return);
			MM_LS_FMA_PS(&reverb_effect_buffer[i + 4], out, send_reverb);
			MM_LS_FMA_PS(&chorus_effect_buffer[i + 4], out, send_chorus);
		}
	}
	memset(delay_effect_buffer, 0, sizeof(DATA_T) * count);
}
#else /* floating-point implementation */
static void mix_variation1_buffer_xg(DATA_T *buf, int32 count)
{
	if (variation_effect_xg[0].connection == XG_CONN_SYSTEM) {	
		int32 i;
		DATA_T x;
		FLOAT_T *pan = variation_effect_xg[0].pan_level;
		FLOAT_T send_reverb = variation_effect_xg[0].reverb_level;
		FLOAT_T send_chorus = variation_effect_xg[0].chorus_level;
		FLOAT_T var_return = variation_effect_xg[0].return_level;
		for (i = 0; i < count; i++) {
			x = delay_effect_buffer[i] * pan[0];
			buf[i] += x * var_return;
			reverb_effect_buffer[i] += x * send_reverb;
			chorus_effect_buffer[i] += x * send_chorus;
			++i;
			x = delay_effect_buffer[i] * pan[1];
			buf[i] += x * var_return;
			reverb_effect_buffer[i] += x * send_reverb;
			chorus_effect_buffer[i] += x * send_chorus;
		}
	}
	memset(delay_effect_buffer, 0, sizeof(DATA_T) * count);
}
#endif /* OPT_MODE != 0 */

void do_variation_effect1_xg(DATA_T *buf, int32 count)
{
	if (variation_effect_xg[0].connection == XG_CONN_SYSTEM) {
		do_effect_list(delay_effect_buffer, count, variation_effect_xg[0].ef);
		mix_variation1_buffer_xg(buf, count);
	}else{
		memset(delay_effect_buffer, 0, sizeof(DATA_T) * count);
	}
}



#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static void mix_chorus_buffer_xg(DATA_T *buf, int32 count)
{
	int32 i, x;
	int32 panli = TIM_FSCALE((double)chorus_status_xg.pan_level[0], 24);
	int32 panri = TIM_FSCALE((double)chorus_status_xg.pan_level[1], 24);
	int32 send_reverbi = TIM_FSCALE((double)chorus_status_xg.reverb_level, 24);
	int32 cho_returni = TIM_FSCALE((double)chorus_status_xg.return_level, 24);
	for (i = 0; i < count; i++) {
		x = imuldiv24(chorus_effect_buffer[i], panli);
		buf[i] += imuldiv24(x, cho_returni);
		reverb_effect_buffer[i] += imuldiv24(x, send_reverbi);
		++i;
		x = imuldiv24(chorus_effect_buffer[i], panri);
		buf[i] += imuldiv24(x, cho_returni);
		reverb_effect_buffer[i] += imuldiv24(x, send_reverbi);
	}
	memset(chorus_effect_buffer, 0, sizeof(int32) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static void mix_chorus_buffer_xg(DATA_T *buf, int32 count)
{
	int32 i;
	FLOAT_T *pan = chorus_status_xg.pan_level;
	__m128d vpanx = _mm_set_pd(pan[1], pan[0]);
	__m256d vpan = MM256_SET2X_PD(vpanx, vpanx);
	__m256d send_reverb = _mm256_set1_pd(chorus_status_xg.chorus_level),
		cho_return = _mm256_set1_pd(chorus_status_xg.return_level);
	cho_return = _mm256_mul_pd(cho_return, vpan);
	send_reverb = _mm256_mul_pd(send_reverb, vpan);	
	for (i = 0; i < count; i += 8) {
		__m256d out = _mm256_load_pd(&chorus_effect_buffer[i]);
		MM256_LS_FMA_PD(&buf[i], out, cho_return);
		MM256_LS_FMA_PD(&reverb_effect_buffer[i], out, send_reverb);
		out = _mm256_load_pd(&chorus_effect_buffer[i + 4]);
		MM256_LS_FMA_PD(&buf[i + 4], out, cho_return);
		MM256_LS_FMA_PD(&reverb_effect_buffer[i + 4], out, send_reverb);
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static void mix_chorus_buffer_xg(DATA_T *buf, int32 count)
{
	int32 i;
	FLOAT_T *pan = chorus_status_xg.pan_level;
	__m128 vpanx = _mm_set_ps(pan[1], pan[0], pan[1], pan[0]);
	__m256 vpan = MM256_SET2X_PS(vpanx, vpanx);
	__m256 send_reverb = _mm256_set1_ps(chorus_status_xg.chorus_level),
		cho_return = _mm256_set1_ps(chorus_status_xg.return_level);
	cho_return = _mm256_mul_ps(cho_return, vpan);
	send_reverb = _mm256_mul_ps(send_reverb, vpan);	
	for (i = 0; i < count; i += 8) {
		__m256 out = _mm256_load_ps(&chorus_effect_buffer[i]);
		MM256_LS_FMA_PS(&buf[i], out, cho_return);
		MM256_LS_FMA_PS(&reverb_effect_buffer[i], out, send_reverb);
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static void mix_chorus_buffer_xg(DATA_T *buf, int32 count)
{
	int32 i;
	FLOAT_T *pan = chorus_status_xg.pan_level;
	__m128d vpan = _mm_set_pd(pan[1], pan[0]);
	__m128d send_reverb = _mm_set1_pd(chorus_status_xg.chorus_level),
		cho_return = _mm_set1_pd(chorus_status_xg.return_level);
	cho_return = _mm_mul_pd(cho_return, vpan);
	send_reverb = _mm_mul_pd(send_reverb, vpan);	
	for (i = 0; i < count; i += 4) {
		__m128d out = _mm_load_pd(&chorus_effect_buffer[i]);
		MM_LS_FMA_PD(&buf[i], out, cho_return);
		MM_LS_FMA_PD(&reverb_effect_buffer[i], out, send_reverb);
		out = _mm_load_pd(&chorus_effect_buffer[i + 2]);
		MM_LS_FMA_PD(&buf[i + 2], out, cho_return);
		MM_LS_FMA_PD(&reverb_effect_buffer[i + 2], out, send_reverb);
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static void mix_chorus_buffer_xg(DATA_T *buf, int32 count)
{
	int32 i;
	FLOAT_T *pan = chorus_status_xg.pan_level;
	__m128 vpan = _mm_set_ps(pan[1], pan[0], pan[1], pan[0]);
	__m128 send_reverb = _mm_set1_ps(chorus_status_xg.chorus_level),
		cho_return = _mm_set1_ps(chorus_status_xg.return_level);
	cho_return = _mm_mul_ps(cho_return, vpan);
	send_reverb = _mm_mul_ps(send_reverb, vpan);	
	for (i = 0; i < count; i += 8) {
		__m128 out = _mm_load_ps(&chorus_effect_buffer[i]);
		MM_LS_FMA_PS(&buf[i], out, cho_return);
		MM_LS_FMA_PS(&reverb_effect_buffer[i], out, send_reverb);
		out = _mm_load_ps(&chorus_effect_buffer[i + 4]);
		MM_LS_FMA_PS(&buf[i + 4], out, cho_return);
		MM_LS_FMA_PS(&reverb_effect_buffer[i + 4], out, send_reverb);
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#else /* floating-point implementation */
static void mix_chorus_buffer_xg(DATA_T *buf, int32 count)
{
	int32 i;
	DATA_T x;
	FLOAT_T *pan = chorus_status_xg.pan_level;
	FLOAT_T send_reverb = chorus_status_xg.reverb_level;
	FLOAT_T cho_return = chorus_status_xg.return_level;
	for (i = 0; i < count; i++) {
		x = chorus_effect_buffer[i] * pan[0];
		buf[i] += x * cho_return;
		reverb_effect_buffer[i] += x * send_reverb;
		++i;
		x = chorus_effect_buffer[i] * pan[1];
		buf[i] += x * cho_return;
		reverb_effect_buffer[i] += x * send_reverb;
	}
	memset(chorus_effect_buffer, 0, sizeof(DATA_T) * count);
}
#endif /* OPT_MODE != 0 */

void do_ch_chorus_xg(DATA_T *buf, int32 count)
{
#ifdef VST_LOADER_ENABLE
#if defined(VSTWRAP_EXT) // if support chorus VST
	if (hVSTHost != NULL && opt_normal_chorus_plus == 6){
		do_chorus_vst(chorus_effect_buffer, count);
	}else
#endif
#endif
	do_effect_list(chorus_effect_buffer, count, chorus_status_xg.ef);
	mix_chorus_buffer_xg(buf, count);
}



#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */
static inline void mix_reverb_buffer_xg(DATA_T *buf, int32 count)
{
	int32 i;
	int32 rev_return[2] = {
		TIM_FSCALE((double)reverb_status_xg.pan_level[0] * reverb_status_xg.return_level, 24),
		TIM_FSCALE((double)reverb_status_xg.pan_level[1] * reverb_status_xg.return_level, 24),
	};
	for (i = 0; i < count; i++) {
		buf[i] += imuldiv24(reverb_effect_buffer[i], rev_return[0]);
		++i;
		buf[i] += imuldiv24(reverb_effect_buffer[i], rev_return[1]);
	}
	memset(reverb_effect_buffer, 0, sizeof(int32) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
static inline void mix_reverb_buffer_xg(DATA_T *buf, int32 count)
{
	int32 i;
	FLOAT_T *pan = reverb_status_xg.pan_level;
	__m128d vpanx = _mm_set_pd(pan[1], pan[0]);
	__m256d vpan = MM256_SET2X_PD(vpanx, vpanx);
	__m256d rev_return = _mm256_set1_pd(reverb_status_xg.return_level);
	rev_return = _mm256_mul_pd(rev_return, vpan);
	for (i = 0; i < count; i += 8){
		MM256_LS_FMA_PD(&buf[i], _mm256_load_pd(&reverb_effect_buffer[i]), rev_return);
		MM256_LS_FMA_PD(&buf[i + 4], _mm256_load_pd(&reverb_effect_buffer[i + 4]), rev_return);
	}
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
static inline void mix_reverb_buffer_xg(DATA_T *buf, int32 count)
{
	int32 i;
	FLOAT_T *pan = reverb_status_xg.pan_level;
	__m128 vpanx = _mm_set_ps(pan[1], pan[0], pan[1], pan[0]);
	__m256 vpan = MM256_SET2X_PS(vpanx, vpanx);
	__m256 rev_return = _mm256_set1_ps(reverb_status_xg.return_level);
	rev_return = _mm256_mul_ps(rev_return, vpan);
	for (i = 0; i < count; i += 8)
		MM256_LS_FMA_PS(&buf[i], _mm256_load_ps(&reverb_effect_buffer[i]), rev_return);
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
static inline void mix_reverb_buffer_xg(DATA_T *buf, int32 count)
{
	int32 i;
	FLOAT_T *pan = reverb_status_xg.pan_level;
	__m128d vpan = _mm_set_pd(pan[1], pan[0]);
	__m128d rev_return = _mm_set1_pd(reverb_status_xg.return_level);
	rev_return = _mm_mul_pd(rev_return, vpan);
	for (i = 0; i < count; i += 8){
		MM_LS_FMA_PD(&buf[i], _mm_load_pd(&reverb_effect_buffer[i]), rev_return);
		MM_LS_FMA_PD(&buf[i + 2], _mm_load_pd(&reverb_effect_buffer[i + 2]), rev_return);
		MM_LS_FMA_PD(&buf[i + 4], _mm_load_pd(&reverb_effect_buffer[i + 4]), rev_return);
		MM_LS_FMA_PD(&buf[i + 6], _mm_load_pd(&reverb_effect_buffer[i + 6]), rev_return);
	}
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#elif (USE_X86_EXT_INTRIN >= 2) && defined(DATA_T_FLOAT)
static inline void mix_reverb_buffer_xg(DATA_T *buf, int32 count)
{
	int32 i;
	FLOAT_T *pan = reverb_status_xg.pan_level;
	__m128 vpan = _mm_set_ps(pan[1], pan[0], pan[1], pan[0]);
	__m128 rev_return = _mm_set1_ps(reverb_status_xg.return_level);
	rev_return = _mm_mul_ps(rev_return, vpan);
	for (i = 0; i < count; i += 8){
		MM_LS_FMA_PS(&buf[i], _mm_load_ps(&reverb_effect_buffer[i]), rev_return);
		MM_LS_FMA_PS(&buf[i + 4], _mm_load_ps(&reverb_effect_buffer[i + 4]), rev_return);
	}
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#else /* floating-point implementation */
static inline void mix_reverb_buffer_xg(DATA_T *buf, int32 count)
{
	int32 i;
	DATA_T x;
	FLOAT_T rev_return[2] = {
		reverb_status_xg.pan_level[0] * reverb_status_xg.return_level,
		reverb_status_xg.pan_level[1] * reverb_status_xg.return_level,
	};
	for (i = 0; i < count; i++) {
		buf[i] += reverb_effect_buffer[i] * rev_return[0];
		++i;
		buf[i] += reverb_effect_buffer[i] * rev_return[1];
	}
	memset(reverb_effect_buffer, 0, sizeof(DATA_T) * count);
}
#endif

void do_ch_reverb_xg(DATA_T *buf, int32 count)
{
#ifdef VST_LOADER_ENABLE
#if defined(VSTWRAP_EXT) // if support reverb VST
	if (hVSTHost != NULL && (opt_reverb_control >= 9 || opt_reverb_control <= -1024)){
		do_reverb_vst(reverb_effect_buffer, count);
	}else
#endif
#endif
	do_effect_list(reverb_effect_buffer, count, reverb_status_xg.ef);
	mix_reverb_buffer_xg(buf, count);
}


//double xg_system_return_level = 1.0;
double xg_reverb_return_level = 1.0;
double xg_chorus_return_level = 1.0;
double xg_variation_return_level = 1.0;
double xg_chorus_send_reverb = 1.0;
double xg_variation_send_reverb = 1.0;
double xg_variation_send_chorus = 1.0;
#define XG_SEND_RETURN_DB (6.0) // xg spec +6db
#define XG_SEND_RETURN_PAN_LEVEL (1.0)

static FLOAT_T calc_xg_return(int8 ret)
{
	// XG v1.35 : -inf[dB]~0[dB]~6[dB] (0~64~127)
	// MU100 manual :0[dB] 96 typo?
	if(ret < 1)
		return 0.0;
	else if(ret == 0x40)
		return 1.0;
	else{
#if 1 // -/+が別カーブ
		FLOAT_T val = ret - 0x40;
		if(ret > 0x40)
			return pow(10.0, val * DIV_64 * XG_SEND_RETURN_DB * DIV_20); // +6db
		else
			return pow(10.0, val * DIV_20); // -64db?
#elif 1 // -/+が同カーブ
		return pow(10.0, (FLOAT_T)(ret - 0x40) * DIV_64 * XG_SEND_RETURN_DB * DIV_20); // -dBが+dBと同じかどうかは不明
#elif 1 // mu100 man , -/+が別カーブ
		FLOAT_T val = ret - 0x60;
		if(ret > 0x60)
			return pow(10.0, val * DIV_32 * XG_SEND_RETURN_DB * DIV_20); // +6db
		else
			return pow(10.0, val * DIV_20); // -96db
#else // mu100 man , -/+が同カーブ
		return pow(10.0, (FLOAT_T)(ret - 0x60) * DIV_32 * XG_SEND_RETURN_DB * DIV_20); // -18db~6db
#endif
	}
}

void calc_send_return_xg(struct effect_xg_t *st)
{
	st->pan_level[0] = calc_pan_xg_left(st->pan) * XG_SEND_RETURN_PAN_LEVEL; // pan64=1.0?
	st->pan_level[1] = calc_pan_xg_right(st->pan) * XG_SEND_RETURN_PAN_LEVEL; // pan64=1.0?

	switch(st->connection){
	case XG_CONN_INSERTION:
		st->return_level = 1.0;
		st->reverb_level = 0.0;
		st->chorus_level = 0.0;
		break;
	case XG_CONN_SYSTEM: // variation
		st->return_level = calc_xg_return(st->ret)
			* xg_variation_return_level; // * xg_system_return_level;
		st->reverb_level = calc_xg_return(st->send_reverb)
			* xg_variation_send_reverb;
		st->chorus_level = calc_xg_return(st->send_chorus)
			* xg_variation_send_chorus;
		break;
	case XG_CONN_SYSTEM_CHORUS:
		st->return_level = calc_xg_return(st->ret)
			* xg_chorus_return_level; // * xg_system_return_level;
		st->reverb_level = calc_xg_return(st->send_reverb)
			* xg_chorus_send_reverb;
		st->chorus_level = 0.0;
		break;
	case XG_CONN_SYSTEM_REVERB:
		st->return_level = calc_xg_return(st->ret)
			* xg_reverb_return_level; // * xg_system_return_level;
		st->reverb_level = 0.0;
		st->chorus_level = 0.0;
		break;
	}
}

void init_ch_effect_xg(void)
{
	memset(reverb_effect_buffer, 0, sizeof(reverb_effect_buffer));
	memset(chorus_effect_buffer, 0, sizeof(chorus_effect_buffer));
	memset(delay_effect_buffer, 0, sizeof(delay_effect_buffer));
}







void alloc_effect(EffectList *ef)
{
	int i;

	ef->engine = NULL;
	for(i = 0; effect_engine[i].type != -1; i++) {
		if (effect_engine[i].type == ef->type) {
			ef->engine = &(effect_engine[i]);
			break;
		}
	}
	if (ef->engine == NULL) {return;}

	if (ef->info != NULL) {
		free(ef->info);
		ef->info = NULL;
	}
	ef->info = safe_malloc(ef->engine->info_size);
	/*  EFX BUFFER  */
#ifdef ALIGN_SIZE
	if(ef->efx_buf != NULL){
		aligned_free(ef->efx_buf);
		ef->efx_buf = NULL;
	}
	ef->efx_buf = (DATA_T *)aligned_malloc(synth_buffer_size, ALIGN_SIZE);
#else
	if(ef->efx_buf != NULL){
		free(ef->efx_buf);
		ef->efx_buf = NULL;
	}
	ef->efx_buf = (DATA_T *)safe_malloc(synth_buffer_size);
#endif
	memset(ef->info, 0, ef->engine->info_size);
/*	ctl->cmsg(CMSG_INFO, VERB_NOISY, "Effect Engine: %s", ef->engine->name); */
}

/*! allocate new effect item and add it into the tail of effect list.
    EffectList *efc: pointer to the top of effect list.
    int8 type: type of new effect item.
    void *info: pointer to infomation of new effect item. */
EffectList *push_effect(EffectList *efc, int type)
{
	EffectList *eft, *efn;
	if (type == EFFECT_NONE) {return NULL;}
	efn = (EffectList *)safe_malloc(sizeof(EffectList));
	memset(efn, 0, sizeof(EffectList));
	efn->type = type;
	efn->next_ef = NULL;
	efn->info = NULL;
	efn->efx_buf = NULL; //
	alloc_effect(efn);

	if(efc == NULL) {
		efc = efn;
	} else {
		eft = efc;
		while(eft->next_ef != NULL) {
			eft = eft->next_ef;
		}
		eft->next_ef = efn;
	}
	return efc;
}

/*! process all items of effect list. */
void do_effect_list(DATA_T *buf, int32 count, EffectList *ef)
{
	EffectList *efc = ef;
	if(ef == NULL) {return;}
	while(efc != NULL && efc->engine->do_effect != NULL)
	{
		(*efc->engine->do_effect)(buf, count, efc);
		efc = efc->next_ef;
	}
}

/*! free all items of effect list. */
void free_effect_list(EffectList *ef)
{
	EffectList *efc, *efn;
	efc = ef;
	if (efc == NULL) {return;}
	do {
		efn = efc->next_ef;
		if(efc->info != NULL) {
			(*efc->engine->do_effect)(NULL, MAGIC_FREE_EFFECT_INFO, efc);
			free(efc->info);
			efc->info = NULL;
		}
		if(efc->efx_buf != NULL){
#ifdef ALIGN_SIZE
			aligned_free(efc->efx_buf);
#else
			free(efc->efx_buf);
#endif
			efc->efx_buf = NULL;
		}
		efc->engine = NULL;
		free(efc);
		efc = NULL;
	} while ((efc = efn) != NULL);
}


static void free_effect_gs(struct insertion_effect_gs_t *st)
{
	free_effect_list(st->ef);
	st->ef = NULL;
}

static void free_effect_xg(struct effect_xg_t *st)
{
	free_effect_list(st->ef);
	st->ef = NULL;	
}

static void free_effect_sd(struct mfx_effect_sd_t *st)
{
	free_effect_list(st->ef);
	st->ef = NULL;	
}

void free_effect_buffers(void)
{
	int i;
	/* free GM/GS/GM2 effects */
	do_ch_standard_reverb(NULL, MAGIC_FREE_EFFECT_INFO, &(reverb_status_gs));
	do_ch_freeverb(NULL, MAGIC_FREE_EFFECT_INFO, &(reverb_status_gs));
	do_ch_reverb_ex(NULL, MAGIC_FREE_EFFECT_INFO, &(reverb_status_gs));
	do_ch_reverb_ex2(NULL, MAGIC_FREE_EFFECT_INFO, &(reverb_status_gs));
	do_ch_plate_reverb(NULL, MAGIC_FREE_EFFECT_INFO, &(reverb_status_gs));
	do_ch_reverb_normal_delay(NULL, MAGIC_FREE_EFFECT_INFO, &(reverb_status_gs));
	do_ch_chorus_free(NULL, MAGIC_FREE_EFFECT_INFO, &(chorus_status_gs.info_stereo_chorus));
	do_ch_3tap_delay(NULL, MAGIC_FREE_EFFECT_INFO, &(delay_status_gs.info_delay));
	free_effect_gs(&insertion_effect_gs);
	/* free XG effects */
	free_effect_xg(&reverb_status_xg);
	free_effect_xg(&chorus_status_xg);
	for (i = 0; i < XG_VARIATION_EFFECT_NUM; i++) {
		free_effect_xg(&variation_effect_xg[i]);
	}
	for (i = 0; i < XG_INSERTION_EFFECT_NUM; i++) {
		free_effect_xg(&insertion_effect_xg[i]);
	}
	free_effect_sd(&reverb_status_sd);
	free_effect_sd(&chorus_status_sd);
	for (i = 0; i < SD_MFX_EFFECT_NUM; i++) {
		free_effect_sd(&mfx_effect_sd[i]);
	}		
}



/********************************** GS EFFECT conv **********************************/

/**************** GS INSERTION conv ****************/
// post EQ
static void conv_gs_post_eq(struct insertion_effect_gs_t *ieffect, EffectList *ef)
{
	Info_GS_PostEQ *info = (Info_GS_PostEQ *)ef->info; 
	InfoEQ2 *eq = &info->eq; 

	eq->mode = CH_STEREO;
	eq->high_freq = 4000;
	eq->high_gain = clip_int(ieffect->parameter[17] - 0x40, -12, 12);
	eq->low_freq = 400;
	eq->low_gain = clip_int(ieffect->parameter[16] - 0x40, -12, 12);
}

void do_gs_post_eq(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_PostEQ *info = (Info_GS_PostEQ *)ef->info;
	InfoEQ2 *eq = &info->eq; 

	do_eq2_multi(buf, count, eq);
}

/***** MSB 01 *****/
/** LSB 0x **/
const FLOAT_T eq_q_table_gs[] ={ 0.5, 1.0, 2.0, 4.0, 9.0,};

static void conv_gs_stereo_eq(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_StereoEQ *info = (Info_GS_StereoEQ *)ef->info;
	InfoStereoEQ *eq = &info->eq;
	
	eq->low_freq = (st->parameter[0] == 0) ? 200 : 400;
	eq->low_gain = clip_int(st->parameter[1] - 64, -12, 12);
	eq->high_freq = (st->parameter[2] == 0) ? 4000 : 8000;
	eq->high_gain = clip_int(st->parameter[3] - 64, -12, 12);
	eq->m1_freq = eq_freq_table_gs[st->parameter[4]];
	eq->m1_q = eq_q_table_gs[clip_int(st->parameter[5], 0, 4)];
	eq->m1_gain = clip_int(st->parameter[6] - 64, -12, 12);
	eq->m2_freq = eq_freq_table_gs[st->parameter[7]];
	eq->m2_q = eq_q_table_gs[clip_int(st->parameter[8], 0, 4)];
	eq->m2_gain = clip_int(st->parameter[9] - 64, -12, 12);
	info->level = calc_gs_level(st->parameter[19]);
}

void do_gs_stereo_eq(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_StereoEQ *info = (Info_GS_StereoEQ *)ef->info;
	InfoStereoEQ *eq = &info->eq;

	do_stereo_eq(buf, count, eq);
	effect_level_stereo(buf, count, info->level);
}

static void conv_gs_spectrum(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_Spectrum *info = (Info_GS_Spectrum *)ef->info;
	InfoSpectrum *eq = &info->eq;

	eq->mode = CH_LEFT;
	eq->freq[0] = 250;
	eq->freq[1] = 500;
	eq->freq[2] = 1000;
	eq->freq[3] = 1250;
	eq->freq[4] = 2000;
	eq->freq[5] = 3150;
	eq->freq[6] = 4000;
	eq->freq[7] = 8000;
	eq->gain[0] = clip_int(st->parameter[0] - 64, -12, 12);
	eq->gain[1] = clip_int(st->parameter[1] - 64, -12, 12);
	eq->gain[2] = clip_int(st->parameter[2] - 64, -12, 12);
	eq->gain[3] = clip_int(st->parameter[3] - 64, -12, 12);
	eq->gain[4] = clip_int(st->parameter[4] - 64, -12, 12);
	eq->gain[5] = clip_int(st->parameter[5] - 64, -12, 12);
	eq->gain[6] = clip_int(st->parameter[6] - 64, -12, 12);
	eq->gain[7] = clip_int(st->parameter[7] - 64, -12, 12);
	eq->width = (double)eq_q_table_gs[clip_int(st->parameter[8], 0, 4)];
	info->panl = calc_pan_gs_left(st->parameter[18]);
	info->panr = calc_pan_gs_right(st->parameter[18]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_spectrum(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_Spectrum *info = (Info_GS_Spectrum *)ef->info;
	InfoSpectrum *eq = &info->eq;

	effect_mix_mono(buf, count);
	do_spectrum(buf, count, eq);
	effect_panning_mono_stereo(buf, count, info->panl, info->panr);
	effect_level_stereo(buf, count, info->level);
}

static void conv_gs_enhancer(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_Enhancer *info = (Info_GS_Enhancer *)ef->info;
	InfoEnhancer *eh = &info->eh;

	// Enhancer
	eh->mode = CH_STEREO;
	eh->hpf_cutoff = 3200;
	eh->sens = (double)st->parameter[0] * DIV_127;	
	info->wet = (double)st->parameter[1] * DIV_127;	
	info->dry = 1.0;
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_enhancer(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_Enhancer *info = (Info_GS_Enhancer *)ef->info;
	InfoEnhancer *eh = &info->eh;

	send_efx_buffer(ef, buf, count);
	do_enhancer_multi(ef->efx_buf, count, eh);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_gs_humanizer(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_Humanizer *info = (Info_GS_Humanizer *)ef->info;
	InfoHumanizer *hm = &info->hm;

	hm->mode = CH_MONO;
	hm->drive = 1.0 + (double)st->parameter[0] * DIV_127 * 3.0;
	hm->od_sw = st->parameter[1] ? 1 : 0;
	hm->vowel = clip_int(st->parameter[2], 0, 4);
	hm->accel = 16.0 * 2000.0 / (double)(st->parameter[3] + 16); // ms 2000ms~223.776ms
	info->panl = calc_pan_gs_left(st->parameter[18]);
	info->panr = calc_pan_gs_right(st->parameter[18]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_humanizer(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_Humanizer *info = (Info_GS_Humanizer *)ef->info;
	InfoHumanizer *hm = &info->hm;

	effect_mix_mono(buf, count);
	do_humanizer(buf, count, hm);
	effect_panning_mono_stereo(buf, count, info->panl, info->panr);
	effect_level_stereo(buf, count, info->level);
}

/** LSB 1x **/
static void conv_gs_overdrive(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_Overdrive *info = (Info_GS_Overdrive *)ef->info;
	InfoOverdrive *od = &info->od;
	
	od->mode = CH_MIX_MONO;
	od->type = 0; // od
	od->drive = st->parameter[0];
	od->amp_type = st->parameter[1];
	od->amp_sw = st->parameter[2] ? 1 : 0;
	od->level = 1.0; 
	info->panl = calc_pan_gs_left(st->parameter[18]);
	info->panr = calc_pan_gs_right(st->parameter[18]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_overdrive(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_Overdrive *info = (Info_GS_Overdrive *)ef->info;
	InfoOverdrive *od = &info->od;
	
	effect_mix_mono(buf, count);
	do_od_ds_multi(buf, count, od);
	effect_panning_mono_stereo(buf, count, info->panl, info->panr);
	effect_level_stereo(buf, count, info->level);
}

static void conv_gs_distortion(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_Overdrive *info = (Info_GS_Overdrive *)ef->info;
	InfoOverdrive *od = &info->od;	

	od->mode = CH_MIX_MONO;
	od->type = 1; // od
	od->drive = st->parameter[0];
	od->amp_type = st->parameter[1];
	od->amp_sw = st->parameter[2] ? 1 : 0;
	od->level = 1.0; 
	info->panl = calc_pan_gs_left(st->parameter[18]);
	info->panr = calc_pan_gs_right(st->parameter[18]);
	info->level = calc_gs_level(st->parameter[19]);	
}

static void do_gs_distortion(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_Overdrive *info = (Info_GS_Overdrive *)ef->info;
	InfoOverdrive *od = &info->od;
	
	do_od_ds_multi(buf, count, od);
	effect_panning_mono_stereo(buf, count, info->panl, info->panr);
	effect_level_stereo(buf, count, info->level);
}

/** LSB 2x **/
static void conv_gs_phaser(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_Phaser *info = (Info_GS_Phaser *)ef->info;
	InfoPhaser *ph = &info->ph;

	ph->mode = CH_STEREO;
	ph->phase = 4;
	ph->manual = (double)manual_table[st->parameter[0]];
	ph->rate = (double)rate1_table[st->parameter[1]];
	ph->depth_cent = calc_chorus_depth_gs(st->parameter[2]);	
	ph->offset = 0.5;
	ph->phase_diff = 0; // deg 0~360
	ph->reso = (double)st->parameter[3] * DIV_127 * 12.0; // 12dB
	info->wet = calc_wet_gs(st->parameter[4]);
	info->dry = 1.0; //calc_dry_gs(st->parameter[4]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_phaser(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_Phaser *info = (Info_GS_Phaser *)ef->info;
	InfoPhaser *ph = &info->ph;
		
	send_efx_buffer(ef, buf, count);
	do_phaser_multi(ef->efx_buf, count, ph);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_gs_auto_wah(struct insertion_effect_gs_t *st, EffectList *ef)
{	
	Info_GS_AutoWah *info = (Info_GS_AutoWah *)ef->info;
	InfoAutoWah *aw = &info->aw;

	aw->mode = CH_MIX_MONO;
	aw->type = st->parameter[0] ? 1 : 0;
	aw->sens = calc_auto_wah_sens_gs(st->parameter[1]);	
	aw->release = 100.0; // ms
	aw->manual = calc_auto_wah_manual_gs(st->parameter[2]);
	aw->peak = calc_auto_wah_peak_gs(st->parameter[3]);
	aw->rate = (double)rate1_table[st->parameter[4]];
	aw->depth = (double)st->parameter[5] * DIV_127;
	aw->pol = st->parameter[6] ? 1 : 0;
	aw->lfo_sw = 1; // on
	aw->sens_sw = 1; // on
	info->panl = calc_pan_gs_left(st->parameter[18]);
	info->panr = calc_pan_gs_right(st->parameter[18]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_auto_wah(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_AutoWah *info = (Info_GS_AutoWah *)ef->info;
	InfoAutoWah *aw = &info->aw;

	do_auto_wah_multi(buf, count, aw);
	effect_panning_mono_stereo(buf, count, info->panl, info->panr);
	effect_level_stereo(buf, count, info->level);
}

static void conv_gs_rotary(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_Rotary *info = (Info_GS_Rotary *)ef->info;
	InfoRotary *rt = &info->rt;

	rt->mode = CH_MIX_STEREO;
	rt->low_slow = (double)rate1_table[st->parameter[0]];
	rt->low_fast = (double)rate1_table[st->parameter[1]];
	rt->low_accl = (double)st->parameter[2] * DIV_127;
	rt->low_level = calc_option_level(st->parameter[3]);
	rt->hi_slow = (double)rate1_table[st->parameter[4]];
	rt->hi_fast = (double)rate1_table[st->parameter[5]];
	rt->hi_accl = (double)st->parameter[6] * DIV_127;
	rt->hi_level = calc_option_level(st->parameter[7]);
	rt->separate = (double)st->parameter[8] * DIV_127;
	rt->speed = st->parameter[10] ? 1 : 0;
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_rotary(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_Rotary *info = (Info_GS_Rotary *)ef->info;
	InfoRotary *rt = &info->rt;

	do_rotary_multi(buf, count, rt);
	effect_level_stereo(buf, count, info->level);
}

static void conv_gs_stereo_flanger(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_StereoFlanger *info = (Info_GS_StereoFlanger *)ef->info;
	InfoStereoChorus *fl = &info->fl;

	fl->mode = CH_STEREO;
	fl->phase = 3;
	fl->filter_type = clip_int(st->parameter[0], 0, 2);
	fl->filter_cutoff = cutoff_freq_table_gs[st->parameter[1]];
	fl->pdelay_ms = (double)pre_delay_time_table[st->parameter[2]];
	fl->rate = (double)rate1_table[st->parameter[3]];
	fl->depth_cent = calc_chorus_depth_gs(st->parameter[4]);
	fl->feedback = (double)(st->parameter[5] - 64) * (0.763 * 2.0 * DIV_100);
	fl->phase_diff = (double)2.0 * clip_int(st->parameter[6], 0, 0x5A); // 0~180
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	info->wet = calc_wet_gs(st->parameter[15]);
	info->dry = calc_dry_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_stereo_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_StereoFlanger *info = (Info_GS_StereoFlanger *)ef->info;
	InfoStereoChorus *fl = &info->fl;
	
	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, fl);
	do_chorus_ex(ef->efx_buf, count, fl);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_gs_step_flanger(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_StepFlanger *info = (Info_GS_StepFlanger *)ef->info;
	InfoStereoChorus *fl = &info->fl;

	fl->mode = CH_STEREO;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = cutoff_freq_table_gs[127];
	fl->pdelay_ms = (double)pre_delay_time_table[st->parameter[0]];
	fl->rate = (double)rate1_table[st->parameter[1]];
	fl->depth_cent = calc_chorus_depth_gs(st->parameter[2]);
	fl->feedback = (double)(st->parameter[3] - 64) * (0.763 * 2.0 * DIV_100);
	fl->phase_diff = (double)2.0 * clip_int(st->parameter[4], 0, 0x5A); // 0~180
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	info->wet = calc_wet_gs(st->parameter[15]);
	info->dry = calc_dry_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_step_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_StereoFlanger *info = (Info_GS_StereoFlanger *)ef->info;
	InfoStereoChorus *fl = &info->fl;
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, fl);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

const int lfo_wave_table_gs[] = {OSC_TYPE_TRIANGULAR, OSC_TYPE_SQUARE, OSC_TYPE_SINE, OSC_TYPE_SAW1, OSC_TYPE_SAW2,};

static void conv_gs_tremolo(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_Tremolo *info = (Info_GS_Tremolo *)ef->info;
	InfoTremolo *trm = &info->trm;

	trm->mode = CH_STEREO;
	trm->type = 0;
	trm->phase = 0; // deg
	trm->wave = lfo_wave_table_gs[clip_int(st->parameter[0], 0, 4)];
	trm->rate = (double)rate1_table[st->parameter[1]];
	trm->depth = (double)st->parameter[2] * DIV_127;
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_tremolo(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_Tremolo *info = (Info_GS_Tremolo *)ef->info;
	InfoTremolo *trm = &info->trm;

	do_tremolo_autopan(buf, count, trm);
	effect_level_stereo(buf, count, info->level);
}

static void conv_gs_auto_pan(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_Tremolo *info = (Info_GS_Tremolo *)ef->info;
	InfoTremolo *trm = &info->trm;

	trm->mode = CH_STEREO;
	trm->type = 1;
	trm->phase = 180; // deg
	trm->wave = lfo_wave_table_gs[clip_int(st->parameter[0], 0, 4)];
	trm->rate = (double)rate1_table[st->parameter[1]];
	trm->depth = (double)st->parameter[2] * DIV_127;
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_auto_pan(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_AutoPan *info = (Info_GS_AutoPan *)ef->info;
	InfoTremolo *trm = &info->trm;

	do_tremolo_autopan(buf, count, trm);
	effect_level_stereo(buf, count, info->level);
}

/** LSB 3x **/
const FLOAT_T cmp_lmt_gain_table_gs[] = {0.0, 6.0, 12.0, 18.0,};

static void conv_gs_compressor(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_Compressor *info = (Info_GS_Compressor *)ef->info;
	InfoCompressor *cmp = &info->cmp;

	cmp->mode = CH_MIX_MONO;
	cmp->attak = mix_double ((double)st->parameter[0] * DIV_127, 10, 500); // 10ms-500ms
	cmp->sustain = mix_double ((double)st->parameter[0] * DIV_127, 10, 500); // 10ms-500ms
	cmp->pre_gain = 6 * (1.0 + (double)st->parameter[1] * DIV_127); // dB
	cmp->post_gain = cmp_lmt_gain_table_gs[clip_int(st->parameter[2], 0, 3)];; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 0.5; // ratio? 1/2
	info->panl = calc_pan_gs_left(st->parameter[18]);
	info->panr = calc_pan_gs_right(st->parameter[18]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_compressor(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_Compressor *info = (Info_GS_Compressor *)ef->info;
	InfoCompressor *cmp = &info->cmp;

	do_compressor_multi(buf, count, cmp);
	effect_panning_mono_stereo(buf, count, info->panl, info->panl);
	effect_level_stereo(buf, count, info->level);
}

const FLOAT_T limiter_ratio_table_gs[] = {1.0 / 1.5, 1.0 / 2.0, 1.0 / 4.0, 1.0 / 100,};

static void conv_gs_limiter(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_Limiter *info = (Info_GS_Limiter *)ef->info;
	InfoLimiter *lmt = &info->lmt;

	lmt->mode = CH_MIX_MONO;
	lmt->threshold = (double)clip_int(st->parameter[0], 1, 127) * DIV_127;
	lmt->ratio = limiter_ratio_table_gs[clip_int(st->parameter[1], 0, 3)];
	lmt->ahead = 10; // 10ms
	lmt->release = mix_double ((double)st->parameter[2] * DIV_127, 10, 200); // 10ms-200ms
	lmt->pre_gain = 0;
	lmt->post_gain = cmp_lmt_gain_table_gs[clip_int(st->parameter[3], 0, 3)];
	info->panl = calc_pan_gs_left(st->parameter[18]);
	info->panr = calc_pan_gs_right(st->parameter[18]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_limiter(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_Limiter *info = (Info_GS_Limiter *)ef->info;
	InfoLimiter *lmt = &info->lmt;

	do_limiter_multi(buf, count, lmt);
	effect_panning_mono_stereo(buf, count, info->panl, info->panl);
	effect_level_stereo(buf, count, info->level);
}

/** LSB 4x **/
static void conv_gs_hexa_chorus(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_HexaChorus *info = (Info_GS_HexaChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;	

	cho->mode = CH_MIX_STEREO;
	cho->phase = 6;
	cho->filter_type = 0; // off
	cho->filter_cutoff = 22000; // 22000Hz
	cho->pdelay_ms = pre_delay_time_table[st->parameter[0]];
	cho->rate = rate1_table[st->parameter[1]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[2]);
	cho->pdelay_dev = st->parameter[3];
	cho->depth_dev = st->parameter[4] - 64;
	cho->pan_dev = st->parameter[5];
	info->dry = calc_dry_gs(st->parameter[15]);
	info->wet = calc_wet_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_hexa_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_HexaChorus *info = (Info_GS_HexaChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_gs_tremolo_chorus(struct insertion_effect_gs_t *st, EffectList *ef)
{	
	Info_GS_TremoloChorus *info = (Info_GS_TremoloChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	InfoTremolo *trm = &info->trm;

	cho->mode = CH_MIX_MONO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = cutoff_freq_table_gs[127];
	cho->pdelay_ms = (double)pre_delay_time_table[st->parameter[0]];
	cho->rate = (double)rate1_table[st->parameter[1]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[2]);
	cho->feedback = 0.0;
	cho->phase_diff = 0.0;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	trm->mode = CH_MONO_STEREO;
	trm->type = 1;
	trm->phase = (double)2.0 * clip_int(st->parameter[3], 0, 0x5A); // 0~180
	trm->wave = lfo_wave_table_gs[0];
	trm->rate = (double)rate1_table[st->parameter[4]];
	trm->depth = (double)st->parameter[5] * DIV_127;
	info->wet = calc_wet_gs(st->parameter[15]);
	info->dry = calc_dry_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_tremolo_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_TremoloChorus *info = (Info_GS_TremoloChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	InfoTremolo *trm = &info->trm;

	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, cho);
	do_chorus_ex(ef->efx_buf, count, cho);
	do_tremolo_autopan(ef->efx_buf, count, trm);	
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_gs_stereo_chorus(struct insertion_effect_gs_t *st, EffectList *ef)
{	
	Info_GS_StereoChorus *info = (Info_GS_StereoChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;	

	cho->mode = CH_STEREO;
	cho->phase = 3;
	cho->filter_type = clip_int(st->parameter[0], 0, 2);
	cho->filter_cutoff = cutoff_freq_table_gs[st->parameter[1]];
	cho->pdelay_ms = (double)pre_delay_time_table[st->parameter[2]];
	cho->rate = (double)rate1_table[st->parameter[3]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[4]);
	cho->feedback = 0.0;
	cho->phase_diff = (double)2.0 * clip_int(st->parameter[6], 0, 0x5A); // 0~180
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	info->wet = calc_wet_gs(st->parameter[15]);
	info->dry = calc_dry_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_stereo_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_StereoChorus *info = (Info_GS_StereoChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_gs_space_d(struct insertion_effect_gs_t *st, EffectList *ef)
{	
	Info_GS_StereoChorus *info = (Info_GS_StereoChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;	

	cho->mode = CH_STEREO;
	cho->phase = 2;
	cho->filter_type = 0;
	cho->filter_cutoff = cutoff_freq_table_gs[127];
	cho->pdelay_ms = (double)pre_delay_time_table[st->parameter[0]];
	cho->rate = (double)rate1_table[st->parameter[1]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[2]);
	cho->feedback = 0.0;
	cho->phase_diff = (double)2.0 * clip_int(st->parameter[3], 0, 0x5A); // 0~180
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	info->wet = calc_wet_gs(st->parameter[15]);
	info->dry = calc_dry_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_space_d(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_SpaceD *info = (Info_GS_SpaceD *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_gs_3d_chorus(struct insertion_effect_gs_t *st, EffectList *ef)
{	
	Info_GS_3DChorus *info = (Info_GS_3DChorus *)ef->info;
	Info3DChorus *cho = &info->cho;	

	cho->mode = CH_MIX_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = cutoff_freq_table_gs[127];
	cho->pdelay_ms = (double)pre_delay_time_table[st->parameter[0]];
	cho->rate = (double)rate1_table[st->parameter[1]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[2]);
	cho->feedback = 0.0;
	cho->phase_diff = 180; // 0~180
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	cho->out = st->parameter[14] ? 1 : 0; // Speaker/Phones
	info->wet = calc_wet_gs(st->parameter[15]);
	info->dry = calc_dry_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_3d_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_3DChorus *info = (Info_GS_3DChorus *)ef->info;
	Info3DChorus *cho = &info->cho;

	send_efx_buffer(ef, buf, count);
	do_3d_chorus(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

/** LSB 5x **/
static void conv_gs_stereo_delay(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_StereoDelay *info = (Info_GS_StereoDelay *)ef->info;
	InfoDelayLR *dly = &info->dly;

	dly->mode = CH_STEREO;
	dly->ldelay = dly->fdelay1 = (double)delay_time_3_table[st->parameter[0]];
	dly->rdelay = dly->fdelay2 = (double)delay_time_3_table[st->parameter[1]];
	dly->feedback = (double)(clip_int(st->parameter[2], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->fb_mode = st->parameter[3] ? 1 : 0;
	dly->phasel = st->parameter[4] ? 1 : 0;
	dly->phaser = st->parameter[5] ? 1 : 0;
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[6]];
	info->dly_wet = calc_wet_gs(st->parameter[15]);
	info->dly_dry = calc_dry_gs(st->parameter[15]);
	info->dly_level = calc_gs_level(st->parameter[19]);
}

static void do_gs_stereo_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_StereoDelay *info = (Info_GS_StereoDelay *)ef->info;
	InfoDelayLR *dly = &info->dly;

	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_gs_mod_delay(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_ModDelay *info = (Info_GS_ModDelay *)ef->info;
	InfoModDelay *dly = &info->dly;	

	dly->ldelay_ms = (double)delay_time_3_table[st->parameter[0]];
	dly->rdelay_ms = (double)delay_time_3_table[st->parameter[1]];
	dly->feedback = (double)(clip_int(st->parameter[2], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->fb_mode = st->parameter[3] ? 1 : 0;
	dly->rate = (double)rate1_table[st->parameter[4]];
	dly->depth_cent = calc_chorus_depth_gs(st->parameter[5]);
	dly->phase = (double)2.0 * clip_int(st->parameter[6], 0, 0x5A); // 0~180
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[7]];
	info->wet = calc_wet_gs(st->parameter[15]);
	info->dry = calc_dry_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_mod_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_ModDelay *info = (Info_GS_ModDelay *)ef->info;
	InfoModDelay *dly = &info->dly;

	send_efx_buffer(ef, buf, count);
	do_mod_delay_multi(ef->efx_buf, count, dly);	
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_gs_3tap_delay(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_3TapDelay *info = (Info_GS_3TapDelay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;
		
	dly->mode = CH_MIX_STEREO;
	dly->tap = 3;
	dly->dtime[0] = (double)delay_time_1_table[st->parameter[0]];
	dly->dtime[1] = (double)delay_time_1_table[st->parameter[1]];
	dly->dtime[2] = (double)delay_time_1_table[st->parameter[2]];
	dly->dtime[3] = dly->dtime[0]; // [tap] for feedback_delay // dtime[0]と同じ
	dly->pan[0] = 0x40;
	dly->pan[1] = 0x00;
	dly->pan[2] = 0x7F;
	dly->pan[3] = 0x40; // [tap] for feedback_delay
	dly->feedback = (double)(clip_int(st->parameter[3], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->dlevel[0] = calc_option_level(st->parameter[4]);
	dly->dlevel[1] = calc_option_level(st->parameter[5]);
	dly->dlevel[2] = calc_option_level(st->parameter[6]);
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[7]];
	info->wet = calc_wet_gs(st->parameter[15]);
	info->dry = calc_dry_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_3tap_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_3TapDelay *info = (Info_GS_3TapDelay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;

	send_efx_buffer(ef, buf, count);
	do_multi_tap_delay(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_gs_4tap_delay(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_4TapDelay *info = (Info_GS_4TapDelay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;
	
	dly->mode = CH_MIX_STEREO;
	dly->tap = 4;
	dly->dtime[0] = (double)delay_time_1_table[st->parameter[0]];
	dly->dtime[1] = (double)delay_time_1_table[st->parameter[1]];
	dly->dtime[2] = (double)delay_time_1_table[st->parameter[2]];
	dly->dtime[3] = (double)delay_time_1_table[st->parameter[3]];
	dly->dtime[4] = dly->dtime[0]; // [tap] for feedback_delay // dtime[0]と同じ
	dly->pan[0] = 0x50;
	dly->pan[1] = 0x30;
	dly->pan[2] = 0x70;
	dly->pan[3] = 0x10;
	dly->pan[4] = 0x40; // [tap] for feedback_delay
	dly->dlevel[0] = calc_option_level(st->parameter[4]);
	dly->dlevel[1] = calc_option_level(st->parameter[5]);
	dly->dlevel[2] = calc_option_level(st->parameter[6]);
	dly->dlevel[3] = calc_option_level(st->parameter[7]);
	dly->feedback = (double)(clip_int(st->parameter[8], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[9]];
	info->wet = calc_wet_gs(st->parameter[15]);
	info->dry = calc_dry_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_4tap_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_4TapDelay *info = (Info_GS_4TapDelay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;

	send_efx_buffer(ef, buf, count);
	do_multi_tap_delay(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_gs_tm_ctrl_delay(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_TmCtrlDelay *info = (Info_GS_TmCtrlDelay *)ef->info;
	InfoDelayShifter *dly = &info->dly;

	dly->mode = CH_MIX_MONO;
	dly->ldelay = dly->rdelay = (double)delay_time_2_table[st->parameter[0]];
	dly->accel = st->parameter[1]; // 0 ~ 15
	dly->feedback = (double)(clip_int(st->parameter[2], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[3]];
	info->panl = calc_pan_gs_left(st->parameter[4]);
	info->panr = calc_pan_gs_right(st->parameter[4]);
	info->wet = calc_wet_gs(st->parameter[15]);
	info->dry = calc_dry_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_tm_ctrl_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_TmCtrlDelay *info = (Info_GS_TmCtrlDelay *)ef->info;
	InfoDelayShifter *dly = &info->dly;

	send_efx_buffer(ef, buf, count);
	do_delay_shifter(ef->efx_buf, count, dly);	
	effect_panning_mono_stereo(ef->efx_buf, count, info->panl, info->panr);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static double ins_gs_revchar_to_roomsize(int character)
{
	double rs;
	switch(character) {
	case 0: rs = 1.0;	break;	/* Room 1 */
	case 1: rs = 0.94;	break;	/* Room 2 */
	case 2: rs = 0.97;	break;	/* Stage 1 */
	case 3: rs = 0.99;	break;	/* Stage 2 */
	case 4: rs = 0.90;	break;	/* Hall 1 */
	default:
	case 5: rs = 0.85;	break;	/* Hall 2 */
	}
	return rs;
}

static double ins_gs_revchar_to_level(int character)
{
	double level;
	switch(character) {
	case 0: level = 0.744025605;	break;	/* Room 1 */
	case 1: level = 1.224309745;	break;	/* Room 2 */
	case 2: level = 0.894025605;	break;	/* Stage 1 */
	case 3: level = 1.112309745;	break;	/* Stage 2 */
	case 4: level = 1.047180200;	break;	/* Hall 1 */
	default:
	case 5: level = 1.000000000;	break;	/* Hall 2 */
	}
	return level;
}

static double ins_gs_revchar_to_rt(int character)
{
	double rt;
	switch(character) {
	case 0: rt = 0.516850262;	break;	/* Room 1 */
	case 1: rt = 0.964226004;	break;	/* Room 2 */
	case 2: rt = 0.706850262;	break;	/* Stage 1 */
	case 3: rt = 0.985116004;	break;	/* Stage 2 */
	case 4: rt = 0.893006004;	break;	/* Hall 1 */
	default:
	case 5: rt = 0.991300000;	break;	/* Hall 2 */
	}
	return rt;
}

static void conv_gs_reverb(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_Reverb *info = (Info_GS_Reverb *)ef->info;
	InfoFreeverb *rvb = &info->rvb;	
	InfoReverbEX *rvb2 = &info->rvb2;	
#ifdef REV_EX2
	InfoReverbEX2 *rvb3 = &info->rvb3;
#endif

#ifdef REV_EX2			
	if((opt_reverb_control >= 7 && opt_reverb_control < 9) || (opt_reverb_control <= -768 && opt_reverb_control > -1024)){
		info->rev_type = 2; // reverb ex2
		rvb3->mode = CH_MIX_STEREO;
		switch(clip_int(st->parameter[0], 0x00, 0x05)){
		case 0: // room1
			rvb3->height = 3.0; // m
			rvb3->width = 5.0; // m
			rvb3->depth = 7.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.65;
			rvb3->er_level = 0.50;
			rvb3->rev_level = 0.50;
			rvb3->density = 1.0;
			break;
		case 1: // room2
			rvb3->height = 4.0; // m
			rvb3->width = 8.0; // m
			rvb3->depth = 10.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.99;
			rvb3->er_level = 0.45;
			rvb3->rev_level = 0.55;
			rvb3->density = 0.75;
			break;
		case 2: // stage1
			rvb3->height = 10.0; // m
			rvb3->width = 12.0; // m
			rvb3->depth = 15.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.85;
			rvb3->er_level = 0.40;
			rvb3->rev_level = 0.60;
			rvb3->density = 0.75;
			break;
		case 3: // stage2
			rvb3->height = 12.0; // m
			rvb3->width = 13.0; // m
			rvb3->depth = 18.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.95;
			rvb3->er_level = 0.60;
			rvb3->rev_level = 0.40;
			rvb3->density = 1.0;
			break;
		case 4: // hall1
			rvb3->height = 12.0; // m
			rvb3->width = 16.0; // m
			rvb3->depth = 20.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.65;
			rvb3->er_level = 0.50;
			rvb3->rev_level = 0.50;
			rvb3->density = 1.0;
			break;
		default:
		case 5: // hall2
			rvb3->height = 16.0; // m
			rvb3->width = 20.0; // m
			rvb3->depth = 31.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.95;
			rvb3->er_level = 0.45;
			rvb3->rev_level = 0.55;
			rvb3->density = 0.75;
			break;
		}		
		rvb3->er_time_ms = pre_delay_time_table[st->parameter[1]];
		rvb3->rev_time_sec = reverb_time_table[st->parameter[2]];
		rvb3->rev_damp_freq = HF_damp_freq_table_gs[st->parameter[3]];
		rvb3->er_damp_freq = HF_damp_freq_table_gs[st->parameter[3]];
		rvb3->rev_feedback = 0.0; // reverb_status_gs.delay_feedback
		rvb3->rev_dly_ms = 0;
		rvb3->density = 1.0;
		rvb3->level = 1.0;
	}else 
#endif
	if(otd.efx_CustomRevType){
		info->rev_type = 1; // reverb ex
		rvb2->mode = CH_MIX_STEREO;
		switch(clip_int(st->parameter[0], 0x00, 0x05)){
		case 0: // room1
			rvb2->height = 3.0; // m
			rvb2->width = 5.0; // m
			rvb2->depth = 7.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.65;
			rvb2->er_level = 0.50;
			rvb2->rev_level = 0.50;
			rvb2->density = 1.0;
			break;
		case 1: // room2
			rvb2->height = 4.0; // m
			rvb2->width = 8.0; // m
			rvb2->depth = 10.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.99;
			rvb2->er_level = 0.45;
			rvb2->rev_level = 0.55;
			rvb2->density = 0.75;
			break;
		case 2: // stage1
			rvb2->height = 10.0; // m
			rvb2->width = 12.0; // m
			rvb2->depth = 15.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.85;
			rvb2->er_level = 0.40;
			rvb2->rev_level = 0.60;
			rvb2->density = 0.75;
			break;
		case 3: // stage2
			rvb2->height = 12.0; // m
			rvb2->width = 13.0; // m
			rvb2->depth = 18.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.95;
			rvb2->er_level = 0.60;
			rvb2->rev_level = 0.40;
			rvb2->density = 1.0;
			break;
		case 4: // hall1
			rvb2->height = 12.0; // m
			rvb2->width = 16.0; // m
			rvb2->depth = 20.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.65;
			rvb2->er_level = 0.50;
			rvb2->rev_level = 0.50;
			rvb2->density = 1.0;
			break;
		default:
		case 5: // hall2
			rvb2->height = 16.0; // m
			rvb2->width = 20.0; // m
			rvb2->depth = 31.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.95;
			rvb2->er_level = 0.45;
			rvb2->rev_level = 0.55;
			rvb2->density = 0.75;
			break;
		}		
		rvb2->er_time_ms = pre_delay_time_table[st->parameter[1]];
		rvb2->rev_time_sec = reverb_time_table[st->parameter[2]];
		rvb2->rev_damp_freq = HF_damp_freq_table_gs[st->parameter[3]];
		rvb2->er_damp_freq = HF_damp_freq_table_gs[st->parameter[3]];
		rvb2->rev_feedback = 0.0; // reverb_status_gs.delay_feedback
		rvb2->rev_dly_ms = 0;
		rvb2->density = 1.0;
		rvb2->level = 1.0;
	}else{
// freeverb
		info->rev_type = 0;
		rvb->mode = CH_MIX_STEREO;
		rvb->rev_rt = ins_gs_revchar_to_rt(clip_int(st->parameter[0], 0x00, 0x05));
		rvb->rev_roomsize = ins_gs_revchar_to_roomsize(clip_int(st->parameter[0], 0x00, 0x05));
		rvb->er_time_ms = pre_delay_time_table[st->parameter[1]];
		rvb->er_damp_freq = HF_damp_freq_table_gs[st->parameter[3]];
		rvb->er_level = 0.35;
		rvb->rev_time_sec = reverb_time_table[st->parameter[2]];
		rvb->rev_wet = 1.0;//ins_gs_revchar_to_level(clip_int(st->parameter[0], 0x00, 0x05));
		rvb->rev_width = initialwidth;
		rvb->rev_damp = HF_damp_freq_table_gs[st->parameter[3]] * DIV_22000; // initialdamp;
		rvb->rev_feedback = 0.0;
		rvb->rev_dly_ms = 0;
		rvb->rev_level = 0.65;
		rvb->rev_dif = 1.0;
	}
	info->rev_wet = calc_wet_gs(st->parameter[15]);
	info->rev_dry = calc_dry_gs(st->parameter[15]);
	info->rev_level = calc_gs_level(st->parameter[19]);
}

static void do_gs_reverb(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_Reverb *info = (Info_GS_Reverb *)ef->info;
	InfoFreeverb *rvb = &info->rvb;
	InfoReverbEX *rvb2 = &info->rvb2;
#ifdef REV_EX2
	InfoReverbEX2 *rvb3 = &info->rvb3;
#endif

	send_efx_buffer(ef, buf, count);
#ifdef REV_EX2	
	if(info->rev_type == 2)
		do_reverb_ex2(ef->efx_buf, count, rvb3);
	else 
#endif
	if(info->rev_type)
		do_reverb_ex(ef->efx_buf, count, rvb2);
	else
		do_freeverb(ef->efx_buf, count, rvb);
	return_efx_buffer(ef, buf, count, info->rev_wet, info->rev_dry, info->rev_level);
}

static void conv_gs_gate_reverb(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_GateReverb *info = (Info_GS_GateReverb *)ef->info;
	InfoGateReverb *gr = &info->gr;
	
	gr->mode = CH_MIX_STEREO;
	gr->rev_time_sec = 2.0;
	gr->rev_damp_type = FILTER_LPF6;
	gr->rev_damp_bal = 0.85;
	gr->er_level = 0.5;
	gr->rev_level = 0.5;
	gr->room_size = 3.0;
	gr->rev_feedback = 0.0;
	gr->density = 1.0;	
	gr->rev_damp_freq = 16000;
	gr->er_damp_freq = 16000;	
	gr->type = clip_int(st->parameter[0], 0x00, 0x03);
	gr->er_time_ms = pre_delay_time_table[st->parameter[1]];
	gr->gate_time_ms = clip_int(st->parameter[2], 0x01, 0x63) * 5.0;
	info->gr_wet = calc_wet_gs(st->parameter[15]);
	info->gr_dry = calc_dry_gs(st->parameter[15]);
	info->gr_level = calc_gs_level(st->parameter[19]);	
}

static void do_gs_gate_reverb(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_GateReverb *info = (Info_GS_GateReverb *)ef->info;
	InfoGateReverb *gr = &info->gr;

	send_efx_buffer(ef, buf, count);
	do_gate_reverb(ef->efx_buf, count, gr);	
	return_efx_buffer(ef, buf, count, info->gr_wet, info->gr_dry, info->gr_level);
}

static void conv_gs_3d_delay(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_3DDelay *info = (Info_GS_3DDelay *)ef->info;
	Info3DMultiTapDelay *dly = &info->dly;

//	dly->mode = CH_MIX_STEREO;
	dly->tap = 3;
	dly->dtime[0] = (double)delay_time_3_table[st->parameter[0]];
	dly->dtime[1] = (double)delay_time_3_table[st->parameter[1]];
	dly->dtime[2] = (double)delay_time_3_table[st->parameter[2]];
	dly->dtime[3] = dly->dtime[0]; // [tap] for feedback_delay // dtime[0]と同じ
	dly->pan[0] = 0x40;
	dly->pan[1] = 0x00;
	dly->pan[2] = 0x7F;
	dly->pan[3] = 0x40; // [tap] for feedback_delay
	dly->feedback = (double)(clip_int(st->parameter[3], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->dlevel[0] = calc_option_level(st->parameter[4]);
	dly->dlevel[1] = calc_option_level(st->parameter[5]);
	dly->dlevel[2] = calc_option_level(st->parameter[6]);
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[7]];
	dly->out = st->parameter[14] ? 1 : 0; // Speaker/Phones
	info->wet = calc_wet_gs(st->parameter[15]);
	info->dry = calc_dry_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_3d_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_3DDelay *info = (Info_GS_3DDelay *)ef->info;
	Info3DMultiTapDelay *dly = &info->dly;

	send_efx_buffer(ef, buf, count);
	do_3d_multi_tap_delay(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

/** LSB 60x **/
static void conv_gs_2pitch_shifter(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_2PitchShifter *info = (Info_GS_2PitchShifter *)ef->info;
	InfoPitchShifter_core *psl = &info->ps.psl;
	InfoPitchShifter_core *psr = &info->ps.psr;

	info->ps.mode = CH_MIX_STEREO;
	psl->pitch_cent = (double)(clip_int(st->parameter[0], 0x28, 0x4C) - 0x40) * 100 + (clip_int(st->parameter[1], 0x0E, 0x72) - 0x40) * 2;
	psl->feedback = 0.0;
	psl->pre_delay_ms = (double)delay_time_1_table[st->parameter[2]];
	info->panll = calc_pan_gs_left(st->parameter[3]);
	info->panlr = calc_pan_gs_right(st->parameter[3]);
	psr->pitch_cent = (double)(clip_int(st->parameter[4], 0x28, 0x4C) - 0x40) * 100 + (clip_int(st->parameter[5], 0x0E, 0x72) - 0x40) * 2;
	psr->feedback = 0.0;
	psr->pre_delay_ms = (double)delay_time_1_table[st->parameter[6]];
	info->panrl = calc_pan_gs_left(st->parameter[7]);
	info->panrr = calc_pan_gs_right(st->parameter[7]);
	psl->ps_delay_ms = psr->ps_delay_ms = PS_CF_DELAY + clip_int(st->parameter[8], 0x00, 0x04) * 4; // PS_CF_DELAY + 16ms
	info->bal1 = calc_wet_gs(st->parameter[10]);
	info->bal2 = calc_dry_gs(st->parameter[10]);
	info->wet = calc_wet_gs(st->parameter[15]);
	info->dry = calc_dry_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_2pitch_shifter(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_2PitchShifter *info = (Info_GS_2PitchShifter *)ef->info;
	InfoPitchShifter *ps = &info->ps;
	
	send_efx_buffer(ef, buf, count);
	do_pitch_shifter_multi(ef->efx_buf, count, ps);
	effect_level_left(ef->efx_buf, count, info->bal1);
	effect_level_right(ef->efx_buf, count, info->bal2);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_gs_fb_pitch_shifter(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_FbPitchShifter *info = (Info_GS_FbPitchShifter *)ef->info;
	InfoPitchShifter *ps = &info->ps;
	
	info->ps.mode = CH_MIX_MONO;
	ps->psl.pitch_cent = (double)(clip_int(st->parameter[0], 0x28, 0x4C) - 0x40) * 100 + (clip_int(st->parameter[1], 0x0E, 0x72) - 0x40) * 2;
	ps->psl.pre_delay_ms = (double)delay_time_1_table[st->parameter[2]];
	ps->psl.feedback = (double)(clip_int(st->parameter[3], 0x0F, 0x71) - 0x40) * 2 * DIV_100;
	ps->psl.ps_delay_ms = PS_CF_DELAY + clip_int(st->parameter[4], 0x00, 0x04) * 4; // PS_CF_DELAY + 16ms
	info->panl = calc_pan_gs_left(st->parameter[5]);
	info->panr = calc_pan_gs_right(st->parameter[5]);
	info->wet = calc_wet_gs(st->parameter[15]);
	info->dry = calc_dry_gs(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_fb_pitch_shifter(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_FbPitchShifter *info = (Info_GS_FbPitchShifter *)ef->info;	
	InfoPitchShifter *ps = &info->ps;

	send_efx_buffer(ef, buf, count); 
	do_pitch_shifter_multi(ef->efx_buf, count, ps);
	effect_panning_mono_stereo(ef->efx_buf, count, info->panl, info->panr);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level); 
}

/** LSB 7x **/
static void conv_gs_3d_auto(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_3DAuto *info = (Info_GS_3DAuto *)ef->info;	
	Info3DAuto *lc = &info->locate;

	lc->azimuth = 	(double)azimuth_table[st->parameter[0]] * DIV_180;
	lc->speed = rate1_table[st->parameter[1]];
	lc->clockwize = st->parameter[1] ? 1 : 0;
	lc->turn = st->parameter[2] ? 1 : 0;
	lc->out = st->parameter[14] ? 1 : 0;
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_3d_auto(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_3DAuto *info = (Info_GS_3DAuto *)ef->info;	
	Info3DAuto *lc = &info->locate;

	do_3d_auto(buf, count, lc);
	effect_level_stereo(buf, count, info->level);
}

static void conv_gs_3d_manual(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_3DManual *info = (Info_GS_3DManual *)ef->info;	
	Info3DManual *lc = &info->locate;

	lc->azimuth = 	(double)azimuth_table[st->parameter[0]] * DIV_180;
	lc->out = st->parameter[14] ? 1 : 0;	
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_3d_manual(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_3DManual *info = (Info_GS_3DManual *)ef->info;	
	Info3DManual *lc = &info->locate;

	do_3d_manual(buf, count, lc);	
	effect_level_stereo(buf, count, info->level);
}

static void conv_gs_lofi1(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_LoFi1 *info = (Info_GS_LoFi1 *)ef->info;
	InfoLoFi *lf = &info->lf;
	
	lf->mode = CH_MIX_MONO;
	lf->level_in = otd.gsefx_CustomLFLvIn;
	lf->level_out = otd.gsefx_CustomLFLvOut;
	lf->sr_rate = 32000;
	lf->pre_fil_type = st->parameter[0] ? FILTER_LPF_BW : FILTER_NONE; // off,lpf
	lf->pre_fil_freq = 16000.0 / (FLOAT_T)(clip_int(st->parameter[0], 0, 5) + 1);
	lf->pre_fil_reso = 0.0;
	lf->bit_length = 12 - clip_int(st->parameter[1], 0, 8);	
	lf->post_fil_type = st->parameter[2] ? FILTER_LPF_BW : FILTER_NONE; // off,lpf
	lf->post_fil_freq = 16000.0 / (FLOAT_T)(clip_int(st->parameter[2], 0, 5) + 1);
	lf->post_fil_reso = 0.0;		
	lf->nz_gen = 0; // noise off
	info->dry = calc_dry_gs(st->parameter[15] & 0x7F);
	info->wet = calc_wet_gs(st->parameter[15] & 0x7F);
	info->panl = calc_pan_gs_left(st->parameter[18]);
	info->panr = calc_pan_gs_right(st->parameter[18]);
	info->level = calc_gs_level(st->parameter[19] & 0x7F);
}

static void do_gs_lofi1(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_LoFi1 *info = (Info_GS_LoFi1 *)ef->info;
	InfoLoFi *lf = &info->lf;
	
	send_efx_buffer(ef, buf, count); 
	do_lofi(ef->efx_buf, count, lf);
	effect_panning_mono_stereo(ef->efx_buf, count, info->panl, info->panr);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level); 
}

static void conv_gs_lofi2(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_LoFi2 *info = (Info_GS_LoFi2 *)ef->info;
	InfoLoFi *lf = &info->lf;

	lf->mode = st->parameter[14] ? CH_STEREO : CH_MIX_MONO;
	lf->level_in = otd.gsefx_CustomLFLvIn;
	lf->level_out = otd.gsefx_CustomLFLvOut;
	lf->sr_rate = 32000;
	lf->pre_fil_type = FILTER_NONE; // off
	lf->pre_fil_freq = 0;
	lf->pre_fil_reso = 0.0;
	lf->bit_length = 14 - clip_int(st->parameter[0], 0, 5) * 2;	
	switch(st->parameter[1]){
	default:
	case 0: // off
		lf->post_fil_type = FILTER_NONE;
		break;
	case 1: // lpf
		lf->post_fil_type = FILTER_LPF_BW;
		break;
	case 2: // hpf
		lf->post_fil_type = FILTER_HPF_BW;
		break;

	}
	lf->post_fil_freq = cutoff_freq_table_gs[st->parameter[2]];
	lf->post_fil_reso = 0.0;		
	lf->nz_gen = 1; // noise on
	lf->rdetune = st->parameter[3];
	//lf->rnz_wet = calc_option_wet(st->parameter[4]);
	//lf->rnz_dry = calc_option_dry(st->parameter[4]);
	lf->rnz_lev = calc_option_level(st->parameter[4]);
	lf->wp_sel = clip_int(st->parameter[5], 0, 1);
	lf->wp_freq = lpf_table_gs[st->parameter[6]];
	//lf->wp_wet = calc_option_wet(st->parameter[7]);
	//lf->wp_dry = calc_option_dry(st->parameter[7]);
	lf->wp_level = calc_option_level(st->parameter[7]);
	lf->disc_type = clip_int(st->parameter[8], 0, 3);
	lf->disc_freq = lpf_table_gs[st->parameter[9]];
	//lf->discnz_wet = calc_option_wet(st->parameter[10]);
	//lf->discnz_dry = calc_option_dry(st->parameter[10]);
	lf->discnz_lev = calc_option_level(st->parameter[10]);
	lf->hum_type = clip_int(st->parameter[11], 0, 1);
	lf->hum_freq = lpf_table_gs[st->parameter[12]];
	//lf->hum_wet = calc_option_wet(st->parameter[13]);
	//lf->hum_dry = calc_option_dry(st->parameter[13]);
	lf->hum_level = calc_option_level(st->parameter[13]);
	info->dry = calc_dry_gs(st->parameter[15] & 0x7F);
	info->wet = calc_wet_gs(st->parameter[15] & 0x7F);
	info->panl = calc_pan_gs_left(st->parameter[18]);
	info->panr = calc_pan_gs_right(st->parameter[18]);
	info->level = calc_gs_level(st->parameter[19] & 0x7F);	
}

static void do_gs_lofi2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_LoFi2 *info = (Info_GS_LoFi2 *)ef->info;
	InfoLoFi *lf = &info->lf;
	
	switch(lf->mode){
	case CH_STEREO:
		send_efx_buffer(ef, buf, count); 
		do_lofi(ef->efx_buf, count, lf);
		return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
		break;
	case CH_MIX_MONO:
		send_efx_buffer(ef, buf, count); 
		do_lofi(ef->efx_buf, count, lf);
		effect_panning_mono_stereo(ef->efx_buf, count, info->panl, info->panr);
		return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
		break;
	}
}


/**************** GS INSERTION conv multi serial ****************/
/***** MSB 02 *****/
static void conv_gs_s_od_chorus(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_OD_Chorus *pe= (Info_GS_S_OD_Chorus *)ef->info;
	InfoOverdrive *od = &pe->info_od;
	InfoStereoChorus *cho = &pe->info_cho;

	// overdrive1
	od->mode = CH_MIX_MONO;
	od->type = 0; // od
	od->drive = st->parameter[0];
	pe->od_panl = calc_pan_gs_left(st->parameter[1]);	
	pe->od_panr = calc_pan_gs_right(st->parameter[1]);	
	od->amp_type = st->parameter[2];
	od->amp_sw = st->parameter[3] ? 1 : 0;	
	od->level = 1.0; 
	// chorus
	cho->mode = CH_MONO_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = (double)pre_delay_time_table[st->parameter[5]];
	cho->rate = (double)rate1_table[st->parameter[6]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[7]);	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[9]);
	pe->cho_dry = calc_dry_gs(st->parameter[9]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_s_od_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_OD_Chorus *pe= (Info_GS_S_OD_Chorus *)ef->info;

	do_od_ds_multi(buf, count, &pe->info_od);
	effect_panning_mono_stereo(buf, count, pe->od_panl, pe->od_panr);
	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_cho);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_od_flanger(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_OD_Flanger *pe= (Info_GS_S_OD_Flanger *)ef->info;
	InfoOverdrive *od = &pe->info_od;
	InfoStereoChorus *fl = &pe->info_fl;

	// overdrive1
	od->mode = CH_MIX_MONO;
	od->type = 0; // od
	od->drive = st->parameter[0];
	pe->od_panl = calc_pan_gs_left(st->parameter[1]);	
	pe->od_panr = calc_pan_gs_right(st->parameter[1]);	
	od->amp_type = st->parameter[2];
	od->amp_sw = st->parameter[3] ? 1 : 0;	
	od->level = 1.0; 
	// chorus
	fl->mode = CH_MONO_STEREO;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = (double)pre_delay_time_table[st->parameter[5]];
	fl->rate = (double)rate1_table[st->parameter[6]];
	fl->depth_cent = calc_chorus_depth_gs(st->parameter[7]);	
	fl->feedback = (double)(st->parameter[8] - 64) * 1.5625 * 0.0081 + 0.10; // param
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_wet_gs(st->parameter[9]);
	pe->fl_dry = calc_dry_gs(st->parameter[9]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_s_od_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_OD_Flanger *pe= (Info_GS_S_OD_Flanger *)ef->info;	

	do_od_ds_multi(buf, count, &pe->info_od);
	send_efx_buffer(ef, buf, count);
	effect_panning_mono_stereo(buf, count, pe->od_panl, pe->od_panr);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_fl);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_od_delay(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_OD_Delay *pe= (Info_GS_S_OD_Delay *)ef->info;
	InfoOverdrive *od = &pe->info_od;
	InfoDelayLR *dly = &pe->info_dly;

	// overdrive1
	od->mode = CH_MIX_MONO;
	od->type = 0; // od
	od->drive = st->parameter[0];
	pe->od_panl = calc_pan_gs_left(st->parameter[1]);	
	pe->od_panr = calc_pan_gs_right(st->parameter[1]);	
	od->amp_type = st->parameter[2];
	od->amp_sw = st->parameter[3] ? 1 : 0;		
	od->level = 1.0; 
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->fdelay1 = dly->rdelay = dly->fdelay2 = (double)delay_time_3_table[st->parameter[5]];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[6], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[7]];
	pe->dly_wet = calc_wet_gs(st->parameter[9]);
	pe->dly_dry = calc_dry_gs(st->parameter[9]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_s_od_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_OD_Delay *pe= (Info_GS_S_OD_Delay *)ef->info;	

	do_od_ds_multi(buf, count, &pe->info_od);
	send_efx_buffer(ef, buf, count);
	effect_panning_mono_stereo(buf, count, pe->od_panl, pe->od_panr);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_ds_chorus(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_OD_Chorus *pe= (Info_GS_S_OD_Chorus *)ef->info;
	InfoOverdrive *od = &pe->info_od;
	InfoStereoChorus *cho = &pe->info_cho;

	// overdrive1
	od->mode = CH_MIX_MONO;
	od->type = 1; // ds
	od->drive = st->parameter[0];
	pe->od_panl = calc_pan_gs_left(st->parameter[1]);	
	pe->od_panr = calc_pan_gs_right(st->parameter[1]);	
	od->amp_type = st->parameter[2];
	od->amp_sw = st->parameter[3] ? 1 : 0;	
	od->level = 1.0; 	
	// chorus
	cho->mode = CH_MONO_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = (double)pre_delay_time_table[st->parameter[5]];
	cho->rate = (double)rate1_table[st->parameter[6]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[7]);	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[9]);
	pe->cho_dry = calc_dry_gs(st->parameter[9]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_s_ds_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_OD_Chorus *pe= (Info_GS_S_OD_Chorus *)ef->info;	

	do_od_ds_multi(buf, count, &pe->info_od);
	send_efx_buffer(ef, buf, count);
	effect_panning_mono_stereo(buf, count, pe->od_panl, pe->od_panr);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_cho);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_ds_flanger(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_OD_Flanger *pe= (Info_GS_S_OD_Flanger *)ef->info;
	InfoOverdrive *od = &pe->info_od;
	InfoStereoChorus *fl = &pe->info_fl;

	// overdrive1
	od->mode = CH_MIX_MONO;
	od->type = 1; // od
	od->drive = st->parameter[0];
	pe->od_panl = calc_pan_gs_left(st->parameter[1]);	
	pe->od_panr = calc_pan_gs_right(st->parameter[1]);	
	od->amp_type = st->parameter[2];
	od->amp_sw = st->parameter[3] ? 1 : 0;	
	od->level = 1.0; 
	// flanger
	fl->mode = CH_MONO_STEREO;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = (double)pre_delay_time_table[st->parameter[5]];
	fl->rate = (double)rate1_table[st->parameter[6]];
	fl->depth_cent = calc_chorus_depth_gs(st->parameter[7]);	
	fl->feedback = (double)(st->parameter[8] - 64) * (0.763 * 2.0 * DIV_100);
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_wet_gs(st->parameter[9]);
	pe->fl_dry = calc_dry_gs(st->parameter[9]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_s_ds_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_OD_Flanger *pe= (Info_GS_S_OD_Flanger *)ef->info;	

	do_od_ds_multi(buf, count, &pe->info_od);
	send_efx_buffer(ef, buf, count);
	effect_panning_mono_stereo(buf, count, pe->od_panl, pe->od_panr);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_fl);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_ds_delay(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_OD_Delay *pe= (Info_GS_S_OD_Delay *)ef->info;
	InfoOverdrive *od = &pe->info_od;
	InfoDelayLR *dly = &pe->info_dly;

	// overdrive1
	od->mode = CH_MIX_MONO;
	od->type = 0; // od
	od->drive = st->parameter[0];
	pe->od_panl = calc_pan_gs_left(st->parameter[1]);	
	pe->od_panr = calc_pan_gs_right(st->parameter[1]);	
	od->amp_type = st->parameter[2];
	od->amp_sw = st->parameter[3] ? 1 : 0;	
	od->level = 1.0; 
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = (double)delay_time_3_table[st->parameter[5]];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[6], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[7]];
	pe->dly_wet = calc_wet_gs(st->parameter[9]);
	pe->dly_dry = calc_dry_gs(st->parameter[9]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_s_ds_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_OD_Delay *pe= (Info_GS_S_OD_Delay *)ef->info;	

	do_od_ds_multi(buf, count, &pe->info_od);
	send_efx_buffer(ef, buf, count);
	effect_panning_mono_stereo(buf, count, pe->od_panl, pe->od_panr);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_enhancer_chorus(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_EH_Chorus *pe= (Info_GS_S_EH_Chorus *)ef->info;
	InfoEnhancer *eh = &pe->info_eh;
	InfoStereoChorus *cho = &pe->info_cho;

	// Enhancer
	eh->mode = CH_STEREO;
	eh->hpf_cutoff = 3200;
	eh->sens = (double)st->parameter[0] * DIV_127;	
	pe->eh_wet = (double)st->parameter[1] * DIV_127;	
	pe->eh_dry = 1.0;
	// chorus
	cho->mode = CH_MIX_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = (double)pre_delay_time_table[st->parameter[5]];
	cho->rate = (double)rate1_table[st->parameter[6]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[7]);	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[9]);
	pe->cho_dry = calc_dry_gs(st->parameter[9]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_s_enhancer_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_EH_Chorus *pe= (Info_GS_S_EH_Chorus *)ef->info;

	send_efx_buffer(ef, buf, count);
	do_enhancer_multi(ef->efx_buf, count, &pe->info_eh);
	return_efx_buffer(ef, buf, count, pe->eh_wet, pe->eh_dry, 1.0);
	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_cho);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_enhancer_flanger(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_EH_Flanger *pe= (Info_GS_S_EH_Flanger *)ef->info;
	InfoEnhancer *eh = &pe->info_eh;
	InfoStereoChorus *fl = &pe->info_fl;

	// Enhancer
	eh->mode = CH_STEREO;
	eh->hpf_cutoff = 3200;
	eh->sens = (double)st->parameter[0] * DIV_127;	
	pe->eh_wet = (double)st->parameter[1] * DIV_127;	
	pe->eh_dry = 1.0;
	// flanger
	fl->mode = CH_MIX_STEREO;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = (double)pre_delay_time_table[st->parameter[5]];
	fl->rate = (double)rate1_table[st->parameter[6]];
	fl->depth_cent = calc_chorus_depth_gs(st->parameter[7]);	
	fl->feedback = (double)(st->parameter[8] - 64) * (0.763 * 2.0 * DIV_100);
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_wet_gs(st->parameter[9]);
	pe->fl_dry = calc_dry_gs(st->parameter[9]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_s_enhancer_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_EH_Flanger *pe= (Info_GS_S_EH_Flanger *)ef->info;

	send_efx_buffer(ef, buf, count);
	do_enhancer_multi(ef->efx_buf, count, &pe->info_eh);
	return_efx_buffer(ef, buf, count, pe->eh_wet, pe->eh_dry, 1.0);
	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_fl);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_enhancer_delay(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_EH_Delay *pe= (Info_GS_S_EH_Delay *)ef->info;
	InfoEnhancer *eh = &pe->info_eh;
	InfoDelayLR *dly = &pe->info_dly;

	// Enhancer
	eh->mode = CH_STEREO;
	eh->hpf_cutoff = 3200;
	eh->sens = (double)st->parameter[0] * DIV_127;	
	pe->eh_wet = (double)st->parameter[1] * DIV_127;	
	pe->eh_dry = 1.0;
	// delay
	dly->mode = CH_MIX_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = (double)delay_time_3_table[st->parameter[5]];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[6], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[7]];
	pe->dly_wet = calc_wet_gs(st->parameter[9]);
	pe->dly_dry = calc_dry_gs(st->parameter[9]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_s_enhancer_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_EH_Delay *pe= (Info_GS_S_EH_Delay *)ef->info;

	send_efx_buffer(ef, buf, count);
	do_enhancer_multi(ef->efx_buf, count, &pe->info_eh);
	return_efx_buffer(ef, buf, count, pe->eh_wet, pe->eh_dry, 1.0);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_chorus_delay(struct insertion_effect_gs_t *st, EffectList *ef)
{	
	Info_GS_S_Cho_Delay *pe= (Info_GS_S_Cho_Delay *)ef->info;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoDelayLR *dly = &pe->info_dly;
	
	cho->mode = CH_MIX_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = (double)pre_delay_time_table[st->parameter[0]];
	cho->rate = (double)rate1_table[st->parameter[1]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[2]);	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[4]);
	pe->cho_dry = calc_dry_gs(st->parameter[4]);
	// delay
	dly->mode = CH_MIX_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = (double)delay_time_3_table[st->parameter[5]];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[6], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[7]];
	pe->dly_wet = calc_wet_gs(st->parameter[9]);
	pe->dly_dry = calc_dry_gs(st->parameter[9]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_s_chorus_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_Cho_Delay *pe= (Info_GS_S_Cho_Delay *)ef->info;

	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_cho);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_flanger_delay(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_FL_Delay *pe= (Info_GS_S_FL_Delay *)ef->info;
	InfoStereoChorus *fl = &pe->info_fl;
	InfoDelayLR *dly = &pe->info_dly;

	// flanger
	fl->mode = CH_MIX_STEREO;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = (double)pre_delay_time_table[st->parameter[0]];
	fl->rate = (double)rate1_table[st->parameter[1]];
	fl->depth_cent = calc_chorus_depth_gs(st->parameter[2]);	
	fl->feedback = (double)(st->parameter[3] - 64) * (0.763 * 2.0 * DIV_100);
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_wet_gs(st->parameter[4]);
	pe->fl_dry = calc_dry_gs(st->parameter[4]);
	fl->level = 1.0;
	// delay
	dly->mode = CH_MIX_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = (double)delay_time_3_table[st->parameter[5]];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[6], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[7]];
	pe->dly_wet = calc_wet_gs(st->parameter[9]);
	pe->dly_dry = calc_dry_gs(st->parameter[9]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_s_flanger_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_FL_Delay *pe= (Info_GS_S_FL_Delay *)ef->info;	

	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_fl);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_chorus_flanger(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_Cho_Flanger *pe= (Info_GS_S_Cho_Flanger *)ef->info;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoStereoChorus *fl = &pe->info_fl;	

	// chorus
	cho->mode = CH_MIX_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = (double)pre_delay_time_table[st->parameter[0]];
	cho->rate = (double)rate1_table[st->parameter[1]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[2]);	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[4]);
	pe->cho_dry = calc_dry_gs(st->parameter[4]);
	// flanger
	fl->mode = CH_MIX_STEREO;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = (double)pre_delay_time_table[st->parameter[5]];
	fl->rate = rate1_table[st->parameter[6]];
	fl->depth_cent = calc_chorus_depth_gs(st->parameter[7]);	
	fl->feedback = (double)(st->parameter[8] - 64) * (0.763 * 2.0 * DIV_100);
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_wet_gs(st->parameter[9]);
	pe->fl_dry = calc_dry_gs(st->parameter[9]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_s_chorus_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_Cho_Flanger *pe= (Info_GS_S_Cho_Flanger *)ef->info;
	
	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_cho);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_fl);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

#define GS_MULTI_EFX_LEVEL (1.0)

/***** MSB 03 *****/
static void conv_gs_s_rotary_multi(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_RotaryMulti *pe= (Info_GS_S_RotaryMulti *)ef->info;
	InfoOverdrive *od = &pe->info_od;
	InfoEQ3 *eq = &pe->info_eq;
	InfoRotary *rt = &pe->info_rt;

	// overdrive1
	od->mode = st->parameter[1] ? CH_MIX_MONO : CH_NONE;
	od->type = 0; // od
	od->drive = st->parameter[0];
	od->amp_type = 0;
	od->amp_sw = 0;
	od->level = 1.0; 
	// eq
	eq->mode = CH_LEFT;
	eq->low_freq = 200;
	eq->low_gain = clip_int(st->parameter[2] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_gs[st->parameter[3]];
	eq->mid_width = (double)eq_q_table_gs[clip_int(st->parameter[4], 0, 4)];
	eq->mid_gain = clip_int(st->parameter[5] - 64, -12, 12);
	eq->high_freq = 5000;
	eq->high_gain = clip_int(st->parameter[6] - 64, -12, 12);
	// rotary	
	rt->mode = CH_MONO_STEREO;
	rt->low_slow = (double)rate1_table[st->parameter[7]];
	rt->low_fast = (double)rate1_table[st->parameter[8]];
	rt->low_accl = (double)st->parameter[9] * DIV_127;
	rt->low_level = calc_option_level(st->parameter[10]);
	rt->hi_slow = (double)rate1_table[st->parameter[11]];
	rt->hi_fast = (double)rate1_table[st->parameter[12]];
	rt->hi_accl = (double)st->parameter[13] * DIV_127;
	rt->hi_level = calc_option_level(st->parameter[14]);
	rt->separate = (double)st->parameter[15] * DIV_127;
	rt->speed = st->parameter[16] ? 1 : 0;
	// mix
	pe->level = calc_gs_level(st->parameter[19]) * GS_MULTI_EFX_LEVEL; // for multi efx
}

static void do_gs_s_rotary_multi(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_RotaryMulti *pe= (Info_GS_S_RotaryMulti *)ef->info;

	do_od_ds_multi(buf, count, &pe->info_od);
	do_eq3_multi(buf, count, &pe->info_eq);
	do_rotary_multi(buf, count, &pe->info_rt);
	effect_level_stereo(buf, count, pe->level);
}

/***** MSB 04 *****/
static void conv_gs_s_gtr_multi1(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_GtMulti1 *pe= (Info_GS_S_GtMulti1 *)ef->info;
	InfoCompressor *cmp = &pe->info_cmp;
	InfoOverdrive *od = &pe->info_od;
	InfoEQ2 * eq = &pe->info_eq;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoDelayLR *dly = &pe->info_dly;

	// compressor
	cmp->mode = st->parameter[3] ? CH_MIX_MONO : CH_NONE;
	cmp->attak = mix_double ((double)st->parameter[0] * DIV_127, 10, 500); // 10ms-500ms
	cmp->sustain = mix_double ((double)st->parameter[1] * DIV_127, 10, 500); // 10ms-500ms
	cmp->pre_gain = 3 * (1.0 + (double)st->parameter[1] * DIV_127); // dB
	cmp->post_gain = 0; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 0.5; // ratio? 1/2
	pe->level_cmp = cmp->mode ? calc_gs_level(st->parameter[2]) : 1.0;
	// od ds
	od->mode = st->parameter[10] ? CH_LEFT : CH_NONE;
	od->type = st->parameter[4];
	od->drive = st->parameter[5];
	od->amp_type = st->parameter[6];
	od->amp_sw = st->parameter[7];
	od->level = 1.0;
	// eq	
	eq->mode = st->parameter[10] ? CH_LEFT : CH_NONE;
	eq->high_freq = 5000;
	eq->high_gain = clip_int(st->parameter[8] - 0x40, -12, 12);
	eq->low_freq = 200;
	eq->low_gain = clip_int(st->parameter[9] - 0x40, -12, 12);
	// chorus flanger	
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = st->parameter[11] ? 1.6 : 1.0  ; // cho 1.0ms , fl 1.6ms
	cho->rate = (double)rate2_table[st->parameter[12]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[13]);	
	if(st->parameter[11])
		cho->feedback = (double)(st->parameter[14] - 64) * (0.763 * 2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[15]);
	pe->cho_dry = calc_dry_gs(st->parameter[15]);
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = delay_time_4_table[st->parameter[16]];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[17], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[127];
	pe->dly_wet = calc_wet_gs(st->parameter[18]);
	pe->dly_dry = calc_dry_gs(st->parameter[18]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]) * GS_MULTI_EFX_LEVEL; // for multi efx
}

static void do_gs_s_gtr_multi1(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_GtMulti1 *pe= (Info_GS_S_GtMulti1 *)ef->info;

	do_compressor_multi(buf, count, &pe->info_cmp);
	effect_level_stereo(buf, count, pe->level_cmp);
	do_eq2_multi(buf, count, &pe->info_eq);
	do_od_ds_multi(buf, count, &pe->info_od);
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	effect_left_mono(buf, count);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_gtr_multi2(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_GtMulti2 *pe= (Info_GS_S_GtMulti2 *)ef->info;
	InfoCompressor *cmp = &pe->info_cmp;
	InfoOverdrive *od = &pe->info_od;
	InfoEQ3 * eq = &pe->info_eq;
	InfoStereoChorus *cho = &pe->info_cho;

	// compressor
	cmp->mode = st->parameter[3] ? CH_MIX_MONO : CH_NONE;
	cmp->attak = mix_double ((double)st->parameter[0] * DIV_127, 10, 500); // 10ms-500ms
	cmp->sustain = mix_double ((double)st->parameter[1] * DIV_127, 10, 500); // 10ms-500ms
	cmp->pre_gain = 3 * (1.0 + (double)st->parameter[1] * DIV_127); // dB
	cmp->post_gain = 0; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 0.5; // ratio? 1/2
	pe->level_cmp = cmp->mode ? calc_gs_level(st->parameter[2]) : 1.0;
	// od ds
	od->mode = st->parameter[8] ? CH_LEFT : CH_NONE;
	od->type = st->parameter[4];
	od->drive = st->parameter[5];
	od->amp_type = st->parameter[6];
	od->amp_sw = st->parameter[7];
	od->level = 1.0;
	// eq	
	eq->mode = CH_LEFT;
	eq->low_freq = 200;
	eq->low_gain = clip_int(st->parameter[9] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_gs[st->parameter[10]];
	eq->mid_width = (double)eq_q_table_gs[clip_int(st->parameter[11], 0, 4)];
	eq->mid_gain = clip_int(st->parameter[12] - 64, -12, 12);
	eq->high_freq = 5000;
	eq->high_gain = clip_int(st->parameter[13] - 64, -12, 12);
	// chorus flanger	
	cho->mode = CH_MONO_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = st->parameter[14] ? 1.6 : 1.0  ; // cho 1.0ms , fl 1.6ms
	cho->rate = rate2_table[st->parameter[15]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[16]);	
	if(st->parameter[14])
		cho->feedback = (double)(st->parameter[17] - 64) * (0.763 * 2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[18]);
	pe->cho_dry = calc_dry_gs(st->parameter[18]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]) * GS_MULTI_EFX_LEVEL; // for multi efx
}

static void do_gs_s_gtr_multi2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_GtMulti2 *pe= (Info_GS_S_GtMulti2 *)ef->info;	

	do_compressor_multi(buf, count, &pe->info_cmp);
	effect_level_stereo(buf, count, pe->level_cmp);
	do_od_ds_multi(buf, count, &pe->info_od);
	do_eq3_multi(buf, count, &pe->info_eq);
	effect_left_mono(buf, count);
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_gtr_multi3(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_GtMulti3 *pe= (Info_GS_S_GtMulti3 *)ef->info;
//	InfoWah *wah = &pe->info_wah;
	InfoAutoWah *aw = &pe->info_aw;
	InfoOverdrive *od = &pe->info_od;
	InfoEQ2 * eq = &pe->info_eq;
	InfoStereoChorus *cho = &pe->info_cho;	
	InfoDelayLR *dly = &pe->info_dly;

	// wah
	aw->mode = st->parameter[3] ? CH_MIX_MONO : CH_NONE;
	aw->type = st->parameter[0] ? 1 : 0;
	aw->manual = calc_auto_wah_manual_gs(st->parameter[1]);
	aw->peak = calc_auto_wah_peak_gs(st->parameter[2]);
	aw->rate = 0.0;
	aw->depth = 0.0;
	aw->pol = 1;
	aw->lfo_sw = 0; // off
	aw->sens_sw = 0; // off
	aw->sens = 0.0;
	aw->release = 100.0; // ms
	//wah->mode = st->parameter[3] ? CH_MIX_MONO : CH_NONE;
	//wah->type = st->parameter[0] ? 1 : 0;
	//wah->manual = (double)manual_table[st->parameter[1]];
	//wah->peak = st->parameter[2] * DIV_127 * 12;
	// od ds
	od->mode = st->parameter[10] ?  CH_LEFT : CH_NONE;
	od->type = st->parameter[4];
	od->drive = st->parameter[5];
	od->amp_type = st->parameter[6];
	od->amp_sw = st->parameter[7];
	od->level = 1.0;
	// eq	
	eq->mode = st->parameter[10] ? CH_LEFT : CH_NONE;
	eq->high_freq = 5000;
	eq->high_gain = clip_int(st->parameter[8] - 0x40, -12, 12);
	eq->low_freq = 200;
	eq->low_gain = clip_int(st->parameter[9] - 0x40, -12, 12);
	// chorus flanger	
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = st->parameter[11] ? 1.6 : 1.0  ; // cho 1.0ms , fl 1.6ms
	cho->rate = (double)rate2_table[st->parameter[12]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[13]);	
	if(st->parameter[11])
		cho->feedback = (double)(st->parameter[14] - 64) * (0.763 * 2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[15]);
	pe->cho_dry = calc_dry_gs(st->parameter[15]);
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = (double)delay_time_4_table[st->parameter[16]];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[17], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[16]];
	pe->dly_wet = calc_wet_gs(st->parameter[18]);
	pe->dly_dry = calc_dry_gs(st->parameter[18]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]) * GS_MULTI_EFX_LEVEL; // for multi efx
}

static void do_gs_s_gtr_multi3(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_GtMulti3 *pe= (Info_GS_S_GtMulti3 *)ef->info;

	do_auto_wah_multi(buf, count, &pe->info_aw);
	do_eq2_multi(buf, count, &pe->info_eq);
	do_od_ds_multi(buf, count, &pe->info_od);
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	effect_left_mono(buf, count);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_clean_gt_multi1(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_CleanGtMulti1 *pe= (Info_GS_S_CleanGtMulti1 *)ef->info;
	InfoCompressor *cmp = &pe->info_cmp;
	InfoEQ3 * eq = &pe->info_eq;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoDelayLR *dly = &pe->info_dly;

	// compressor
	cmp->mode = st->parameter[3] ? CH_MIX_MONO : CH_NONE;
	cmp->attak = mix_double ((double)st->parameter[0] * DIV_127, 10, 500); // 10ms-500ms
	cmp->sustain = mix_double ((double)st->parameter[1] * DIV_127, 10, 500); // 10ms-500ms
	cmp->pre_gain = 3 * (1.0 + (double)st->parameter[1] * DIV_127); // dB
	cmp->post_gain = 0; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 0.5; // ratio? 1/2
	pe->level_cmp = cmp->mode ? calc_gs_level(st->parameter[2]) : 1.0;
	// eq	
	eq->mode = CH_LEFT;
	eq->low_freq = 200;
	eq->low_gain = clip_int(st->parameter[4] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_gs[st->parameter[5]];
	eq->mid_width = (double)eq_q_table_gs[clip_int(st->parameter[6], 0, 4)];
	eq->mid_gain = clip_int(st->parameter[7] - 64, -12, 12);
	eq->high_freq = 5000;
	eq->high_gain = clip_int(st->parameter[8] - 64, -12, 12);
	// chorus flanger	
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = st->parameter[9] ? 1.6 : 1.0  ; // cho 1.0ms , fl 1.6ms
	cho->rate = (double)rate2_table[st->parameter[10]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[11]);	
	if(st->parameter[9])
		cho->feedback = (double)(st->parameter[12] - 64) * (0.763 * 2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[13]);
	pe->cho_dry = calc_dry_gs(st->parameter[13]);
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = (double)delay_time_4_table[st->parameter[14]];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[15], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[16]];
	pe->dly_wet = calc_wet_gs(st->parameter[17]);
	pe->dly_dry = calc_dry_gs(st->parameter[17]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]) * GS_MULTI_EFX_LEVEL; // for multi efx
}

static void do_gs_s_clean_gt_multi1(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_CleanGtMulti1 *pe= (Info_GS_S_CleanGtMulti1 *)ef->info;

	do_compressor_multi(buf, count, &pe->info_cmp);
	effect_level_stereo(buf, count, pe->level_cmp);
	do_eq3_multi(buf, count, &pe->info_eq);
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	effect_left_mono(buf, count);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_clean_gt_multi2(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_CleanGtMulti2 *pe= (Info_GS_S_CleanGtMulti2 *)ef->info;
	InfoAutoWah *aw = &pe->info_aw;
	InfoEQ3 * eq = &pe->info_eq;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoDelayLR *dly = &pe->info_dly;

	// auto wah
	aw->mode = st->parameter[5] ? CH_MIX_MONO : CH_NONE;
	aw->type = st->parameter[0] ? 1 : 0;
	aw->sens = 0.0; 
	aw->release = 100.0; // ms
	aw->manual = calc_auto_wah_manual_gs(st->parameter[1]);
	aw->peak = calc_auto_wah_peak_gs(st->parameter[2]);
	aw->rate = (double)rate1_table[st->parameter[3]];
	aw->depth = (double)st->parameter[4] * DIV_127;
	aw->pol = 1;
	aw->lfo_sw = 1; // on
	aw->sens_sw = 1; // on
	// eq	
	eq->mode = CH_LEFT;
	eq->low_freq = 200;
	eq->low_gain = clip_int(st->parameter[6] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_gs[st->parameter[7]];
	eq->mid_width = (double)eq_q_table_gs[clip_int(st->parameter[8], 0, 4)];
	eq->mid_gain = clip_int(st->parameter[9] - 64, -12, 12);
	eq->high_freq = 5000;
	eq->high_gain = clip_int(st->parameter[10] - 64, -12, 12);
	// chorus flanger	
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = st->parameter[11] ? 1.6 : 1.0  ; // cho 1.0ms , fl 1.6ms
	cho->rate = (double)rate2_table[st->parameter[12]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[13]);	
	if(st->parameter[11])
		cho->feedback = (double)(st->parameter[14] - 64) * (0.763 * 2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[15]);
	pe->cho_dry = calc_dry_gs(st->parameter[15]);
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = (double)delay_time_4_table[st->parameter[16]];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[17], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[127];
	pe->dly_wet = calc_wet_gs(st->parameter[18]);
	pe->dly_dry = calc_dry_gs(st->parameter[18]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]) * GS_MULTI_EFX_LEVEL; // for multi efx
}

static void do_gs_s_clean_gt_multi2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_CleanGtMulti2 *pe= (Info_GS_S_CleanGtMulti2 *)ef->info;

	do_auto_wah_multi(buf, count, &pe->info_aw);
	do_eq3_multi(buf, count, &pe->info_eq);
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	effect_left_mono(buf, count);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_base_multi(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_BaseMulti *pe= (Info_GS_S_BaseMulti *)ef->info;
	InfoCompressor *cmp = &pe->info_cmp;
	InfoOverdrive *od = &pe->info_od;
	InfoEQ3 *eq = &pe->info_eq;
	InfoStereoChorus *cho = &pe->info_cho;	

	// compressor
	cmp->mode = st->parameter[3] ? CH_MIX_MONO : CH_NONE;
	cmp->attak = mix_double ((double)st->parameter[0] * DIV_127, 10, 500); // 10ms-500ms
	cmp->sustain = mix_double ((double)st->parameter[1] * DIV_127, 10, 500); // 10ms-500ms
	cmp->pre_gain = 3 * (1.0 + (double)st->parameter[1] * DIV_127); // dB
	cmp->post_gain = 0; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 0.5; // ratio? 1/2
	pe->level_cmp = cmp->mode ? calc_gs_level(st->parameter[2]) : 1.0;
	// od ds
	od->mode = st->parameter[8] ? CH_LEFT : CH_NONE;
	od->type = st->parameter[4];
	od->drive = st->parameter[5];
	od->amp_type = st->parameter[6];
	od->amp_sw = st->parameter[7];
	od->level = 1.0;
	// eq	
	eq->mode = CH_LEFT;
	eq->low_freq = 200;
	eq->low_gain = clip_int(st->parameter[9] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_gs[st->parameter[10]];
	eq->mid_width = (double)eq_q_table_gs[clip_int(st->parameter[11], 0, 4)];
	eq->mid_gain = clip_int(st->parameter[12] - 64, -12, 12);
	eq->high_freq = 5000;
	eq->high_gain = clip_int(st->parameter[13] - 64, -12, 12);
	// chorus flanger	
	cho->mode = CH_MONO_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = st->parameter[14] ? 1.6 : 1.0  ; // cho 1.0ms , fl 1.6ms
	cho->rate = rate2_table[st->parameter[15]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[16]);	
	if(st->parameter[14])
		cho->feedback = (double)(st->parameter[17] - 64) * (0.763 * 2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[18]);
	pe->cho_dry = calc_dry_gs(st->parameter[18]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]) * GS_MULTI_EFX_LEVEL; // for multi efx
}

static void do_gs_s_base_multi(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_BaseMulti *pe= (Info_GS_S_BaseMulti *)ef->info;

	do_compressor_multi(buf, count, &pe->info_cmp);
	effect_level_stereo(buf, count, pe->level_cmp);
	do_od_ds_multi(buf, count, &pe->info_od);
	do_eq3_multi(buf, count, &pe->info_eq);
	effect_left_mono(buf, count);
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_gs_s_rhodes_multi(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_RhodesMulti *pe= (Info_GS_S_RhodesMulti *)ef->info;
	InfoEnhancer *eh = &pe->info_eh;
	InfoPhaser *ph = &pe->info_ph;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoTremolo *trm = &pe->info_trm;

	// Enhancer
	eh->mode = CH_STEREO;
	eh->hpf_cutoff = 3200;
	eh->sens = (double)st->parameter[0] * DIV_127;	
	pe->eh_wet = (double)st->parameter[1] * DIV_127;	
	pe->eh_dry = 1.0;
	// Phaser
	ph->mode = CH_MIX_MONO;	
	ph->phase = 4;
	ph->manual = (double)manual_table[st->parameter[2]];
	ph->rate = (double)rate2_table[st->parameter[3]];
	ph->depth_cent = calc_chorus_depth_gs(st->parameter[4]);
	ph->feedback = 1.0;
	ph->offset = 0.5;
	ph->phase_diff = 0; // deg 0~360
	ph->reso = (double)st->parameter[5] * DIV_127 * 12.0; // 12dB
	pe->ph_wet = calc_wet_gs(st->parameter[6]);
	pe->ph_dry = 1.0; //calc_dry_gs(st->parameter[6]);
	// chorus flanger	
	cho->mode = CH_MIX_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = (double)cutoff_freq_table_gs[st->parameter[8]];
	cho->pdelay_ms = (double)pre_delay_time_table[st->parameter[9]];
	cho->rate = (double)rate2_table[st->parameter[10]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[11]);
	if(st->parameter[7])
		cho->feedback = (double)(st->parameter[12] - 64) * (0.763 * 2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[13]);
	pe->cho_dry = calc_dry_gs(st->parameter[13]);
	// Tremolo AutoPan	
	trm->mode = st->parameter[18] ? CH_STEREO : CH_NONE;
	trm->type = st->parameter[14] ? 1 : 0;
	trm->phase = st->parameter[14] ? 180 : 0; // deg
	trm->wave = lfo_wave_table_gs[clip_int(st->parameter[15], 0, 4)];
	trm->rate = (double)rate2_table[st->parameter[16]];
	trm->depth = (double)st->parameter[17] * DIV_127;
	// mix
	pe->level = calc_gs_level(st->parameter[19]) * GS_MULTI_EFX_LEVEL; // for multi efx
}

static void do_gs_s_rhodes_multi(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_RhodesMulti *pe= (Info_GS_S_RhodesMulti *)ef->info;
	
	send_efx_buffer(ef, buf, count);
	do_enhancer_multi(ef->efx_buf, count, &pe->info_eh);
	return_efx_buffer(ef, buf, count, pe->eh_wet, pe->eh_dry, 1.0);
	send_efx_buffer(ef, buf, count);
	do_phaser_multi(ef->efx_buf, count, &pe->info_ph);
	return_efx_buffer(ef, buf, count, pe->ph_wet, pe->ph_dry, 1.0);	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	do_tremolo_autopan(buf, count, &pe->info_trm);
	effect_level_stereo(buf, count, pe->level);	
}

/***** MSB 05 *****/
static void conv_gs_s_keyboard_multi(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_S_KeyboardMulti *pe= (Info_GS_S_KeyboardMulti *)ef->info;
	InfoRingModulator *rm = &pe->info_rm;
	InfoEQ3 *eq = &pe->info_eq;
	InfoPitchShifter *ps = &pe->info_ps;
	InfoPhaser *ph = &pe->info_ph;
	InfoDelayLR *dly = &pe->info_dly;

	// ring modulator
	rm->mode = CH_STEREO;
	rm->freq = (double)freq_table[st->parameter[0]] * DIV_1000;
	rm->lfo_sw = 0; // lfo off
	pe->rm_wet = calc_wet_gs(st->parameter[1]);
	pe->rm_dry = calc_dry_gs(st->parameter[1]);
	// eq
	eq->mode = CH_STEREO;
	eq->low_freq = 200;
	eq->low_gain = clip_int(st->parameter[2] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_gs[st->parameter[3]];
	eq->mid_width = (double)eq_q_table_gs[clip_int(st->parameter[4], 0, 4)];
	eq->mid_gain = clip_int(st->parameter[5] - 64, -12, 12);
	eq->high_freq = 5000;
	eq->high_gain = clip_int(st->parameter[6] - 64, -12, 12);
	// pitch shifter
	ps->mode = CH_MIX_MONO;
	ps->psl.pitch_cent = (double)(clip_int(st->parameter[7], 0x28, 0x58) - 0x40) * 100 + (clip_int(st->parameter[8], 0x0E, 0x72) - 0x40) * 2;
	ps->psl.pre_delay_ms = 0.0;
	ps->psl.feedback = 0.0;	
	ps->psl.ps_delay_ms = PS_CF_DELAY + clip_int(st->parameter[9], 0x00, 0x04) * 4; // PS_CF_DELAY + 16ms
	pe->pswet = calc_wet_gs(st->parameter[10]);
	pe->psdry = calc_dry_gs(st->parameter[10]);
	// phaser
	ph->mode = CH_MIX_MONO;
	ph->phase = 4;
	ph->manual = (double)manual_table[st->parameter[11]];
	ph->rate = (double)rate2_table[st->parameter[12]];
	ph->depth_cent = calc_chorus_depth_gs(st->parameter[13]);
	ph->feedback = 1.0;
	ph->offset = 0.5;
	ph->phase_diff = 0; // deg 0~360
	ph->reso = (double)st->parameter[14] * DIV_127 * 12.0; // 12dB
	pe->ph_wet = calc_wet_gs(st->parameter[15]);
	pe->ph_dry = 1.0; //calc_dry_gs(st->parameter[15]);
	// delay
	dly->mode = CH_MIX_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = (double)delay_time_4_table[st->parameter[16]];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[17], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[127];
	pe->dly_wet = calc_wet_gs(st->parameter[18]);
	pe->dly_dry = calc_dry_gs(st->parameter[18]);
	// mix
	pe->level = calc_gs_level(st->parameter[19]) * GS_MULTI_EFX_LEVEL; // for multi efx

}

static void do_gs_s_keyboard_multi(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_S_KeyboardMulti *pe= (Info_GS_S_KeyboardMulti *)ef->info;
	
	send_efx_buffer(ef, buf, count);
	do_ring_modulator_multi(ef->efx_buf, count, &pe->info_rm);
	return_efx_buffer(ef, buf, count, pe->rm_wet, pe->rm_dry, 1.0);
	do_eq3_multi(buf, count, &pe->info_eq);
	send_efx_buffer(ef, buf, count); 
	effect_mix_mono(ef->efx_buf, count);
	do_pitch_shifter_multi(ef->efx_buf, count, &pe->info_ps);
	return_efx_buffer(ef, buf, count, pe->pswet, pe->psdry, 1.0);
	send_efx_buffer(ef, buf, count);
	do_phaser_multi(ef->efx_buf, count, &pe->info_ph);
	return_efx_buffer(ef, buf, count, pe->ph_wet, pe->ph_dry, 1.0);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

/**************** GS INSERTION conv multi parallel ****************/

/***** MSB 11 *****/
static void conv_gs_p_chorus_delay(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_P_Cho_Delay *pe= (Info_GS_P_Cho_Delay *)ef->info;
	Info_P_Mix *mix = &pe->info_mix;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoDelayLR *dly = &pe->info_dly;

	// chorus
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = (double)pre_delay_time_table[st->parameter[0]];
	cho->rate = (double)rate1_table[st->parameter[1]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[2]);	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[4]);
	pe->cho_dry = calc_dry_gs(st->parameter[4]);
	// delay
	dly->mode = CH_RIGHT;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = (double)delay_time_3_table[st->parameter[5]];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[6], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[7]];
	pe->dly_wet = calc_wet_gs(st->parameter[8]);
	pe->dly_dry = calc_dry_gs(st->parameter[8]);
	// mix
	mix->panll = calc_pan_gs_left(st->parameter[15]);
	mix->panlr = calc_pan_gs_right(st->parameter[15]);
	mix->levell = calc_gs_level(st->parameter[16]);
	mix->panrl = calc_pan_gs_left(st->parameter[17]);
	mix->panrr = calc_pan_gs_right(st->parameter[17]);
	mix->levelr = calc_gs_level(st->parameter[18]);
	mix->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_p_chorus_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_P_Cho_Delay *pe= (Info_GS_P_Cho_Delay *)ef->info;	
	
	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_cho);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer_right(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	mix_parallel_effect(buf, count, &pe->info_mix);
}

static void conv_gs_p_flanger_delay(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_P_FL_Delay *pe= (Info_GS_P_FL_Delay *)ef->info;
	Info_P_Mix *mix = &pe->info_mix;
	InfoStereoChorus *fl = &pe->info_fl;
	InfoDelayLR *dly = &pe->info_dly;

	// flanger
	fl->mode = CH_LEFT;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = (double)pre_delay_time_table[st->parameter[0]];
	fl->rate = (double)rate1_table[st->parameter[1]];
	fl->depth_cent = calc_chorus_depth_gs(st->parameter[2]);	
	fl->feedback = (double)(st->parameter[3] - 64) * (0.763 * 2.0 * DIV_100);
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_wet_gs(st->parameter[4]);
	pe->fl_dry = calc_dry_gs(st->parameter[4]);
	// delay
	dly->mode = CH_RIGHT;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = (double)delay_time_3_table[st->parameter[5]];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[6], 0x0F, 0x71) - 0x40) * 2.0 * DIV_100;
	dly->high_damp = (double)HF_damp_freq_table_gs[st->parameter[7]];
	pe->dly_wet = calc_wet_gs(st->parameter[9]);
	pe->dly_dry = calc_dry_gs(st->parameter[9]);
	// mix
	mix->panll = calc_pan_gs_left(st->parameter[15]);
	mix->panlr = calc_pan_gs_right(st->parameter[15]);
	mix->levell = calc_gs_level(st->parameter[16]);
	mix->panrl = calc_pan_gs_left(st->parameter[17]);
	mix->panrr = calc_pan_gs_right(st->parameter[17]);
	mix->levelr = calc_gs_level(st->parameter[18]);
	mix->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_p_flanger_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_P_FL_Delay *pe= (Info_GS_P_FL_Delay *)ef->info;	
	
	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_fl);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer_left(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer_right(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	mix_parallel_effect(buf, count, &pe->info_mix);
}

static void conv_gs_p_chorus_flanger(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_P_Cho_Flanger *pe= (Info_GS_P_Cho_Flanger *)ef->info;
	Info_P_Mix *mix = &pe->info_mix;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoStereoChorus *fl = &pe->info_fl;	

	// chorus
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = pre_delay_time_table[st->parameter[0]];
	cho->rate = rate1_table[st->parameter[1]];
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[2]);	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->cho_wet = calc_wet_gs(st->parameter[4]);
	pe->cho_dry = calc_dry_gs(st->parameter[4]);
	// flanger
	fl->mode = CH_RIGHT;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = pre_delay_time_table[st->parameter[5]];
	fl->rate = rate1_table[st->parameter[6]];
	fl->depth_cent = calc_chorus_depth_gs(st->parameter[7]);	
	fl->feedback = (double)(st->parameter[8] - 64) * (0.763 * 2.0 * DIV_100);
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_wet_gs(st->parameter[9]);
	pe->fl_dry = calc_dry_gs(st->parameter[9]);
	fl->level = 1.0;
	// mix
	mix->panll = calc_pan_gs_left(st->parameter[15]);
	mix->panlr = calc_pan_gs_right(st->parameter[15]);
	mix->levell = calc_gs_level(st->parameter[16]);
	mix->panrl = calc_pan_gs_left(st->parameter[17]);
	mix->panrr = calc_pan_gs_right(st->parameter[17]);
	mix->levelr = calc_gs_level(st->parameter[18]);
	mix->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_p_chorus_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_P_Cho_Flanger *pe= (Info_GS_P_Cho_Flanger *)ef->info;	
	
	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_cho);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
//	do_chorus_p3(ef->efx_buf, count, &pe->info_fl);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer_right(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	mix_parallel_effect(buf, count, &pe->info_mix);
}

static void conv_gs_p_od1_od2(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_P_OD1_OD2 *pe= (Info_GS_P_OD1_OD2 *)ef->info;
	Info_P_Mix *mix = &pe->info_mix;
	InfoOverdrive *od = &pe->info_od1;
	InfoOverdrive *od2 = &pe->info_od2;

	// overdrive1
	od->mode = CH_LEFT;
	od->type = st->parameter[0];
	od->drive = st->parameter[1];
	od->amp_type = st->parameter[2];
	od->amp_sw = st->parameter[3] ? 1 : 0;	
	od->level = 1.0; 
	// overdrive2
	od2->mode = CH_RIGHT;
	od2->type = st->parameter[5];
	od2->drive = st->parameter[6];
	od2->amp_type = st->parameter[7];
	od2->amp_sw = st->parameter[8] ? 1 : 0;
	od2->level = 1.0; 	
	// mix
	mix->panll = calc_pan_gs_left(st->parameter[15]);
	mix->panlr = calc_pan_gs_right(st->parameter[15]);
	mix->levell = calc_gs_level(st->parameter[16]);
	mix->panrl = calc_pan_gs_left(st->parameter[17]);
	mix->panrr = calc_pan_gs_right(st->parameter[17]);
	mix->levelr = calc_gs_level(st->parameter[18]);
	mix->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_p_od1_od2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_P_OD1_OD2 *pe= (Info_GS_P_OD1_OD2 *)ef->info;	
//	do_od_ds_multi(buf, count, &pe->info_od1);	
//	do_od_ds_multi(buf, count, &pe->info_od2);
	do_od_ds_parallel(buf, count, &pe->info_od1, &pe->info_od2);
	mix_parallel_effect(buf, count, &pe->info_mix);
}

static void conv_gs_p_od_rotary(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_P_OD_Rotary *pe= (Info_GS_P_OD_Rotary *)ef->info;
	Info_P_Mix *mix = &pe->info_mix;
	InfoOverdrive *od = &pe->info_od;
	InfoRotary *rt = &pe->info_rt;

	// overdrive
	od->mode = CH_LEFT;
	od->type = st->parameter[0];
	od->drive = st->parameter[1];
	od->amp_type = st->parameter[2];
	od->amp_sw = st->parameter[3] ? 1 : 0;
	od->level = 1.0; 
	// rotary
	rt->mode = CH_RIGHT;
	rt->low_slow = (double)rate1_table[st->parameter[5]];
	rt->low_fast = (double)rate1_table[st->parameter[6]];
	rt->low_accl = (double)st->parameter[7] * DIV_127;
	rt->low_level = calc_option_level(st->parameter[8]);
	rt->hi_slow = (double)rate1_table[st->parameter[9]];
	rt->hi_fast = (double)rate1_table[st->parameter[10]];
	rt->hi_accl = (double)st->parameter[11] * DIV_127;
	rt->hi_level = calc_option_level(st->parameter[12]);
	rt->separate = (double)st->parameter[13] * DIV_127;
	rt->speed = st->parameter[14] ? 1 : 0;
	// mix
	mix->panll = calc_pan_gs_left(st->parameter[15]);
	mix->panlr = calc_pan_gs_right(st->parameter[15]);
	mix->levell = calc_gs_level(st->parameter[16]);
	mix->panrl = calc_pan_gs_left(st->parameter[17]);
	mix->panrr = calc_pan_gs_right(st->parameter[17]);
	mix->levelr = calc_gs_level(st->parameter[18]);
	mix->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_p_od_rotary(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_P_OD_Rotary *pe= (Info_GS_P_OD_Rotary *)ef->info;

	do_od_ds_multi(buf, count, &pe->info_od);
	do_rotary_multi(buf, count, &pe->info_rt);
	mix_parallel_effect(buf, count, &pe->info_mix);
}

static void conv_gs_p_od_phaser(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_P_OD_Phaser *pe= (Info_GS_P_OD_Phaser *)ef->info;
	Info_P_Mix *mix = &pe->info_mix;
	InfoOverdrive *od = &pe->info_od;
	InfoPhaser *ph = &pe->info_ph;

	// overdrive
	od->mode = CH_LEFT;
	od->type = st->parameter[0];
	od->drive = st->parameter[1];
	od->amp_type = st->parameter[2];
	od->amp_sw = st->parameter[3] ? 1 : 0;
	od->level = 1.0; 
	// phaser
	ph->mode = CH_RIGHT;
	ph->phase = 4;
	ph->manual = (double)manual_table[st->parameter[5]];
	ph->rate = (double)rate1_table[st->parameter[6]];
	ph->depth_cent = calc_chorus_depth_gs(st->parameter[7]);
	ph->feedback = 1.0;
	ph->offset = 0.5;
	ph->phase_diff = 0; // deg 0~360
	ph->reso = (double)st->parameter[8] * DIV_127 * 12.0; // 12dB
	pe->ph_wet = calc_wet_gs(st->parameter[9]);
	pe->ph_dry = 1.0; //calc_dry_gs(st->parameter[9]);
	// mix
	mix->panll = calc_pan_gs_left(st->parameter[15]);
	mix->panlr = calc_pan_gs_right(st->parameter[15]);
	mix->levell = calc_gs_level(st->parameter[16]);
	mix->panrl = calc_pan_gs_left(st->parameter[17]);
	mix->panrr = calc_pan_gs_right(st->parameter[17]);
	mix->levelr = calc_gs_level(st->parameter[18]);
	mix->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_p_od_phaser(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_P_OD_Phaser *pe= (Info_GS_P_OD_Phaser *)ef->info;	

	do_od_ds_multi(buf, count, &pe->info_od);
	send_efx_buffer(ef, buf, count);
	do_phaser_multi(ef->efx_buf, count, &pe->info_ph);
	return_efx_buffer_right(ef, buf, count, pe->ph_wet, pe->ph_dry, 1.0);
	mix_parallel_effect(buf, count, &pe->info_mix);
}

static void conv_gs_p_od_auto_wah(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_P_OD_AutoWah *pe= (Info_GS_P_OD_AutoWah *)ef->info;
	Info_P_Mix *mix = &pe->info_mix;
	InfoOverdrive *od = &pe->info_od;
	InfoAutoWah *aw = &pe->info_aw;

	// overdrive
	od->mode = CH_LEFT;
	od->type = st->parameter[0];
	od->drive = st->parameter[1];
	od->amp_type = st->parameter[2];
	od->amp_sw = st->parameter[3] ? 1 : 0;
	od->level = 1.0; 
	// auto wah
	aw->mode = CH_RIGHT;
	aw->type = st->parameter[5] ? 1 : 0;
	aw->sens = calc_auto_wah_sens_gs(st->parameter[6]);
	aw->release = 100.0; // ms
	aw->manual = calc_auto_wah_manual_gs(st->parameter[7]);
	aw->peak = calc_auto_wah_peak_gs(st->parameter[8]);
	aw->rate = (double)rate1_table[st->parameter[9]];
	aw->depth = (double)st->parameter[10] * DIV_127;
	aw->pol = st->parameter[11] ? 1 : 0;
	aw->lfo_sw = 1; // on
	aw->sens_sw = 1; // on
	// mix
	mix->panll = calc_pan_gs_left(st->parameter[15]);
	mix->panlr = calc_pan_gs_right(st->parameter[15]);
	mix->levell = calc_gs_level(st->parameter[16]);
	mix->panrl = calc_pan_gs_left(st->parameter[17]);
	mix->panrr = calc_pan_gs_right(st->parameter[17]);
	mix->levelr = calc_gs_level(st->parameter[18]);
	mix->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_p_od_auto_wah(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_P_OD_AutoWah *pe= (Info_GS_P_OD_AutoWah *)ef->info;	

	do_od_ds_multi(buf, count, &pe->info_od);
	do_auto_wah_multi(buf, count, &pe->info_aw);
	mix_parallel_effect(buf, count, &pe->info_mix);
}

static void conv_gs_p_phaser_rotary(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_P_PH_Rotary *pe= (Info_GS_P_PH_Rotary *)ef->info;
	Info_P_Mix *mix = &pe->info_mix;
	InfoPhaser *ph = &pe->info_ph;
	InfoRotary *rt = &pe->info_rt;

	// phaser
	ph->mode = CH_LEFT;
	ph->phase = 4;
	ph->manual = (double)manual_table[st->parameter[0]];
	ph->rate = (double)rate1_table[st->parameter[1]];
	ph->depth_cent = calc_chorus_depth_gs(st->parameter[5]);
	ph->feedback = 1.0;
	ph->offset = 0.5;
	ph->phase_diff = 0; // deg 0~360
	ph->reso = (double)st->parameter[3] * DIV_127 * 12.0; // 12dB
	pe->ph_wet = calc_wet_gs(st->parameter[4]);
	pe->ph_dry = 1.0; //calc_dry_gs(st->parameter[4]);
	// rotary
	rt->mode = CH_RIGHT;
	rt->low_slow = (double)rate1_table[st->parameter[5]];
	rt->low_fast = (double)rate1_table[st->parameter[6]];
	rt->low_accl = (double)st->parameter[7] * DIV_127;
	rt->low_level = calc_option_level(st->parameter[8]);
	rt->hi_slow = (double)rate1_table[st->parameter[9]];
	rt->hi_fast = (double)rate1_table[st->parameter[10]];
	rt->hi_accl = (double)st->parameter[11] * DIV_127;
	rt->hi_level = calc_option_level(st->parameter[12]);
	rt->separate = (double)st->parameter[13] * DIV_127;
	rt->speed = st->parameter[14] ? 1 : 0;
	// mix
	mix->panll = calc_pan_gs_left(st->parameter[15]);
	mix->panlr = calc_pan_gs_right(st->parameter[15]);
	mix->levell = calc_gs_level(st->parameter[16]);
	mix->panrl = calc_pan_gs_left(st->parameter[17]);
	mix->panrr = calc_pan_gs_right(st->parameter[17]);
	mix->levelr = calc_gs_level(st->parameter[18]);
	mix->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_p_phaser_rotary(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_P_PH_Rotary *pe= (Info_GS_P_PH_Rotary *)ef->info;	
	
	send_efx_buffer(ef, buf, count);
	do_phaser_multi(ef->efx_buf, count, &pe->info_ph);
	return_efx_buffer_left(ef, buf, count, pe->ph_wet, pe->ph_dry, 1.0);
	do_rotary_multi(buf, count, &pe->info_rt);
	mix_parallel_effect(buf, count, &pe->info_mix);
}

static void conv_gs_p_phaser_auto_wah(struct insertion_effect_gs_t *st, EffectList *ef)
{
	Info_GS_P_PH_AutoWah *pe= (Info_GS_P_PH_AutoWah *)ef->info;
	Info_P_Mix *mix = &pe->info_mix;
	InfoPhaser *ph = &pe->info_ph;
	InfoAutoWah *aw = &pe->info_aw;

	// phaser
	ph->mode = CH_LEFT;
	ph->phase = 4;
	ph->manual = (double)manual_table[st->parameter[0]];
	ph->rate = (double)rate1_table[st->parameter[1]];
	ph->depth_cent = calc_chorus_depth_gs(st->parameter[2]);
	ph->feedback = 1.0;
	ph->offset = 0.5;
	ph->phase_diff = 0; // deg 0~360
	ph->reso = (double)st->parameter[3] * DIV_127 * 12.0; // 12dB
	pe->ph_wet = calc_wet_gs(st->parameter[4]);
	pe->ph_dry = 1.0; //calc_dry_gs(st->parameter[4]);
	// auto wah
	aw->mode = CH_RIGHT;
	aw->type = st->parameter[5] ? 1 : 0;
	aw->sens = calc_auto_wah_sens_gs(st->parameter[6]);
	aw->release = 100.0; // ms
	aw->manual = calc_auto_wah_manual_gs(st->parameter[7]);
	aw->peak = calc_auto_wah_peak_gs(st->parameter[8]);
	aw->rate = (double)rate1_table[st->parameter[9]];
	aw->depth = (double)st->parameter[10] * DIV_127;
	aw->pol = st->parameter[11] ? 1 : 0;
	aw->lfo_sw = 1; // on
	aw->sens_sw = 1; // on
	// mix
	mix->panll = calc_pan_gs_left(st->parameter[15]);
	mix->panlr = calc_pan_gs_right(st->parameter[15]);
	mix->levell = calc_gs_level(st->parameter[16]);
	mix->panrl = calc_pan_gs_left(st->parameter[17]);
	mix->panrr = calc_pan_gs_right(st->parameter[17]);
	mix->levelr = calc_gs_level(st->parameter[18]);
	mix->level = calc_gs_level(st->parameter[19]);
}

static void do_gs_p_phaser_auto_wah(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_GS_P_PH_AutoWah *pe= (Info_GS_P_PH_AutoWah *)ef->info;
	
	send_efx_buffer(ef, buf, count);
	do_phaser_multi(ef->efx_buf, count, &pe->info_ph);
	return_efx_buffer_left(ef, buf, count, pe->ph_wet, pe->ph_dry, 1.0);
	do_auto_wah_multi(buf, count, &pe->info_aw);
	mix_parallel_effect(buf, count, &pe->info_mix);
}


/********************************** XG EFFECT conv **********************************/

const int8 amp_type_xg[] = {0, 1, 2, 3, 3, 4, 3};
const int8 cab_type_xg[] = {0, 1, 2, 3, 3, 1, 1};

static double ins_xg_revchar_to_roomsize(struct effect_xg_t *st)
{
	double rs;
	switch(st->type_msb) {
	case 0x01:
		switch(st->type_lsb) {
		default:
		case 0x00: rs = 0.90;	break;	/* Hall 1 */
		case 0x01: rs = 0.85;	break;	/* Hall 2 */
		case 0x06: rs = 0.82;	break;	/* Hall M */
		case 0x07: rs = 0.80;	break;	/* Hall L */
		}
		break;
	case 0x02:
		switch(st->type_lsb) {
		default:
		case 0x00: rs = 1.0;	break;	/* Room 1 */
		case 0x01: rs = 0.97;	break;	/* Room 2 */
		case 0x02: rs = 0.94;	break;	/* Room 3 */
		case 0x05: rs = 0.99;	break;	/* Room S */
		case 0x06: rs = 0.96;	break;	/* Room M */
		case 0x07: rs = 0.93;	break;	/* Room L */
		}
		break;
	case 0x03:
		switch(st->type_lsb) {
		default:
		case 0x00: rs = 0.92;	break;	/* Stage 1 */
		case 0x01: rs = 0.87;	break;	/* Stage 2 */
		}
		break;
	case 0x04:
		switch(st->type_lsb) {
		default:
		case 0x00: rs = 0.92;	break;	/* Plate */
		case 0x07: rs = 0.87;	break;	/* GM Plate*/
		}
		break;
	case 0x10:
		rs = 1.0;	break;	/* White Room */
		break;
	case 0x11:
		rs = 0.99;	break;	/* Tunnel */
		break;
	case 0x12:
		rs = 0.70;	break;	/* Canyon */
		break;
	case 0x13:
		rs = 0.80;	break;	/* Basement */
		break;
	}
	return rs;
}

static double ins_xg_revchar_to_level(struct effect_xg_t *st)
{
	double level;
	switch(st->type_msb) {
	case 0x01:
		switch(st->type_lsb) {
		default:
		case 0x00: level = 1.047180200;	break;	/* Hall 1 */
		case 0x01: level = 1.000000000;	break;	/* Hall 2 */
		case 0x06: level = 0.953180200;	break;	/* Hall M */
		case 0x07: level = 0.916000000;	break;	/* Hall L */
		}
		break;
	case 0x02:
		switch(st->type_lsb) {
		default:
		case 0x00: level = 1.224309745;	break;	/* Room 1 */
		case 0x01: level = 1.000000000;	break;	/* Room 2 */
		case 0x02: level = 0.744025605;	break;	/* Room 3 */
		case 0x05: level = 1.124309745;	break;	/* Room S */
		case 0x06: level = 0.944025605;	break;	/* Room M */
		case 0x07: level = 0.744025605;	break;	/* Room L */
		}
		break;
	case 0x03:
		switch(st->type_lsb) {
		default:
		case 0x00: level = 0.894025605;	break;	/* Stage 1 */
		case 0x01: level = 1.112309745;	break;	/* Stage 2 */
		}
		break;
	case 0x04:
		switch(st->type_lsb) {
		default:
		case 0x00: level = 0.894025605;	break;	/* Plate */
		case 0x07: level = 1.112309745;	break;	/* GM Plate*/
		}
		break;
	case 0x10:
		level = 1.200000000;	break;	/* White Room */
		break;
	case 0x11:
		level = 0.750000000;	break;	/* Tunnel */
		break;
	case 0x12:
		level = 0.700000000;	break;	/* Canyon */
		break;
	case 0x13:
		level = 0.900000000;	break;	/* Basement */
		break;
	}
	return level;
}

static double ins_xg_revchar_to_rt(struct effect_xg_t *st)
{
	double rt;
	switch(st->type_msb) {
	default:
	case 0x01:
		switch(st->type_lsb) {
		default:
		case 0x00: rt = 0.943006004;	break;	/* Hall 1 */
		case 0x01: rt = 0.920000000;	break;	/* Hall 2 */
		case 0x06: rt = 0.893006004;	break;	/* Hall M */
		case 0x07: rt = 0.850000000;	break;	/* Hall L */
		}
		break;
	case 0x02:
		switch(st->type_lsb) {
		default:
		case 0x00: rt = 0.516850262;	break;	/* Room 1 */
		case 0x01: rt = 0.754226004;	break;	/* Room 2 */
		case 0x02: rt = 1.004226004;	break;	/* Room 3 */
		case 0x05: rt = 0.804226004;	break;	/* Room S */
		case 0x06: rt = 0.876850262;	break;	/* Room M */
		case 0x07: rt = 0.954226004;	break;	/* Room L */
		}
		break;
	case 0x03:
		switch(st->type_lsb) {
		default:
		case 0x00: rt = 0.706850262;	break;	/* Stage 1 */
		case 0x01: rt = 1.002116004;	break;	/* Stage 2 */
		}
		break;
	case 0x04:
		switch(st->type_lsb) {
		default:
		case 0x00: rt = 0.943006004;	break;	/* Plate */
		case 0x07: rt = 0.920000000;	break;	/* GM Plate*/
		}
		break;
	case 0x10:
		rt = 0.50;	break;	/* White Room */
		break;
	case 0x11:
		rt = 1.00;	break;	/* Tunnel */
		break;
	case 0x12:
		rt = 0.650;	break;	/* Canyon */
		break;
	case 0x13:
		rt = 0.850;	break;	/* Basement */
		break;
	}
	return rt;
}

static void conv_xg_reverb1(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Reverb1 *info = (Info_XG_Reverb1 *)ef->info;
	InfoFreeverb *rvb = &info->rvb;
	InfoReverbEX *rvb2 = &info->rvb2;	
#ifdef REV_EX2
	InfoReverbEX2 *rvb3 = &info->rvb3;
#endif	
	InfoPreFilter *bpf = &info->bpf;

	bpf->freqH = eq_freq_table_xg[clip_int(st->param_lsb[3], 0x00, 0x34)];
	bpf->freqL = eq_freq_table_xg[clip_int(st->param_lsb[4], 0x22, 0x3C)];
	init_pre_bpf(bpf);

#ifdef REV_EX2		
	if((opt_reverb_control >= 7 && opt_reverb_control < 9) || (opt_reverb_control <= -768 && opt_reverb_control > -1024)){
		info->rev_type = 2; // reverb ex2
		if(st->connection == XG_CONN_SYSTEM_REVERB){
			rvb3->mode = CH_STEREO;
		}else{
			rvb3->mode = CH_MIX_STEREO;
		}	
		switch(st->type_msb) {
		case 0x01:
			switch(st->type_lsb) {
			default:
			case 0x00:/* Hall 1 */
				rvb3->height = 12.0; // m
				rvb3->width = 14.0; // m
				rvb3->depth = 20.0; // m
				rvb3->rev_damp_type = FILTER_LPF6;
				rvb3->rev_damp_bal = 0.75;
				break;
			case 0x01:/* Hall 2 */
				rvb3->height = 16.0; // m
				rvb3->width = 18.0; // m
				rvb3->depth = 27.0; // m
				rvb3->rev_damp_type = FILTER_LPF6;
				rvb3->rev_damp_bal = 0.95;
				break;
			case 0x06:/* Hall M */
				rvb3->height = 12.0; // m
				rvb3->width = 16.0; // m
				rvb3->depth = 23.0; // m
				rvb3->rev_damp_type = FILTER_LPF6;
				rvb3->rev_damp_bal = 0.85;
				break;
			case 0x07:/* Hall L */
				rvb3->height = 18.0; // m
				rvb3->width = 21.0; // m
				rvb3->depth = 30.0; // m
				rvb3->rev_damp_type = FILTER_LPF6;
				rvb3->rev_damp_bal = 0.85;
				break;
			}
			break;
		case 0x02:
			switch(st->type_lsb) {
			default:
			case 0x00:/* Room 1 */
				rvb3->height = 3.0; // m
				rvb3->width = 5.0; // m
				rvb3->depth = 7.0; // m
				rvb3->rev_damp_type = FILTER_LPF6;
				rvb3->rev_damp_bal = 0.5;
				break;
			case 0x01:/* Room 2 */
				rvb3->height = 4.0; // m
				rvb3->width = 8.0; // m
				rvb3->depth = 10.0; // m
				rvb3->rev_damp_type = FILTER_LPF6;
				rvb3->rev_damp_bal = 0.75;
				break;
			case 0x02:/* Room 3 */
				rvb3->height = 5.0; // m
				rvb3->width = 12.0; // m
				rvb3->depth = 15.0; // m
				rvb3->rev_damp_type = FILTER_LPF6;
				rvb3->rev_damp_bal = 0.95;
				break;
			case 0x05:/* Room S */
				rvb3->height = 3.0; // m
				rvb3->width = 4.0; // m
				rvb3->depth = 5.0; // m
				rvb3->rev_damp_type = FILTER_LPF6;
				rvb3->rev_damp_bal = 0.45;
				break;
			case 0x06:/* Room M */
				rvb3->height = 4.0; // m
				rvb3->width = 8.0; // m
				rvb3->depth = 10.0; // m
				rvb3->rev_damp_type = FILTER_LPF6;
				rvb3->rev_damp_bal = 0.80;
				break;
			case 0x07:/* Room L */
				rvb3->height = 5.0; // m
				rvb3->width = 12.0; // m
				rvb3->depth = 15.0; // m
				rvb3->rev_damp_type = FILTER_LPF6;
				rvb3->rev_damp_bal = 0.98;
				break;
			}
			break;
		case 0x03:
			switch(st->type_lsb) {
			default:
			case 0x00:/* Stage 1 */
				rvb3->height = 10.0; // m
				rvb3->width = 12.0; // m
				rvb3->depth = 15.0; // m
				rvb3->rev_damp_type = FILTER_LPF6;
				rvb3->rev_damp_bal = 0.85;
				break;
			case 0x01:/* Stage 2 */
				rvb3->height = 12.0; // m
				rvb3->width = 13.0; // m
				rvb3->depth = 18.0; // m
				rvb3->rev_damp_type = FILTER_LPF6;
				rvb3->rev_damp_bal = 0.95;
				break;
			}
			break;
		}
		rvb3->rev_time_sec = reverb_time_table_xg[clip_int(st->param_lsb[0], 0x00, 0x45)];
	//	rvb3->rev_dif = 0.5 * (10 + clip_int(st->param_lsb[1], 0x00, 0x0a)) * DIV_20;		
		rvb3->er_time_ms = delay_time_table_xg[clip_int(st->param_lsb[2], 0x00, 0x3F)];
		rvb3->rev_dly_ms = delay_time_table_xg[clip_int(st->param_lsb[10], 0x00, 0x3F)];
		rvb3->density = (double)clip_int(st->param_lsb[11], 0x00, 0x04) * DIV_4;
		rvb3->er_level = calc_option_level(clip_int(st->param_lsb[12], 0x01, 0x7F));
		rvb3->rev_level = calc_option_level(127 - clip_int(st->param_lsb[12], 0x01, 0x7F));		
		rvb3->rev_damp_freq = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10 * 22000.0;
		rvb3->er_damp_freq = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10 * 22000.0;
		rvb3->rev_feedback = (double)(clip_int(st->param_lsb[14], 0x01, 0x7F) - 0x40) * DIV_127; //0.125;
		rvb3->level = 1.0;
	}else 
#endif
	if(otd.efx_CustomRevType){
		info->rev_type = 1; // reverb ex
		if(st->connection == XG_CONN_SYSTEM_REVERB){
			rvb2->mode = CH_STEREO;
		}else{
			rvb2->mode = CH_MIX_STEREO;
		}	
		switch(st->type_msb) {
		case 0x01:
			switch(st->type_lsb) {
			default:
			case 0x00:/* Hall 1 */
				rvb2->height = 12.0; // m
				rvb2->width = 14.0; // m
				rvb2->depth = 20.0; // m
				rvb2->rev_damp_type = FILTER_LPF6;
				rvb2->rev_damp_bal = 0.75;
				break;
			case 0x01:/* Hall 2 */
				rvb2->height = 16.0; // m
				rvb2->width = 18.0; // m
				rvb2->depth = 27.0; // m
				rvb2->rev_damp_type = FILTER_LPF6;
				rvb2->rev_damp_bal = 0.95;
				break;
			case 0x06:/* Hall M */
				rvb2->height = 12.0; // m
				rvb2->width = 16.0; // m
				rvb2->depth = 23.0; // m
				rvb2->rev_damp_type = FILTER_LPF6;
				rvb2->rev_damp_bal = 0.85;
				break;
			case 0x07:/* Hall L */
				rvb2->height = 18.0; // m
				rvb2->width = 21.0; // m
				rvb2->depth = 30.0; // m
				rvb2->rev_damp_type = FILTER_LPF6;
				rvb2->rev_damp_bal = 0.85;
				break;
			}
			break;
		case 0x02:
			switch(st->type_lsb) {
			default:
			case 0x00:/* Room 1 */
				rvb2->height = 3.0; // m
				rvb2->width = 5.0; // m
				rvb2->depth = 7.0; // m
				rvb2->rev_damp_type = FILTER_LPF6;
				rvb2->rev_damp_bal = 0.5;
				break;
			case 0x01:/* Room 2 */
				rvb2->height = 4.0; // m
				rvb2->width = 8.0; // m
				rvb2->depth = 10.0; // m
				rvb2->rev_damp_type = FILTER_LPF6;
				rvb2->rev_damp_bal = 0.75;
				break;
			case 0x02:/* Room 3 */
				rvb2->height = 5.0; // m
				rvb2->width = 12.0; // m
				rvb2->depth = 15.0; // m
				rvb2->rev_damp_type = FILTER_LPF6;
				rvb2->rev_damp_bal = 0.95;
				break;
			case 0x05:/* Room S */
				rvb2->height = 3.0; // m
				rvb2->width = 4.0; // m
				rvb2->depth = 5.0; // m
				rvb2->rev_damp_type = FILTER_LPF6;
				rvb2->rev_damp_bal = 0.45;
				break;
			case 0x06:/* Room M */
				rvb2->height = 4.0; // m
				rvb2->width = 8.0; // m
				rvb2->depth = 10.0; // m
				rvb2->rev_damp_type = FILTER_LPF6;
				rvb2->rev_damp_bal = 0.80;
				break;
			case 0x07:/* Room L */
				rvb2->height = 5.0; // m
				rvb2->width = 12.0; // m
				rvb2->depth = 15.0; // m
				rvb2->rev_damp_type = FILTER_LPF6;
				rvb2->rev_damp_bal = 0.98;
				break;
			}
			break;
		case 0x03:
			switch(st->type_lsb) {
			default:
			case 0x00:/* Stage 1 */
				rvb2->height = 10.0; // m
				rvb2->width = 12.0; // m
				rvb2->depth = 15.0; // m
				rvb2->rev_damp_type = FILTER_LPF6;
				rvb2->rev_damp_bal = 0.85;
				break;
			case 0x01:/* Stage 2 */
				rvb2->height = 12.0; // m
				rvb2->width = 13.0; // m
				rvb2->depth = 18.0; // m
				rvb2->rev_damp_type = FILTER_LPF6;
				rvb2->rev_damp_bal = 0.95;
				break;
			}
			break;
		}
		rvb2->rev_time_sec = reverb_time_table_xg[clip_int(st->param_lsb[0], 0x00, 0x45)];
	//	rvb2->rev_dif = 0.5 * (10 + clip_int(st->param_lsb[1], 0x00, 0x0a)) * DIV_20;		
		rvb2->er_time_ms = delay_time_table_xg[clip_int(st->param_lsb[2], 0x00, 0x3F)];
		rvb2->rev_dly_ms = delay_time_table_xg[clip_int(st->param_lsb[10], 0x00, 0x3F)];
		rvb2->density = (double)clip_int(st->param_lsb[11], 0x00, 0x04) * DIV_4;
		rvb2->er_level = calc_option_level(clip_int(st->param_lsb[12], 0x01, 0x7F));
		rvb2->rev_level = calc_option_level(127 - clip_int(st->param_lsb[12], 0x01, 0x7F));		
		rvb2->rev_damp_freq = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10 * 22000.0;
		rvb2->er_damp_freq = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10 * 22000.0;
		rvb2->rev_feedback = (double)(clip_int(st->param_lsb[14], 0x01, 0x7F) - 0x40) * DIV_127; //0.125;
		rvb2->level = 1.0;
	}else{
// freeverb
		info->rev_type = 0;
		if(st->connection == XG_CONN_SYSTEM_REVERB){
			rvb->mode = CH_STEREO;
		}else{
			rvb->mode = CH_MIX_STEREO;
		}
		rvb->rev_time_sec = reverb_time_table_xg[clip_int(st->param_lsb[0], 0x00, 0x45)];
		rvb->rev_dif = 0.5 * (10 + clip_int(st->param_lsb[1], 0x00, 0x0a)) * DIV_20;
		rvb->er_time_ms = delay_time_table_xg[clip_int(st->param_lsb[2], 0x00, 0x3F)];
		rvb->rev_dly_ms = delay_time_table_xg[clip_int(st->param_lsb[10], 0x00, 0x3F)];
	//	rvb->density = clip_int(st->param_lsb[11], 0x00, 0x04);
		rvb->er_level = calc_option_level(clip_int(st->param_lsb[12], 0x01, 0x7F));
		rvb->rev_level = calc_option_level(127 - clip_int(st->param_lsb[12], 0x01, 0x7F));
		rvb->rev_damp = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10; // initialdamp;
		rvb->er_damp_freq = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10 * 22000.0;
		rvb->rev_feedback = (double)(clip_int(st->param_lsb[14], 0x01, 0x7F) - 0x40) * DIV_127; //0.125;
		rvb->rev_rt = ins_xg_revchar_to_rt(st);
		rvb->rev_roomsize = ins_xg_revchar_to_roomsize(st);
		rvb->rev_wet = ins_xg_revchar_to_level(st);
		rvb->rev_width = initialwidth;
	}
	info->rev_dry = calc_dry_xg(st->param_lsb[9], st);
	info->rev_wet = calc_wet_xg(st->param_lsb[9], st);
	info->rev_level = 1.0;
}

static void do_xg_reverb1(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Reverb1 *info = (Info_XG_Reverb1 *)ef->info;
	InfoFreeverb *rvb = &info->rvb;
	InfoReverbEX *rvb2 = &info->rvb2;
#ifdef REV_EX2
	InfoReverbEX2 *rvb3 = &info->rvb3;
#endif
	InfoPreFilter *bpf = &info->bpf;

	send_efx_buffer(ef, buf, count);
	do_pre_bpf(ef->efx_buf, count, bpf);	
#ifdef REV_EX2	
	if(info->rev_type == 2)
		do_reverb_ex2(ef->efx_buf, count, rvb3);
	else 
#endif
	if(info->rev_type)
		do_reverb_ex(ef->efx_buf, count, rvb2);
	else
		do_freeverb(ef->efx_buf, count, rvb);
	return_efx_buffer(ef, buf, count, info->rev_wet, info->rev_dry, info->rev_level);
}

static void conv_xg_plate(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Plate *info = (Info_XG_Plate *)ef->info;
	InfoPlateReverb *rvb = &info->rvb;		
	InfoPreFilter *bpf = &info->bpf;

	bpf->freqH = eq_freq_table_xg[clip_int(st->param_lsb[3], 0x00, 0x34)];
	bpf->freqL = eq_freq_table_xg[clip_int(st->param_lsb[4], 0x22, 0x3C)];
	init_pre_bpf(bpf);

	if(st->connection == XG_CONN_SYSTEM_REVERB){
		rvb->mode = CH_STEREO;
	}else{
		rvb->mode = CH_MIX_STEREO;
	}
	rvb->rev_time_sec = reverb_time_table_xg[clip_int(st->param_lsb[0], 0x00, 0x45)];
	rvb->rev_diff = 0.5 * (10 + clip_int(st->param_lsb[1], 0x00, 0x0a)) * DIV_20;
	rvb->er_time_ms = delay_time_table_xg[clip_int(st->param_lsb[2], 0x00, 0x3F)];
//	rvb->rev_delay = delay_time_table_xg[clip_int(st->param_lsb[10], 0x00, 0x3F)];
//	rvb->density = clip_int(st->param_lsb[11], 0x00, 0x04);
	rvb->er_level = calc_option_level(clip_int(st->param_lsb[12], 0x01, 0x7F));
	rvb->rev_level = calc_option_level(127 - clip_int(st->param_lsb[12], 0x01, 0x7F));
	rvb->rev_damp = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10; // initialdamp;
	rvb->rev_feedback = (double)(clip_int(st->param_lsb[14], 0x01, 0x7F) - 0x40) * DIV_127; //0.125;
	rvb->rev_wet = 1.0;	
	info->rev_dry = calc_dry_xg(st->param_lsb[9], st);
	info->rev_wet = calc_wet_xg(st->param_lsb[9], st);
	info->rev_level = 1.0;
}
static void do_xg_plate(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Plate *info = (Info_XG_Plate *)ef->info;
	InfoPlateReverb *rvb = &info->rvb;
	InfoPreFilter *bpf = &info->bpf;

	send_efx_buffer(ef, buf, count);
	do_pre_bpf(ef->efx_buf, count, bpf);
	do_plate_reverb(ef->efx_buf, count, rvb);
	return_efx_buffer(ef, buf, count, info->rev_wet, info->rev_dry, info->rev_level);
}

static void conv_xg_delay_lcr(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_DelayLCR *info = (Info_XG_DelayLCR *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;
	int time_max = st->connection ? 14860 : 7429;

	dly->tap = 3;
	dly->dtime[0] = (double)clip_int(st->param_msb[0] * 128 + st->param_lsb[0], 1, time_max) * DIV_10;
	dly->dtime[1] = (double)clip_int(st->param_msb[1] * 128 + st->param_lsb[1], 1, time_max) * DIV_10;
	dly->dtime[2] = (double)clip_int(st->param_msb[2] * 128 + st->param_lsb[2], 1, time_max) * DIV_10;
	dly->dtime[3] = (double)clip_int(st->param_msb[3] * 128 + st->param_lsb[3], 1, time_max) * DIV_10; // [tap] for feedback_delay	
	dly->pan[0] = 0x40;
	dly->pan[1] = 0x00;
	dly->pan[2] = 0x7F;
	dly->pan[3] = 0x40; // [tap] for feedback_delay
	dly->feedback = (double)(st->param_lsb[4] - 64) * (0.763 * 2.0 * DIV_100);
	dly->dlevel[0] = calc_option_level(st->param_lsb[5]);
	dly->dlevel[1] = 1.0;
	dly->dlevel[2] = 1.0;
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[6], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = 1.0;
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[12], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[13] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[14], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[15] - 64, -12, 12);
}

static void do_xg_delay_lcr(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_DelayLCR *info = (Info_XG_DelayLCR *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);	
	send_efx_buffer(ef, buf, count);
	do_multi_tap_delay(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_xg_delay_lr(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_DelayLR *info = (Info_XG_DelayLR *)ef->info;
	InfoDelayLR *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;
	int time_max = st->connection ? 14860 : 7429;

	dly->mode = CH_STEREO;
	dly->ldelay = (double)clip_int(st->param_msb[0] * 128 + st->param_lsb[0], 1, time_max) * DIV_10;
	dly->rdelay = (double)clip_int(st->param_msb[1] * 128 + st->param_lsb[1], 1, time_max) * DIV_10;
	dly->fdelay1 = (double)clip_int(st->param_msb[2] * 128 + st->param_lsb[2], 1, time_max) * DIV_10;
	dly->fdelay2 = (double)clip_int(st->param_msb[3] * 128 + st->param_lsb[3], 1, time_max) * DIV_10;
	dly->feedback = (double)(st->param_lsb[4] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[5], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[9], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[9], st);
	info->dly_level = 1.0;
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[12], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[13] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[14], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[15] - 64, -12, 12);
}

static void do_xg_delay_lr(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_DelayLR *info = (Info_XG_DelayLR *)ef->info;
	InfoDelayLR *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_echo(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Echo *info = (Info_XG_Echo *)ef->info;
	InfoEcho *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;
	int time_max = st->connection ? 7430 : 3714;

	dly->ldelay1 = (double)clip_int(st->param_msb[0] * 128 + st->param_lsb[0], 1, time_max) * DIV_10;
	dly->lfeedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->rdelay1 = (double)clip_int(st->param_msb[2] * 128 + st->param_lsb[2], 1, time_max) * DIV_10;
	dly->rfeedback = (double)(st->param_lsb[3] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[4], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->ldelay2 = (double)clip_int(st->param_msb[5] * 128 + st->param_lsb[5], 1, time_max) * DIV_10;
	dly->rdelay2 = (double)clip_int(st->param_msb[6] * 128 + st->param_lsb[6], 1, time_max) * DIV_10;
	dly->delay2_level = calc_xg_level(st->param_lsb[7], st);
	info->dly_level = 1.0;
	info->dly_dry = calc_dry_xg(st->param_lsb[9], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[9], st);
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[12], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[13] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[14], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[15] - 64, -12, 12);
}

static void do_xg_echo(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Echo *info = (Info_XG_Echo *)ef->info;
	InfoEcho *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_echo(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_cross_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_CrossDelay *info = (Info_XG_CrossDelay *)ef->info;
	InfoDelayLR *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;
	int time_max = st->connection ? 7430 : 3714;

	dly->mode = CH_STEREO;
	dly->ldelay = dly->fdelay1 = (double)clip_int(st->param_msb[0] * 128 + st->param_lsb[0], 1, time_max) * DIV_10;
	dly->rdelay = dly->fdelay2 = (double)clip_int(st->param_msb[1] * 128 + st->param_lsb[1], 1, time_max) * DIV_10;
	dly->feedback = (double)(st->param_lsb[2] - 64) * (0.763 * 2.0 * DIV_100);
	dly->fb_mode = 1; // cross
	dly->phasel = 0;
	dly->phaser = 0;
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[4], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	info->dly_dry = calc_dry_xg(st->param_lsb[9], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[9], st);
	info->dly_level = 1.0;
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[12], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[13] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[14], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[15] - 64, -12, 12);
}

static void do_xg_cross_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_CrossDelay *info = (Info_XG_CrossDelay *)ef->info;
	InfoDelayLR *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_early_ref1(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_EarlyRef1 *info = (Info_XG_EarlyRef1 *)ef->info;
	InfoEarlyReflection *er = &info->er;	
	InfoPreFilter *bpf = &info->bpf;

	bpf->freqH = eq_freq_table_xg[clip_int(st->param_lsb[5], 0x00, 0x34)];
	bpf->freqL = eq_freq_table_xg[clip_int(st->param_lsb[6], 0x22, 0x3C)];
	init_pre_bpf(bpf);

	er->mode = CH_MIX_STEREO;
//	er->type = clip_int(st->param_lsb[0], 0, 5);
	er->roomsize = room_size_table_xg[clip_int(st->param_lsb[1], 0, 44)];
	er->dif = (1 + clip_int(st->param_lsb[2], 0x00, 0x0a)) * DIV_12;
	er->er_time_ms = delay_time_table_xg[clip_int(st->param_lsb[3], 0x00, 0x7F)];
	er->feedback = (double)(clip_int(st->param_lsb[4], 0x01, 0x7F) - 0x40) * DIV_127;
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = 1.0;	
//	er->liveness = clip_int(st->param_lsb[10], 0, 10);
//	er->density = clip_int(st->param_lsb[11], 0, 3);
	er->damp_freq = (double)clip_int(st->param_lsb[12], 1, 10) * DIV_10 * 22000.0;	
}

static void do_xg_early_ref1(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_EarlyRef1 *info = (Info_XG_EarlyRef1 *)ef->info;
	InfoEarlyReflection *er = &info->er;
	InfoPreFilter *bpf = &info->bpf;

	send_efx_buffer(ef, buf, count);
	do_pre_bpf(ef->efx_buf, count, bpf);
	do_early_reflection(ef->efx_buf, count, er);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_xg_early_ref2(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_EarlyRef2 *info = (Info_XG_EarlyRef2 *)ef->info;
	InfoEarlyReflection *er = &info->er;
	InfoPreFilter *bpf = &info->bpf;

	bpf->freqH = eq_freq_table_xg[clip_int(st->param_lsb[5], 0x00, 0x34)];
	bpf->freqL = eq_freq_table_xg[clip_int(st->param_lsb[6], 0x22, 0x3C)];
	init_pre_bpf(bpf);	

	er->mode = CH_MIX_STEREO;
//	er->type = clip_int(st->param_lsb[0], 0, 5);
	er->roomsize = room_size_table_xg[clip_int(st->param_lsb[1], 0, 44)];
	er->dif = (1 + clip_int(st->param_lsb[2], 0x00, 0x0a)) * DIV_12;
	er->er_time_ms = delay_time_table_xg[clip_int(st->param_lsb[3], 0x00, 0x7F)];
	er->feedback = (double)(clip_int(st->param_lsb[4], 0x01, 0x7F) - 0x40) * DIV_127;
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = 1.0;	
//	er->liveness = clip_int(st->param_lsb[10], 0, 10);
//	er->density = clip_int(st->param_lsb[11], 0, 3);
	er->damp_freq = (double)clip_int(st->param_lsb[12], 1, 10) * DIV_10 * 22000.0;
}

static void do_xg_early_ref2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_EarlyRef2 *info = (Info_XG_EarlyRef2 *)ef->info;
	InfoEarlyReflection *er = &info->er;
	InfoPreFilter *bpf = &info->bpf;

	send_efx_buffer(ef, buf, count);
	do_pre_bpf(ef->efx_buf, count, bpf);
	do_early_reflection(ef->efx_buf, count, er);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_xg_gate_reverb(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_GateReverb *info = (Info_XG_GateReverb *)ef->info;
	InfoGateReverb *gr = &info->gr;
	InfoPreFilter *bpf = &info->bpf;

	bpf->freqL = eq_freq_table_xg[clip_int(st->param_lsb[3], 0x00, 0x34)];
	bpf->freqH = eq_freq_table_xg[clip_int(st->param_lsb[4], 0x22, 0x3C)];
	init_pre_bpf(bpf);	
	
	gr->mode = CH_MIX_STEREO;
	gr->gate_time_ms = 200; // ms
	gr->rev_time_sec = 2.0;
	gr->rev_damp_type = FILTER_LPF6;
	gr->rev_damp_bal = 0.85;
	gr->er_level = 0.5;
	gr->rev_level = 0.5;
	gr->type = clip_int(st->param_lsb[0], 0x00, 0x01);
	gr->room_size = room_size_table_xg[clip_int(st->param_lsb[1], 0x00, 0x44)];
	gr->er_time_ms = delay_time_table_xg[clip_int(st->param_lsb[2], 0x00, 0x3F)];
	gr->rev_feedback = (double)(clip_int(st->param_lsb[4], 0x01, 0x7F) - 0x40) * DIV_127; //0.125;
	gr->density = (double)clip_int(st->param_lsb[11], 0x00, 0x04) * DIV_4;	
	gr->rev_damp_freq = (double)clip_int(st->param_lsb[12], 0x01, 0x0A) * DIV_10 * 22000.0;
	gr->er_damp_freq = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10 * 22000.0;
	info->rev_dry = calc_dry_xg(st->param_lsb[9], st);
	info->rev_wet = calc_wet_xg(st->param_lsb[9], st);
	info->rev_level = 1.0;
}

static void do_xg_gate_reverb(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_GateReverb *info = (Info_XG_GateReverb *)ef->info;
	InfoGateReverb *gr = &info->gr;
	InfoPreFilter *bpf = &info->bpf;

	send_efx_buffer(ef, buf, count);
	do_gate_reverb(ef->efx_buf, count, gr);	
	return_efx_buffer(ef, buf, count, info->rev_wet, info->rev_dry, info->rev_level);
}

static void conv_xg_reverb2(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Reverb2 *info = (Info_XG_Reverb2 *)ef->info;
	InfoFreeverb *rvb = &info->rvb;
	InfoReverbEX *rvb2 = &info->rvb2;
#ifdef REV_EX2
	InfoReverbEX2 *rvb3 = &info->rvb3;
#endif
	InfoPreFilter *bpf = &info->bpf;

	bpf->freqH = eq_freq_table_xg[clip_int(st->param_lsb[3], 0x00, 0x34)];
	bpf->freqL = eq_freq_table_xg[clip_int(st->param_lsb[4], 0x22, 0x3C)];
	init_pre_bpf(bpf);

#ifdef REV_EX2	
	if((opt_reverb_control >= 7 && opt_reverb_control < 9) || (opt_reverb_control <= -768 && opt_reverb_control > -1024)){
		info->rev_type = 2; // reverb ex2
		if(st->connection == XG_CONN_SYSTEM_REVERB){
			rvb3->mode = CH_STEREO;
		}else{
			rvb3->mode = CH_MIX_STEREO;
		}		
		switch(st->type_msb) {
		default:
		case 0x10:/* White Room */
			rvb3->rev_damp_type = FILTER_LPF6;
			break;
		case 0x11:/* Tunnel */
			rvb3->rev_damp_type = FILTER_LPF6x2;
			break;
		case 0x12:/* Canyon */
			rvb3->rev_damp_type = FILTER_LPF6;
			break;
		case 0x13:/* Basement */
			rvb3->rev_damp_type = FILTER_LPF6;
			break;
		}
		rvb3->rev_time_sec = reverb_time_table_xg[clip_int(st->param_lsb[0], 0x00, 0x45)];
	//	rvb3->rev_dif = 0.5 * (10 + clip_int(st->param_lsb[1], 0x00, 0x0a)) * DIV_20;		
		rvb3->er_time_ms = delay_time_table_xg[clip_int(st->param_lsb[2], 0x00, 0x3F)];
		rvb3->width = reverb_width_height_table_xg[clip_int(st->param_lsb[5], 0x00, 37)];
		rvb3->height = reverb_width_height_table_xg[clip_int(st->param_lsb[6], 0x00, 73)];
		rvb3->depth = reverb_width_height_table_xg[clip_int(st->param_lsb[7], 0x00, 104)];
		rvb3->rev_damp_bal = (double)clip_int(st->param_lsb[8], 0x00, 30) * DIV_30;
	//	rvb3->rev_wall = reverb_width_height_table_xg[clip_int(st->param_lsb[8], 0x00, 30)];
		rvb3->rev_dly_ms = delay_time_table_xg[clip_int(st->param_lsb[10], 0x00, 0x3F)];
		rvb3->density = (double)clip_int(st->param_lsb[11], 0x00, 0x04) * DIV_4;
		rvb3->er_level = calc_option_level(clip_int(st->param_lsb[12], 0x01, 0x7F));
		rvb3->rev_level = calc_option_level(127 - clip_int(st->param_lsb[12], 0x01, 0x7F));		
		rvb3->rev_damp_freq = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10 * 22000.0;
		rvb3->er_damp_freq = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10 * 22000.0;
		rvb3->rev_feedback = (double)(clip_int(st->param_lsb[14], 0x01, 0x7F) - 0x40) * DIV_127; //0.125;
		rvb3->level = 1.0;	
	}else
#endif
	if(otd.efx_CustomRevType){
		info->rev_type = 1; // reverb ex
		if(st->connection == XG_CONN_SYSTEM_REVERB){
			rvb2->mode = CH_STEREO;
		}else{
			rvb2->mode = CH_MIX_STEREO;
		}		
		switch(st->type_msb) {
		default:
		case 0x10:/* White Room */
			rvb2->rev_damp_type = FILTER_LPF6;
			break;
		case 0x11:/* Tunnel */
			rvb2->rev_damp_type = FILTER_LPF6x2;
			break;
		case 0x12:/* Canyon */
			rvb2->rev_damp_type = FILTER_LPF6;
			break;
		case 0x13:/* Basement */
			rvb2->rev_damp_type = FILTER_LPF6;
			break;
		}
		rvb2->rev_time_sec = reverb_time_table_xg[clip_int(st->param_lsb[0], 0x00, 0x45)];
	//	rvb2->rev_dif = 0.5 * (10 + clip_int(st->param_lsb[1], 0x00, 0x0a)) * DIV_20;		
		rvb2->er_time_ms = delay_time_table_xg[clip_int(st->param_lsb[2], 0x00, 0x3F)];
		rvb2->width = reverb_width_height_table_xg[clip_int(st->param_lsb[5], 0x00, 37)];
		rvb2->height = reverb_width_height_table_xg[clip_int(st->param_lsb[6], 0x00, 73)];
		rvb2->depth = reverb_width_height_table_xg[clip_int(st->param_lsb[7], 0x00, 104)];
		rvb2->rev_damp_bal = (double)clip_int(st->param_lsb[8], 0x00, 30) * DIV_30;
	//	rvb2->rev_wall = reverb_width_height_table_xg[clip_int(st->param_lsb[8], 0x00, 30)];
		rvb2->rev_dly_ms = delay_time_table_xg[clip_int(st->param_lsb[10], 0x00, 0x3F)];
		rvb2->density = (double)clip_int(st->param_lsb[11], 0x00, 0x04) * DIV_4;
		rvb2->er_level = calc_option_level(clip_int(st->param_lsb[12], 0x01, 0x7F));
		rvb2->rev_level = calc_option_level(127 - clip_int(st->param_lsb[12], 0x01, 0x7F));		
		rvb2->rev_damp_freq = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10 * 22000.0;
		rvb2->er_damp_freq = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10 * 22000.0;
		rvb2->rev_feedback = (double)(clip_int(st->param_lsb[14], 0x01, 0x7F) - 0x40) * DIV_127; //0.125;
		rvb2->level = 1.0;	
	}else{
		info->rev_type = 0; // freeverb
		if(st->connection == XG_CONN_SYSTEM_REVERB){
			rvb->mode = CH_STEREO;
		}else{
			rvb->mode = CH_MIX_STEREO;
		}	
		rvb->rev_time_sec = reverb_time_table_xg[clip_int(st->param_lsb[0], 0x00, 0x45)];
		rvb->rev_dif = 0.5 * (10 + clip_int(st->param_lsb[1], 0x00, 0x0a)) * DIV_20;
		rvb->er_time_ms = delay_time_table_xg[clip_int(st->param_lsb[2], 0x00, 0x3F)];
		rvb->rev_dly_ms = delay_time_table_xg[clip_int(st->param_lsb[10], 0x00, 0x3F)];
		rvb->er_level = calc_option_level(clip_int(st->param_lsb[12], 0x01, 0x7F));
		rvb->rev_level = calc_option_level(127 - clip_int(st->param_lsb[12], 0x01, 0x7F));
		rvb->rev_damp = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10; // initialdamp;
		rvb->er_damp_freq = (double)clip_int(st->param_lsb[13], 0x01, 0x0A) * DIV_10 * 22000.0;
		rvb->rev_feedback = (double)(clip_int(st->param_lsb[14], 0x01, 0x7F) - 0x40) * DIV_127; //0.125;
		rvb->rev_rt = ins_xg_revchar_to_rt(st);
		rvb->rev_roomsize = sqrt(
			(double)reverb_width_height_table_xg[clip_int(st->param_lsb[5], 0x00, 37)]
			* reverb_width_height_table_xg[clip_int(st->param_lsb[6], 0x00, 73)]
			* reverb_width_height_table_xg[clip_int(st->param_lsb[7], 0x00, 104)]
			* DIV_1600); // max 6222.408
		rvb->rev_wet = ins_xg_revchar_to_level(st);
		rvb->rev_width = initialwidth;
	}
	info->rev_dry = calc_dry_xg(st->param_lsb[9], st);
	info->rev_wet = calc_wet_xg(st->param_lsb[9], st);
	info->rev_level = 1.0;
}

static void do_xg_reverb2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Reverb2 *info = (Info_XG_Reverb2 *)ef->info;
	InfoFreeverb *rvb = &info->rvb;
	InfoReverbEX *rvb2 = &info->rvb2;
#ifdef REV_EX2
	InfoReverbEX2 *rvb3 = &info->rvb3;
#endif
	InfoPreFilter *bpf = &info->bpf;

	send_efx_buffer(ef, buf, count);
	do_pre_bpf(ef->efx_buf, count, bpf);
#ifdef REV_EX2	
	if(info->rev_type == 2)
		do_reverb_ex2(ef->efx_buf, count, rvb3);
	else 
#endif
	if(info->rev_type)
		do_reverb_ex(ef->efx_buf, count, rvb2);
	else
		do_freeverb(ef->efx_buf, count, rvb);
	return_efx_buffer(ef, buf, count, info->rev_wet, info->rev_dry, info->rev_level);
}

static void conv_xg_karaoke(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Karaoke *info = (Info_XG_Karaoke *)ef->info;
	InfoEcho  *dly = &info->dly;
	InfoPreFilter *bpf = &info->bpf;

	bpf->freqH = eq_freq_table_xg[clip_int(st->param_lsb[3], 0x00, 0x34)];
	bpf->freqL = eq_freq_table_xg[clip_int(st->param_lsb[4], 0x22, 0x3C)];
	init_pre_bpf(bpf);

	dly->ldelay1 = dly->rdelay1 = delay_time_2_table_xg[st->param_lsb[0]];
	dly->ldelay2 = dly->rdelay2 = dly->ldelay1 * 1.5;
	dly->lfeedback = dly->rfeedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = 0.5;	
	dly->delay2_level = 0.25;
	info->dly_level = 1.0;
	info->dly_dry = calc_dry_xg(st->param_lsb[9], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[9], st);
}

static void do_xg_karaoke(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Karaoke *info = (Info_XG_Karaoke *)ef->info;
	InfoEcho  *dly = &info->dly;
	InfoPreFilter *bpf = &info->bpf;

	send_efx_buffer(ef, buf, count);
	do_pre_bpf(ef->efx_buf, count, bpf);
	effect_mix_mono(ef->efx_buf, count);
	do_echo(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_tempo_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_TempoDelay *info = (Info_XG_TempoDelay *)ef->info;
	InfoDelayLR *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;

	dly->mode = CH_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = calc_tempo_xg(clip_int(st->param_lsb[0], 0, 19));
	dly->feedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[2], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[9], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[9], st);
	info->dly_level = 1.0;
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[12], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[13] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[14], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[15] - 64, -12, 12);
}

static void do_xg_tempo_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_TempoDelay *info = (Info_XG_TempoDelay *)ef->info;
	InfoDelayLR *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_tempo_echo(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_TempoEcho *info = (Info_XG_TempoEcho *)ef->info;
	InfoEcho *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;
	
	dly->ldelay1 = dly->ldelay2 = dly->rdelay1 = dly->rdelay2 = calc_tempo_xg(clip_int(st->param_lsb[0], 0, 19));
	dly->lfeedback = dly->rfeedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[2], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->delay2_level = calc_xg_level(st->param_lsb[7], st);
	info->dly_level = 1.0;
	info->dly_dry = calc_dry_xg(st->param_lsb[9], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[9], st);
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[12], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[13] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[14], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[15] - 64, -12, 12);
}

static void do_xg_tempo_echo(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_TempoEcho *info = (Info_XG_TempoEcho *)ef->info;
	InfoEcho *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_echo(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_tempo_cross(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_TempoCross *info = (Info_XG_TempoCross *)ef->info;
	InfoDelayLR *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;

	dly->mode = CH_STEREO;
	dly->ldelay = dly->fdelay1 = calc_tempo_xg(clip_int(st->param_lsb[0], 0, 19));
	dly->rdelay = dly->fdelay2 = calc_tempo_xg(clip_int(st->param_lsb[1], 0, 19));
	dly->feedback = (double)(st->param_lsb[2] - 64) * (0.763 * 2.0 * DIV_100);
	dly->fb_mode = 1; // cross
	dly->phasel = 0;
	dly->phaser = 0;
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[4], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	info->dly_dry = calc_dry_xg(st->param_lsb[9], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[9], st);
	info->dly_level = 1.0;
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[12], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[13] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[14], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[15] - 64, -12, 12);
}

static void do_xg_tempo_cross(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_TempoCross *info = (Info_XG_TempoCross *)ef->info;
	InfoDelayLR *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_chorus(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Chorus *info = (Info_XG_Chorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	InfoEQ3 *eq = &info->eq;
	
	if(st->param_lsb[14] == 1)
		cho->mode = CH_STEREO;
	else
		cho->mode = CH_MIX_MONO;
	cho->phase = 3;
	cho->filter_type = 0; // off
	cho->filter_cutoff = 22000; // 22000Hz
	cho->rate = lfo_freq_table_xg[st->param_lsb[0]];
	cho->depth_cent = calc_chorus_depth_xg(st->param_lsb[1]);
	cho->feedback = (double)(st->param_lsb[2] - 64) * 1.5625 * 0.0081 + 0.10;
	cho->pdelay_ms = mod_delay_offset_table_xg[st->param_lsb[3]];
	cho->phase_diff = 30; // 0~180
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = 1.0;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);		
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[10], 14, 54)];
	if(st->connection == XG_CONN_SYSTEM)
		eq->mid_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	else
		eq->mid_gain = 0;
	eq->mid_width = (double)clip_int(st->param_lsb[12], 10, 120) * DIV_10;
	return;
}

static void conv_xg_chorus_gm(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Chorus *info = (Info_XG_Chorus *)ef->info;
	InfoEQ3 *eq = &info->eq;
	
	conv_xg_chorus(st, ef);	
	if(st->connection <= XG_CONN_SYSTEM)
		eq->mid_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	else
		eq->mid_gain = 0.0;
	return;
}

static void do_xg_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Chorus *info = (Info_XG_Chorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	InfoEQ3 *eq = &info->eq;	

	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, cho);
	do_chorus_ex(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_xg_celeste(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Chorus *info = (Info_XG_Chorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	InfoEQ3 *eq = &info->eq;
	
	if(st->param_lsb[14] == 1)
		cho->mode = CH_STEREO;
	else
		cho->mode = CH_MIX_MONO;
	cho->phase = 3;
	cho->filter_type = 0; // off
	cho->filter_cutoff = 22000; // 22000Hz
	cho->rate = lfo_freq_table_xg[st->param_lsb[0]];
	cho->depth_cent = calc_chorus_depth_xg(st->param_lsb[1]);
	cho->feedback = (double)(st->param_lsb[2] - 64) * 1.5625 * 0.0081 + 0.10;
	cho->pdelay_ms = mod_delay_offset_table_xg[st->param_lsb[3]];
	cho->phase_diff = 120; // 0~180
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = 1.0;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[10], 14, 54)];
	if(st->connection == XG_CONN_SYSTEM)
		eq->mid_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	else
		eq->mid_gain = 0;
	eq->mid_width = (double)clip_int(st->param_lsb[12], 10, 120) * DIV_10;
	return;
}

static void do_xg_celeste(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Chorus *info = (Info_XG_Chorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	InfoEQ3 *eq = &info->eq;	

	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
//	do_chorus_p2(ef->efx_buf, count, cho);
	do_chorus_ex(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_xg_flanger(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Flanger *info = (Info_XG_Flanger *)ef->info;
	InfoStereoChorus *fl = &info->fl;
	InfoEQ3 *eq = &info->eq;

	fl->mode = CH_STEREO;
	fl->phase = 3;
	fl->filter_type = 0; // off
	fl->filter_cutoff = 22000; // 22000Hz
	fl->rate = lfo_freq_table_xg[st->param_lsb[0]];
	fl->depth_cent = calc_chorus_depth_xg(st->param_lsb[1]);
	fl->feedback = (double)(st->param_lsb[2] - 64) * (0.763 * 2.0 * DIV_100);
	fl->pdelay_ms = mod_delay_offset_table_xg[st->param_lsb[3]];
	fl->phase_diff = (double)(clip_int(st->param_lsb[13], 4, 124) - 64) * 3.0;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = 1.0;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[10], 14, 54)];	
	if(st->connection == XG_CONN_SYSTEM)
		eq->mid_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	else
		eq->mid_gain = 0;
	eq->mid_width = (double)clip_int(st->param_lsb[12], 10, 120) * DIV_10;	
}

static void conv_xg_flanger_gm(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Flanger *info = (Info_XG_Flanger *)ef->info;
	InfoStereoChorus *fl = &info->fl;
	InfoEQ3 *eq = &info->eq;

	conv_xg_flanger(st, ef);
	if(st->connection <= XG_CONN_SYSTEM)
		eq->mid_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	else
		eq->mid_gain = 0;
}

static void do_xg_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Flanger *info = (Info_XG_Flanger *)ef->info;
	InfoStereoChorus *fl = &info->fl;
	InfoEQ3 *eq = &info->eq;	

	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, fl);
	do_chorus_ex(ef->efx_buf, count, fl);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_xg_symphonic(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Symphonic *info = (Info_XG_Symphonic *)ef->info;
	InfoStereoChorus *cho1 = &info->cho1,  *cho2 = &info->cho2;
	InfoEQ3 *eq = &info->eq;
		
	// chorus stage1
	cho1->mode = CH_MIX_STEREO; // mix in stereo out
	cho1->phase = 3;
	cho1->filter_type = 0; // off
	cho1->filter_cutoff = 22000; // 22000Hz
	cho1->rate = lfo_freq_table_xg[st->param_lsb[0]];
	cho1->depth_cent = calc_chorus_depth_xg(st->param_lsb[1]);
	cho1->feedback = 0.0;
	cho1->pdelay_ms = mod_delay_offset_table_xg[st->param_lsb[3]];
	cho1->phase_diff = 90; // 0~180
	cho1->pdelay_dev = 20; // 0~20
	cho1->depth_dev = 20; // -20~+20
	cho1->pan_dev = 20; // 0~20
	// chorus stage2
	cho2->mode = CH_STEREO; // stereo in stereo out
	cho2->phase = 3;
	cho2->filter_type = 0; // off
	cho2->filter_cutoff = 22000; // 22000Hz
	cho2->rate = lfo_freq_table_xg[st->param_lsb[0]];
	cho2->depth_cent = calc_chorus_depth_xg(st->param_lsb[1]);
	cho2->feedback = 0.0;
	cho2->pdelay_ms = 5.0; // include stage1
	cho2->phase_diff = 45; // 0~180
	cho2->pdelay_dev = 20; // 0~20
	cho2->depth_dev = 20; // -20~+20
	cho2->pan_dev = 20; // 0~20
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = 1.0;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[10], 14, 54)];
	if(st->connection == XG_CONN_SYSTEM)
		eq->mid_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	else
		eq->mid_gain = 0;
	eq->mid_width = (double)clip_int(st->param_lsb[12], 10, 120) * DIV_10;
}

static void do_xg_symphonic(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Symphonic *info = (Info_XG_Symphonic *)ef->info;
	InfoStereoChorus *cho1 = &info->cho1,  *cho2 = &info->cho2;
	InfoEQ3 *eq = &info->eq;	

	do_eq3_multi(buf, count, eq);	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, cho1);
	do_chorus_ex(ef->efx_buf, count, cho2);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_xg_rotary_speaker(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_RotarySpeaker *info = (Info_XG_RotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoEQ3 *eq = &info->eq;

	rt->mode = CH_MIX_STEREO;
	rt->low_fast = rt->low_slow = lfo_freq_table_xg[st->param_lsb[0]];
	rt->low_fast = lfo_freq_table_xg[st->param_lsb[0]];
	rt->low_accl = 1.0;
	rt->low_level = 1.0;
	rt->hi_fast = rt->hi_slow = rt->low_fast * 1.1;
	rt->hi_accl = 1.0;
	rt->hi_level = 1.0;
	rt->separate = 0.5;
	rt->speed = 0;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[10], 14, 54)];
	if(st->connection == XG_CONN_SYSTEM)
		eq->mid_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	else
		eq->mid_gain = 0;
	eq->mid_width = (double)clip_int(st->param_lsb[12], 10, 120) * DIV_10;
}

static void do_xg_rotary_speaker(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_RotarySpeaker *info = (Info_XG_RotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoEQ3 *eq = &info->eq;

	do_eq3_multi(buf, count, eq);
	do_rotary_multi(buf, count, rt);
}

static void conv_xg_ds_rotary_speaker(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_DS_RotarySpeaker *info = (Info_XG_DS_RotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;

	rt->mode = CH_MIX_STEREO;
	rt->low_fast = rt->low_slow = lfo_freq_table_xg[st->param_lsb[0]];
	rt->low_fast = lfo_freq_table_xg[st->param_lsb[0]];
	rt->low_accl = 1.0;
	rt->low_level = 1.0;
	rt->hi_fast = rt->hi_slow = rt->low_fast * 1.1;
	rt->hi_accl = 1.0;
	rt->hi_level = 1.0;
	rt->separate = (double)st->param_lsb[1] * DIV_127;
	rt->speed = 0;
	od->mode = CH_STEREO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[13] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[14], 34, 60)];
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
}

static void do_xg_ds_rotary_speaker(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_DS_RotarySpeaker *info = (Info_XG_DS_RotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	do_stereo_od(buf, count, od);
	do_rotary_multi(buf, count, rt);
}

static void conv_xg_od_rotary_speaker(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_OD_RotarySpeaker *info = (Info_XG_OD_RotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;

	rt->mode = CH_MIX_STEREO;
	rt->low_fast = rt->low_slow = lfo_freq_table_xg[st->param_lsb[0]];
	rt->low_fast = lfo_freq_table_xg[st->param_lsb[0]];
	rt->low_accl = 1.0;
	rt->low_level = 1.0;
	rt->hi_fast = rt->hi_slow = rt->low_fast * 1.1;
	rt->hi_accl = 1.0;
	rt->hi_level = 1.0;
	rt->separate = (double)st->param_lsb[1] * DIV_127;
	rt->speed = 0;
	od->mode = CH_STEREO;
	od->od_type = 0;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[13] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[14], 34, 60)];
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
}

static void do_xg_od_rotary_speaker(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_OD_RotarySpeaker *info = (Info_XG_OD_RotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;	

	do_eq2_multi(buf, count, eq);
	do_stereo_od(buf, count, od);
	do_rotary_multi(buf, count, rt);
}

static void conv_xg_amp_rotary_speaker(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_AMP_RotarySpeaker *info = (Info_XG_AMP_RotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;

	rt->mode = CH_MIX_STEREO;
	rt->low_fast = rt->low_slow = lfo_freq_table_xg[st->param_lsb[0]];
	rt->low_fast = lfo_freq_table_xg[st->param_lsb[0]];
	rt->low_accl = 1.0;
	rt->low_level = 1.0;
	rt->hi_fast = rt->hi_slow = rt->low_fast * 1.1;
	rt->hi_accl = 1.0;
	rt->hi_level = 1.0;
	rt->separate = (double)st->param_lsb[1] * DIV_127;
	rt->speed = 0;
	od->mode = CH_STEREO;
	od->od_type = 0;
	od->amp_type = clip_int(st->param_lsb[1], 0, 6);
	od->cab_type = cab_type_xg[clip_int(st->param_lsb[1], 0, 6)];
	od->drive = (double)st->param_lsb[13] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[14], 34, 60)];
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
}

static void do_xg_amp_rotary_speaker(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_AMP_RotarySpeaker *info = (Info_XG_AMP_RotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	do_stereo_od(buf, count, od);
	do_rotary_multi(buf, count, rt);
}

static void conv_xg_tremolo(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Tremolo *info = (Info_XG_Tremolo *)ef->info;
	InfoTremolo *trm = &info->trm;
	InfoEQ3 *eq = &info->eq;

	trm->mode = CH_STEREO;
	trm->type = 1;
	trm->phase = (double)(clip_int(st->param_lsb[13], 4, 124) - 64) * 3.0; // deg
	trm->wave = LFO_TRIANGULAR;
	trm->rate = lfo_freq_table_xg[st->param_lsb[0]];
	trm->depth = (double)st->param_lsb[1] * DIV_127;
	trm->pm_mode = 1;
	trm->depth_cent = calc_chorus_depth_xg(st->param_lsb[2]);
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[10], 14, 54)];	
	if(st->connection == XG_CONN_SYSTEM)
		eq->mid_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	else
		eq->mid_gain = 0;
	eq->mid_width = (double)clip_int(st->param_lsb[12], 10, 120) * DIV_10;
}

static void do_xg_tremolo(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Tremolo *info = (Info_XG_Tremolo *)ef->info;
	InfoTremolo *trm = &info->trm;
	InfoEQ3 *eq = &info->eq;

	do_eq3_multi(buf, count, eq);
	do_tremolo_autopan(buf, count, trm);
}

static void conv_xg_auto_pan(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_AutoPan *info = (Info_XG_AutoPan *)ef->info;
	InfoTremolo *ap = &info->ap;
	InfoEQ3 *eq = &info->eq;

	ap->mode = CH_STEREO;
	ap->type = 1;
	ap->phase = 180; // deg
	ap->wave = LFO_TRIANGULAR;
	ap->rate = lfo_freq_table_xg[st->param_lsb[0]];
	ap->depth = (double)st->param_lsb[1] * DIV_127;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[10], 14, 54)];
	if(st->connection == XG_CONN_SYSTEM)
		eq->mid_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	else
		eq->mid_gain = 0;
	eq->mid_width = (double)clip_int(st->param_lsb[12], 10, 120) * DIV_10;
}

static void do_xg_auto_pan(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_AutoPan *info = (Info_XG_AutoPan *)ef->info;
	InfoTremolo *ap = &info->ap;
	InfoEQ3 *eq = &info->eq;

	do_eq3_multi(buf, count, eq);
	do_tremolo_autopan(buf, count, ap);
}

static void conv_xg_phaser1(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Phaser1 *info = (Info_XG_Phaser1 *)ef->info;
	InfoPhaser *ph = &info->ph;
	InfoEQ2 *eq = &info->eq;

	ph->mode = CH_MIX_MONO;
	if(st->connection == XG_CONN_SYSTEM)
		ph->phase = clip_int(st->param_lsb[10], 4, 12); // stage?
	else
		ph->phase = clip_int(st->param_lsb[10], 4, 6); // stage?
	ph->manual = (double)manual_table[64];
	ph->rate = lfo_freq_table_xg[st->param_lsb[0]];
	ph->depth_cent = calc_chorus_depth_xg(st->param_lsb[1]);
	ph->offset = (double)(st->param_lsb[2] - 64) * DIV_64;
	ph->feedback = (double)(st->param_lsb[3] - 64) * DIV_64;	
	ph->reso = 6.0; // 6dB
	ph->phase_diff = 180 + clip_int(st->param_lsb[12] - 64, -60, 60) * 3; // def 0~+360
	info->ph_dry = calc_dry_xg(st->param_lsb[9], st);
	info->ph_wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = 1.0;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
}

static void do_xg_phaser1(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Phaser1 *info = (Info_XG_Phaser1 *)ef->info;
	InfoPhaser *ph = &info->ph;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_phaser_multi(ef->efx_buf, count, ph);
	return_efx_buffer(ef, buf, count, info->ph_wet, info->ph_dry, info->level);
}

static void conv_xg_phaser2(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Phaser2 *info = (Info_XG_Phaser2 *)ef->info;
	InfoPhaser *ph = &info->ph;
	InfoEQ2 *eq = &info->eq;

	ph->mode = CH_STEREO;
	ph->phase = clip_int(st->param_lsb[10], 3, 6); // stage?
	ph->manual = (double)manual_table[64];
	ph->rate = lfo_freq_table_xg[st->param_lsb[0]];
	ph->depth_cent = calc_chorus_depth_xg(st->param_lsb[1]);
	ph->offset = (double)(st->param_lsb[2] - 64) * DIV_64;
	ph->feedback = (double)(st->param_lsb[3] - 64) * DIV_64;	
	ph->reso = 6.0; // 6dB
	ph->phase_diff = 180 + clip_int(st->param_lsb[12] - 64, -60, 60) * 3; // def 0~+360
	info->ph_dry = calc_dry_xg(st->param_lsb[9], st);
	info->ph_wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = 1.0;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
}

static void do_xg_phaser2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Phaser2 *info = (Info_XG_Phaser2 *)ef->info;
	InfoPhaser *ph = &info->ph;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_phaser_multi(ef->efx_buf, count, ph);
	return_efx_buffer(ef, buf, count, info->ph_wet, info->ph_dry, info->level);
}

static void conv_xg_distortion(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Distortion *info = (Info_XG_Distortion *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;

	od->mode = CH_MIX_MONO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[0] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[3], 34, 60)];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[1], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[2] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[6], 14, 54)];
	eq->mid_gain = clip_int(st->param_lsb[7] - 64, -12, 12);
	eq->mid_width = (double)clip_int(st->param_lsb[8], 10, 120) * DIV_10;
	eq->high_freq = 0;
	eq->high_gain = 0;
}

static void do_xg_distortion(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Distortion *info = (Info_XG_Distortion *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;

	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
}

static void conv_xg_comp_distortion(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Comp_Distortion *info = (Info_XG_Comp_Distortion *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoCompressor *cmp1 = &info->cmp1, *cmp2 = &info->cmp2;
	
	od->mode = CH_MONO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[0] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[3], 34, 60)];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[1], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[2] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[6], 14, 54)];
	eq->mid_gain = clip_int(st->param_lsb[7] - 64, -12, 12);
	eq->mid_width = (double)clip_int(st->param_lsb[8], 10, 120) * DIV_10;
	eq->high_freq = 0;
	eq->high_gain = 0;
	cmp1->mode = cmp2->mode = CH_MONO;
	cmp1->attak = cmp2->attak = compressor_attack_time_table_xg[clip_int(st->param_lsb[11], 0, 19)]; // 10ms-500ms
	cmp1->sustain = cmp2->sustain = compressor_release_time_table_xg[clip_int(st->param_lsb[12], 0, 15)]; // 10ms-500ms
	cmp1->pre_gain = cmp2->pre_gain = (double)(127 - clip_int(st->param_lsb[13], 79, 121)); // dB
	cmp1->post_gain = cmp2->post_gain = 0.0; // dB
	cmp1->threshold = cmp2->threshold = 1.0; // threshold(~1.0)
	cmp1->slope = cmp2->slope = 1.0 / compressor_ratio_table_xg[clip_int(st->param_lsb[14], 0, 7)]; // ratio?
	cmp1->div_level_0db = cmp2->div_level_0db = div_ins_level * DIV_2;
}

static void do_xg_comp_distortion(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Comp_Distortion *info = (Info_XG_Comp_Distortion *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoCompressor *cmp1 = &info->cmp1, *cmp2 = &info->cmp2;
	
	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	effect_mix_mono(ef->efx_buf, count);
	do_compressor_multi(ef->efx_buf, count, cmp1);
	do_stereo_od(ef->efx_buf, count, od);
	do_compressor_multi(ef->efx_buf, count, cmp2);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
}

static void conv_xg_st_distortion(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_StDistortion *info = (Info_XG_StDistortion *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;

	od->mode = CH_STEREO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[0] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[3], 34, 60)];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);	
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[1], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[2] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[6], 14, 54)];
	eq->mid_gain = clip_int(st->param_lsb[7] - 64, -12, 12);
	eq->mid_width = (double)clip_int(st->param_lsb[8], 10, 120) * DIV_10;
	eq->high_freq = 0;
	eq->high_gain = 0;
}

static void do_xg_st_distortion(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_StDistortion *info = (Info_XG_StDistortion *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;

	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
}

static void conv_xg_overdrive(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Overdrive *info = (Info_XG_Overdrive *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;

	od->mode = CH_MIX_MONO;
	od->od_type = 0;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[0] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[3], 34, 60)];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[1], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[2] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[6], 14, 54)];
	eq->mid_gain = clip_int(st->param_lsb[7] - 64, -12, 12);
	eq->mid_width = (double)clip_int(st->param_lsb[8], 10, 120) * DIV_10;
	eq->high_freq = 0;
	eq->high_gain = 0;
}

static void do_xg_overdrive(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_StOverdrive *info = (Info_XG_StOverdrive *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;

	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
}

static void conv_xg_st_overdrive(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_StOverdrive *info = (Info_XG_StOverdrive *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;

	od->mode = CH_STEREO;
	od->od_type = 0;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[0] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[3], 34, 60)];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);	
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[1], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[2] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[6], 14, 54)];
	eq->mid_gain = clip_int(st->param_lsb[7] - 64, -12, 12);
	eq->mid_width = (double)clip_int(st->param_lsb[8], 10, 120) * DIV_10;
	eq->high_freq = 0;
	eq->high_gain = 0;
}

static void do_xg_st_overdrive(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Overdrive *info = (Info_XG_Overdrive *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;

	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
}

static void conv_xg_amp_simulator(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_AmpSimulator *info = (Info_XG_AmpSimulator *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;

	od->mode = CH_MIX_MONO;
	od->od_type = 1;
	od->amp_type = clip_int(st->param_lsb[1], 0, 6);
	od->cab_type = cab_type_xg[clip_int(st->param_lsb[1], 0, 6)];
	od->drive = (double)st->param_lsb[0] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[2], 34, 60)];
	info->od_level = calc_xg_level(st->param_lsb[3], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);	
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(20, 4, 40)];
	eq->low_gain = clip_int(72 - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(43, 14, 54)];
	eq->mid_gain = clip_int(74 - 64, -12, 12);
	eq->mid_width = (double)clip_int(10, 10, 120) * DIV_10;
	eq->high_freq = 6000;
	eq->high_gain = 8;
}

static void do_xg_amp_simulator(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_AmpSimulator *info = (Info_XG_AmpSimulator *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	
//	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
}

static void conv_xg_st_amp_simulator(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_StAmpSimulator *info = (Info_XG_StAmpSimulator *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;

	od->mode = CH_STEREO;
	od->od_type = 1;
	od->amp_type = clip_int(st->param_lsb[1], 0, 6);
	od->cab_type = cab_type_xg[clip_int(st->param_lsb[1], 0, 6)];
	od->drive = (double)st->param_lsb[0] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[2], 34, 60)];
	info->od_level = calc_xg_level(st->param_lsb[3], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(20, 4, 40)];
	eq->low_gain = clip_int(72 - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(43, 14, 54)];
	eq->mid_gain = clip_int(74 - 64, -12, 12);
	eq->mid_width = (double)clip_int(10, 10, 120) * DIV_10;
	eq->high_freq = 6000;
	eq->high_gain = 8;
}

static void do_xg_st_amp_simulator(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_StAmpSimulator *info = (Info_XG_StAmpSimulator *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
		
//	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
}

static void conv_xg_eq3(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_EQ3 *info = (Info_XG_EQ3 *)ef->info;
	InfoEQ3 *eq = &info->eq;

	eq->mode = st->param_lsb[14] ? CH_STEREO : CH_MONO;
	eq->low_gain = clip_int(st->param_lsb[0] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[1], 14, 54)];
	eq->mid_gain = clip_int(st->param_lsb[2] - 64, -12, 12);
	eq->mid_width = (double)clip_int(st->param_lsb[3], 10, 120) * DIV_10;
	eq->high_gain = clip_int(st->param_lsb[4] - 64, -12, 12);
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[6], 28, 58)];
}

static void do_xg_eq3(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_EQ3 *info = (Info_XG_EQ3 *)ef->info;
	InfoEQ3 *eq = &info->eq;

	do_eq3_multi(buf, count, eq);
}

static void conv_xg_eq2(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_EQ2 *info = (Info_XG_EQ2 *)ef->info;
	InfoEQ2 *eq = &info->eq;

	eq->mode = st->param_lsb[14] ? CH_STEREO : CH_MONO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[0], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[1] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[2], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[3] - 64, -12, 12);
}

static void do_xg_eq2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_EQ2 *info = (Info_XG_EQ2 *)ef->info;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
}

static void conv_xg_auto_wah(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_AutoWah *info = (Info_XG_AutoWah *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;	
	
	aw->mode = CH_STEREO;
	aw->type = 1;
	aw->rate = lfo_freq_table_xg[st->param_lsb[0]];
	aw->depth = (double)st->param_lsb[1] * DIV_127;
	aw->manual = calc_auto_wah_manual_xg(st->param_lsb[2]);
	aw->peak = calc_auto_wah_peak_xg(st->param_lsb[3]);
	aw->pol = 1;
	aw->lfo_sw = 1; // on
	aw->sens_sw = 0; // off
	aw->sens = 0.0;
	aw->release = 100.0; // ms
	//aw->mode = CH_STEREO;
	//aw->lfo_freq = lfo_freq_table_xg[st->param_lsb[0]];
	//aw->lfo_depth = st->param_lsb[1];
	//aw->offset_freq = (double)(st->param_lsb[2]) * 3900.0 * DIV_127 + 100.0;
	//aw->resonance = (double)clip_int(st->param_lsb[3], 10, 120) * DIV_10;
	//aw->drive = (double)st->param_lsb[10] * DIV_127;	
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	od->mode = CH_MIX_MONO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[10] * DIV_127;
	od->cutoff = eq_freq_table_xg[50];
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
}

static void do_xg_auto_wah(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_AutoWah *info = (Info_XG_AutoWah *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count); 
	do_auto_wah_multi(ef->efx_buf, count, aw);
	do_stereo_od(ef->efx_buf, count, od);	
	return_efx_buffer(ef, buf, count, info->wet, info->dry, 1.0); //
}

static void conv_xg_auto_wah_ds(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_AutoWah_DS *info = (Info_XG_AutoWah_DS *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoEQ2 *eq = &info->eq;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq3 = &info->eq3;
	
	aw->mode = CH_STEREO;
	aw->type = 1;
	aw->rate = lfo_freq_table_xg[st->param_lsb[0]];
	aw->depth = (double)st->param_lsb[1] * DIV_127;
	aw->manual = calc_auto_wah_manual_xg(st->param_lsb[2]);
	aw->peak = calc_auto_wah_peak_xg(st->param_lsb[3]);
	aw->pol = 1;
	aw->lfo_sw = 1; // on
	aw->sens_sw = 0; // off
	aw->sens = 0.0;
	aw->release = 100.0; // ms
	//aw->mode = CH_MIX_MONO;
	//aw->lfo_freq = lfo_freq_table_xg[st->param_lsb[0]];
	//aw->lfo_depth = st->param_lsb[1];
	//aw->offset_freq = (double)(st->param_lsb[2]) * 3900.0 * DIV_127 + 100.0;
	//aw->resonance = (double)clip_int(st->param_lsb[3], 10, 120) * DIV_10;
	//aw->drive = (double)st->param_lsb[10] * DIV_127;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	od->mode = CH_MIX_MONO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[10] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[13], 34, 60)];
	eq3->mode = CH_STEREO;
	eq3->low_freq = eq_freq_table_xg[24];
	eq3->low_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	eq3->mid_freq = eq_freq_table_xg[41];
	eq3->mid_gain = clip_int(st->param_lsb[12] - 64, -12, 12);
	eq3->mid_width = 1.0;
	eq3->high_freq = 0;
	eq3->high_gain = 0;
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = calc_xg_level(st->param_lsb[14], st);
}

static void do_xg_auto_wah_ds(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_AutoWah_DS *info = (Info_XG_AutoWah_DS *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoEQ2 *eq = &info->eq;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq3 = &info->eq3;

	send_efx_buffer(ef, buf, count); 
	do_eq2_multi(ef->efx_buf, count, eq);
	do_auto_wah_multi(ef->efx_buf, count, aw);
	do_eq3_multi(ef->efx_buf, count, eq3);
	do_stereo_od(ef->efx_buf, count, od);	
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level); 
}

static void conv_xg_auto_wah_od(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_AutoWah_OD *info = (Info_XG_AutoWah_OD *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoEQ2 *eq = &info->eq;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq3 = &info->eq3;
	
	aw->mode = CH_STEREO;
	aw->type = 1;
	aw->rate = lfo_freq_table_xg[st->param_lsb[0]];
	aw->depth = (double)st->param_lsb[1] * DIV_127;
	aw->manual = calc_auto_wah_manual_xg(st->param_lsb[2]);
	aw->peak = calc_auto_wah_peak_xg(st->param_lsb[3]);
	aw->pol = 1;
	aw->lfo_sw = 1; // on
	aw->sens_sw = 0; // off
	aw->sens = 0.0;
	aw->release = 100.0; // ms
	//aw->mode = CH_MIX_MONO;
	//aw->lfo_freq = lfo_freq_table_xg[st->param_lsb[0]];
	//aw->lfo_depth = st->param_lsb[1];
	//aw->offset_freq = (double)(st->param_lsb[2]) * 3900.0 * DIV_127 + 100.0;
	//aw->resonance = (double)clip_int(st->param_lsb[3], 10, 120) * DIV_10;
	//aw->drive = (double)st->param_lsb[10] * DIV_127;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);	
	od->mode = CH_MIX_MONO;
	od->od_type = 0;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[10] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[13], 34, 60)];
	eq3->mode = CH_STEREO;
	eq3->low_freq = eq_freq_table_xg[24];
	eq3->low_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	eq3->mid_freq = eq_freq_table_xg[41];
	eq3->mid_gain = clip_int(st->param_lsb[12] - 64, -12, 12);
	eq3->mid_width = 1.0;
	eq3->high_freq = 0;
	eq3->high_gain = 0;
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = calc_xg_level(st->param_lsb[14], st);
}

static void do_xg_auto_wah_od(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_AutoWah_OD *info = (Info_XG_AutoWah_OD *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoEQ2 *eq = &info->eq;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq3 = &info->eq3;

	send_efx_buffer(ef, buf, count); 
	do_eq2_multi(ef->efx_buf, count, eq);
	do_auto_wah_multi(ef->efx_buf, count, aw);
	do_eq3_multi(ef->efx_buf, count, eq3);
	do_stereo_od(ef->efx_buf, count, od);	
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level); 
}

static void conv_xg_pitch_change1(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_PitchChange1 *info = (Info_XG_PitchChange1 *)ef->info;
	InfoPitchShifter_core *psl = &info->ps.psl;
	InfoPitchShifter_core *psr = &info->ps.psr;
	Info_P_Mix *pmix = &info->pmix;

	info->ps.mode = CH_MIX_STEREO;
	psl->pitch_cent = (double)(clip_int(st->param_lsb[0], 40, 88) - 0x40) * 100 + (double)(clip_int(st->param_lsb[2], 14, 114) - 0x40);
	psl->feedback = (double)(clip_int(st->param_lsb[4], 1, 127) - 0x40) * DIV_64;
	psl->pre_delay_ms = (double)delay_time_2_table_xg[st->param_lsb[1]];
	psl->ps_delay_ms = PS_CF_DELAY + 8;
	psr->pitch_cent = (double)(clip_int(st->param_lsb[0], 40, 88) - 0x40) * 100 + (double)(clip_int(st->param_lsb[3], 14, 114) - 0x40);
	psr->feedback = (double)(clip_int(st->param_lsb[4], 1, 127) - 0x40) * DIV_64;
	psr->pre_delay_ms = (double)delay_time_2_table_xg[st->param_lsb[1]];
	psr->ps_delay_ms = PS_CF_DELAY + 8;
	info->wet = calc_wet_gs(st->param_lsb[9]);
	info->dry = calc_dry_gs(st->param_lsb[9]);
	pmix->panll = calc_pan_xg_left(st->param_lsb[10]);
	pmix->panlr = calc_pan_xg_right(st->param_lsb[10]);
	pmix->levell = calc_xg_level(st->param_lsb[11], st);
	pmix->panrl = calc_pan_xg_left(st->param_lsb[12]);
	pmix->panrr = calc_pan_xg_right(st->param_lsb[12]);
	pmix->levelr = calc_xg_level(st->param_lsb[13], st);
	pmix->level = 1.0;
}

static void do_xg_pitch_change1(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_PitchChange1 *info = (Info_XG_PitchChange1 *)ef->info;
	InfoPitchShifter *ps = &info->ps;
	Info_P_Mix *pmix = &info->pmix;
	
	send_efx_buffer(ef, buf, count);
	do_pitch_shifter_multi(ef->efx_buf, count, ps);
	mix_parallel_effect(ef->efx_buf, count, pmix);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, 1.0);
}

static void conv_xg_pitch_change2(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_PitchChange2 *info = (Info_XG_PitchChange2 *)ef->info;
	InfoPitchShifter_core *psl = &info->ps.psl;
	InfoPitchShifter_core *psr = &info->ps.psr;
	Info_P_Mix *pmix = &info->pmix;

	info->ps.mode = CH_MIX_STEREO;
	psl->pitch_cent = (double)(clip_int(st->param_lsb[0], 40, 88) - 0x40) * 100 + (double)(clip_int(st->param_lsb[2], 14, 114) - 0x40);
	psl->feedback = (double)(clip_int(st->param_lsb[4], 1, 127) - 0x40) * DIV_64;
	psl->pre_delay_ms = (double)delay_time_2_table_xg[st->param_lsb[1]];
	psl->ps_delay_ms = PS_CF_DELAY + 8;
	psr->pitch_cent = (double)(clip_int(st->param_lsb[0], 40, 88) - 0x40) * 100 + (double)(clip_int(st->param_lsb[3], 14, 114) - 0x40);
	psr->feedback = (double)(clip_int(st->param_lsb[4], 1, 127) - 0x40) * DIV_64;
	psr->pre_delay_ms = (double)delay_time_2_table_xg[st->param_lsb[1]];
	psr->ps_delay_ms = PS_CF_DELAY + 8;
	info->wet = calc_wet_gs(st->param_lsb[9]);
	info->dry = calc_dry_gs(st->param_lsb[9]);
	pmix->panll = calc_pan_xg_left(st->param_lsb[10]);
	pmix->panlr = calc_pan_xg_right(st->param_lsb[10]);
	pmix->levell = calc_xg_level(st->param_lsb[11], st);
	pmix->panrl = calc_pan_xg_left(st->param_lsb[12]);
	pmix->panrr = calc_pan_xg_right(st->param_lsb[12]);
	pmix->levelr = calc_xg_level(st->param_lsb[13], st);
	pmix->level = 1.0;
}

static void do_xg_pitch_change2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_PitchChange2 *info = (Info_XG_PitchChange2 *)ef->info;
	InfoPitchShifter *ps = &info->ps;
	Info_P_Mix *pmix = &info->pmix;
	
	send_efx_buffer(ef, buf, count);
	do_pitch_shifter_multi(ef->efx_buf, count, ps);
	mix_parallel_effect(ef->efx_buf, count, pmix);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, 1.0);
}

static void conv_xg_harmonic_enhancer(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_HarmonicEnhancer *info = (Info_XG_HarmonicEnhancer *)ef->info;
	InfoEnhancer *eh = &info->eh;

	eh->mode = CH_STEREO;
	eh->hpf_cutoff = eq_freq_table_xg[st->param_lsb[0]];
	eh->sens = (double)st->param_lsb[1] * DIV_127;	
	info->wet = (double)st->param_lsb[2] * DIV_127;
	info->dry = 1.0;
}

static void do_xg_harmonic_enhancer(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_HarmonicEnhancer *info = (Info_XG_HarmonicEnhancer *)ef->info;
	InfoEnhancer *eh = &info->eh;

	send_efx_buffer(ef, buf, count);
	do_enhancer_multi(ef->efx_buf, count, eh);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, 1.0);
}

static void conv_xg_touch_wah1(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_TouchWah1 *info = (Info_XG_TouchWah1 *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;	
	
	aw->mode = CH_STEREO;
	aw->type = 1;
	aw->sens = calc_auto_wah_sens_xg(st->param_lsb[0]);
	aw->depth = 1.0;
	aw->manual = calc_auto_wah_manual_xg(st->param_lsb[1]);
	aw->peak = calc_auto_wah_peak_xg(st->param_lsb[2]);
	aw->release = 100.0; // ms
	aw->pol = 1;
	aw->sens_sw = 1; // on
	aw->lfo_sw = 0; // off
	aw->rate = 0.0;	
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	od->mode = CH_MIX_MONO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[10] * DIV_127;
	od->cutoff = eq_freq_table_xg[50];
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
}

static void do_xg_touch_wah1(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_TouchWah1 *info = (Info_XG_TouchWah1 *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count); 
	do_auto_wah_multi(ef->efx_buf, count, aw);
	do_stereo_od(ef->efx_buf, count, od);	
	return_efx_buffer(ef, buf, count, info->wet, info->dry, 1.0); //
}

static void conv_xg_touch_wah_ds(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_TouchWah_DS *info = (Info_XG_TouchWah_DS *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoEQ2 *eq = &info->eq;
	InfoStereoOD *od = &info->od;
	
	aw->mode = CH_STEREO;
	aw->type = 1;
	aw->sens = calc_auto_wah_sens_xg(st->param_lsb[0]);
	aw->depth = 1.0;
	aw->manual = calc_auto_wah_manual_xg(st->param_lsb[1]);
	aw->peak = calc_auto_wah_peak_xg(st->param_lsb[2]);
	aw->release = 100.0; // ms
	aw->pol = 1;
	aw->sens_sw = 1; // on
	aw->lfo_sw = 0; // off
	aw->rate = 0.0;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	od->mode = CH_MIX_MONO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[10] * DIV_127;
	od->cutoff = eq_freq_table_xg[50];
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
}

static void do_xg_touch_wah_ds(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_TouchWah_DS *info = (Info_XG_TouchWah_DS *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoEQ2 *eq = &info->eq;
	InfoStereoOD *od = &info->od;

	send_efx_buffer(ef, buf, count); 
	do_eq2_multi(ef->efx_buf, count, eq);
	do_auto_wah_multi(ef->efx_buf, count, aw);
	do_stereo_od(ef->efx_buf, count, od);	
	return_efx_buffer(ef, buf, count, info->wet, info->dry, 1.0); //
}

static void conv_xg_touch_wah_od(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_TouchWah_OD *info = (Info_XG_TouchWah_OD *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoEQ2 *eq = &info->eq;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq3 = &info->eq3;
	
	aw->mode = CH_STEREO;
	aw->type = 1;
	aw->sens = calc_auto_wah_sens_xg(st->param_lsb[0]);
	aw->depth = 1.0;
	aw->manual = calc_auto_wah_manual_xg(st->param_lsb[1]);
	aw->peak = calc_auto_wah_peak_xg(st->param_lsb[2]);
	aw->release = wah_release_time_table_xg[clip_int(st->param_lsb[15], 52, 67)]; // ms
	aw->pol = 1;
	aw->sens_sw = 1; // on
	aw->lfo_sw = 0; // off
	aw->rate = 0.0;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);	
	od->mode = CH_MIX_MONO;
	od->od_type = 0;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[10] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[13], 34, 60)];
	eq3->mode = CH_STEREO;
	eq3->low_freq = eq_freq_table_xg[24];
	eq3->low_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	eq3->mid_freq = eq_freq_table_xg[41];
	eq3->mid_gain = clip_int(st->param_lsb[12] - 64, -12, 12);
	eq3->mid_width = 1.0;
	eq3->high_freq = 0;
	eq3->high_gain = 0;
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = calc_xg_level(st->param_lsb[14], st);
}

static void do_xg_touch_wah_od(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_TouchWah_OD *info = (Info_XG_TouchWah_OD *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoEQ2 *eq = &info->eq;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq3 = &info->eq3;

	send_efx_buffer(ef, buf, count); 
	do_eq2_multi(ef->efx_buf, count, eq);
	do_auto_wah_multi(ef->efx_buf, count, aw);
	do_eq3_multi(ef->efx_buf, count, eq3);
	do_stereo_od(ef->efx_buf, count, od);	
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level); 
}

static void conv_xg_touch_wah2(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_TouchWah2 *info = (Info_XG_TouchWah2 *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoEQ2 *eq = &info->eq;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq3 = &info->eq3;
	
	aw->mode = CH_STEREO;
	aw->type = 1;
	aw->sens = calc_auto_wah_sens_xg(st->param_lsb[0]);
	aw->depth = 1.0;
	aw->manual = calc_auto_wah_manual_xg(st->param_lsb[1]);
	aw->peak = calc_auto_wah_peak_xg(st->param_lsb[2]);
	aw->release = wah_release_time_table_xg[clip_int(st->param_lsb[15], 52, 67)]; // ms
	aw->pol = 1;
	aw->sens_sw = 1; // on
	aw->lfo_sw = 0; // off
	aw->rate = 0.0;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);	
	od->mode = CH_MIX_MONO;
	od->od_type = 0;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[10] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[13], 34, 60)];
	eq3->mode = CH_STEREO;
	eq3->low_freq = eq_freq_table_xg[24];
	eq3->low_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	eq3->mid_freq = eq_freq_table_xg[41];
	eq3->mid_gain = clip_int(st->param_lsb[12] - 64, -12, 12);
	eq3->mid_width = 1.0;
	eq3->high_freq = 0;
	eq3->high_gain = 0;
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = calc_xg_level(st->param_lsb[14], st);
}

static void do_xg_touch_wah2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_TouchWah2 *info = (Info_XG_TouchWah2 *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoEQ2 *eq = &info->eq;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq3 = &info->eq3;

	send_efx_buffer(ef, buf, count); 
	do_eq2_multi(ef->efx_buf, count, eq);
	do_auto_wah_multi(ef->efx_buf, count, aw);
	do_eq3_multi(ef->efx_buf, count, eq3);
	do_stereo_od(ef->efx_buf, count, od);	
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level); 
}

static void conv_xg_compressor(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Compressor *info = (Info_XG_Compressor *)ef->info;
	InfoCompressor *cmp = &info->cmp;

	cmp->mode = CH_STEREO;
	cmp->attak = compressor_attack_time_table_xg[clip_int(st->param_lsb[0], 0, 19)]; // 10ms-500ms
	cmp->sustain = compressor_release_time_table_xg[clip_int(st->param_lsb[1], 0, 15)]; // 10ms-500ms
	cmp->pre_gain = (double)(127 - clip_int(st->param_lsb[2], 79, 121)); // dB
	cmp->post_gain = 0.0; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 1.0 / compressor_ratio_table_xg[clip_int(st->param_lsb[3], 0, 7)]; // ratio?
	cmp->div_level_0db = div_ins_level * DIV_2;
	info->level = calc_xg_level(st->param_lsb[4], st);
}

static void do_xg_compressor(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Compressor *info = (Info_XG_Compressor *)ef->info;
	InfoCompressor *cmp = &info->cmp;

	do_compressor_multi(buf, count, cmp);
	effect_level_stereo(buf, count, info->level);
}

static void conv_xg_noise_gate(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_NoiseGate *info = (Info_XG_NoiseGate *)ef->info;
	InfoNoiseGate *ng = &info->ng;

	ng->mode = CH_STEREO;
	ng->attack_ms = compressor_attack_time_table_xg[clip_int(st->param_lsb[0], 0, 19)]; // 10ms-500ms
	ng->release_ms = compressor_release_time_table_xg[clip_int(st->param_lsb[1], 0, 15)]; // 10ms-500ms
	ng->threshold = 127 - clip_int(st->param_lsb[2], 55, 97); // dB
	info->level = calc_xg_level(st->param_lsb[3], st);
}

static void do_xg_noise_gate(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_NoiseGate *info = (Info_XG_NoiseGate *)ef->info;
	InfoNoiseGate *ng = &info->ng;

	do_noise_gate(buf, count, ng);
	effect_level_stereo(buf, count, info->level);
}

static void conv_xg_2way_rotary_speaker(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_2WayRotarySpeaker *info = (Info_XG_2WayRotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoEQ3 *eq = &info->eq;

	rt->mode = CH_MIX_STEREO;
	rt->low_fast = rt->low_slow = lfo_freq_table_xg[st->param_lsb[0]];
	rt->low_accl = 1.0;
	rt->low_level = 1.0;
	rt->hi_fast = rt->hi_slow = rt->low_fast * 1.1;
	rt->hi_accl = 1.0;
	rt->hi_level = 1.0;
	rt->separate = 0.5;
	rt->speed = 0;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[10], 14, 54)];
	eq->mid_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	eq->mid_width = (double)clip_int(st->param_lsb[12], 10, 120) * DIV_10;
}

static void do_xg_2way_rotary_speaker(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_2WayRotarySpeaker *info = (Info_XG_2WayRotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoEQ3 *eq = &info->eq;

	do_eq3_multi(buf, count, eq);
	do_rotary_multi(buf, count, rt);
}

static void conv_xg_ds_2way_rotary_speaker(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_DS_2WayRotarySpeaker *info = (Info_XG_DS_2WayRotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;

	rt->mode = CH_MIX_STEREO;
	rt->low_fast = rt->low_slow = lfo_freq_table_xg[st->param_lsb[0]];
	rt->low_accl = 1.0;
	rt->low_level = 1.0;
	rt->hi_fast = rt->hi_slow = rt->low_fast * 1.1;
	rt->hi_accl = 1.0;
	rt->hi_level = 1.0;
	rt->separate = (double)st->param_lsb[1] * DIV_127;
	rt->speed = 0;
	od->mode = CH_MIX_MONO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[13] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[14], 34, 60)];
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
}

static void do_xg_ds_2way_rotary_speaker(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_DS_2WayRotarySpeaker *info = (Info_XG_DS_2WayRotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	do_stereo_od(buf, count, od);
	do_rotary_multi(buf, count, rt);
}

static void conv_xg_od_2way_rotary_speaker(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_OD_2WayRotarySpeaker *info = (Info_XG_OD_2WayRotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;

	rt->mode = CH_MIX_STEREO;
	rt->low_fast = rt->low_slow = lfo_freq_table_xg[st->param_lsb[0]];
	rt->low_accl = 1.0;
	rt->low_level = 1.0;
	rt->hi_fast = rt->hi_slow = rt->low_fast * 1.1;
	rt->hi_accl = 1.0;
	rt->hi_level = 1.0;
	rt->separate = (double)st->param_lsb[1] * DIV_127;
	rt->speed = 0;
	od->mode = CH_MIX_MONO;
	od->od_type = 0;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[13] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[14], 34, 60)];
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
}

static void do_xg_od_2way_rotary_speaker(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_OD_2WayRotarySpeaker *info = (Info_XG_OD_2WayRotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	do_stereo_od(buf, count, od);
	do_rotary_multi(buf, count, rt);
}

static void conv_xg_amp_2way_rotary_speaker(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_AMP_2WayRotarySpeaker *info = (Info_XG_AMP_2WayRotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;

	rt->mode = CH_MONO_STEREO;
	rt->low_fast = rt->low_slow = lfo_freq_table_xg[st->param_lsb[0]];
	rt->low_accl = 1.0;
	rt->low_level = 1.0;
	rt->hi_fast = rt->hi_slow = rt->low_fast * 1.1;
	rt->hi_accl = 1.0;
	rt->hi_level = 1.0;
	rt->separate = (double)st->param_lsb[1] * DIV_127;
	rt->speed = 0;
	od->mode = CH_MIX_MONO;
	od->od_type = 0;
	od->amp_type = clip_int(st->param_lsb[1], 0, 6);
	od->cab_type = cab_type_xg[clip_int(st->param_lsb[1], 0, 6)];
	od->drive = (double)st->param_lsb[13] * DIV_127;
	od->cutoff = eq_freq_table_xg[clip_int(st->param_lsb[14], 34, 60)];
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
}

static void do_xg_amp_2way_rotary_speaker(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_AMP_2WayRotarySpeaker *info = (Info_XG_AMP_2WayRotarySpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoStereoOD *od = &info->od;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	do_stereo_od(buf, count, od);
	do_rotary_multi(buf, count, rt);
}

static void conv_xg_ensemble_detune(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_EnsembleDetune *info = (Info_XG_EnsembleDetune *)ef->info;
	InfoPitchShifter_core *psl = &info->ps.psl;
	InfoPitchShifter_core *psr = &info->ps.psr;
	InfoEQ2 *eq = &info->eq;
	
	info->ps.mode = CH_STEREO;
	psl->pitch_cent = clip_int(st->param_lsb[0], 14, 114) - 0x40;
	psl->pre_delay_ms = (double)delay_time_2_table_xg[st->param_lsb[1]];
	psl->feedback = 0;
	psl->ps_delay_ms = PS_CF_DELAY + 8;
	psr->pitch_cent = clip_int(st->param_lsb[0], 14, 114) - 0x40;
	psr->pre_delay_ms = (double)delay_time_2_table_xg[st->param_lsb[2]];
	psr->feedback = 0;
	psr->ps_delay_ms = PS_CF_DELAY + 8;
	info->wet = calc_wet_gs(st->param_lsb[9]);
	info->dry = calc_dry_gs(st->param_lsb[9]);	
	if(st->connection >= XG_CONN_SYSTEM_CHORUS)
		eq->mode = CH_NONE;
	else
		eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[10], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[12], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[13] - 64, -12, 12);
}

static void do_xg_ensemble_detune(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_EnsembleDetune *info = (Info_XG_EnsembleDetune *)ef->info;
	InfoPitchShifter *ps = &info->ps;
	InfoEQ2 *eq = &info->eq;
	
	send_efx_buffer(ef, buf, count);
	do_eq2_multi(buf, count, eq);
	do_pitch_shifter_multi(ef->efx_buf, count, ps);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, 1.0);
}

static void conv_xg_ambience(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Ambience *info = (Info_XG_Ambience *)ef->info;
	InfoAmbience *amb = &info->amb;
	InfoEQ2 *eq = &info->eq;

	amb->mode = CH_MIX_STEREO;
	amb->delay_ms = (double)mod_delay_offset_table_xg[st->param_lsb[0]];
	amb->phase = clip_int(st->param_lsb[1], 0, 1);
	eq->mode = CH_STEREO;
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	info->wet = calc_wet_gs(st->param_lsb[9]);
	info->dry = calc_dry_gs(st->param_lsb[9]);
}

static void do_xg_ambience(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Ambience *info = (Info_XG_Ambience *)ef->info;
	InfoAmbience *amb = &info->amb;
	InfoEQ2 *eq = &info->eq;
	
	send_efx_buffer(ef, buf, count);
	do_eq2_multi(buf, count, eq);
	do_ambience(ef->efx_buf, count, amb);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, 1.0);
}

static void conv_xg_talking_modulator(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_TalkingModulator *info = (Info_XG_TalkingModulator *)ef->info;
	InfoHumanizer *hm = &info->hm;

	hm->mode = CH_MONO;
	hm->vowel = clip_int(st->param_lsb[0], 0, 4);
	hm->accel = 620 / (double)clip_int(st->param_lsb[0], 1, 62); // ms 620ms~10ms 
	hm->drive = 1.0 + (double)st->param_lsb[3] * DIV_127 * 3.0;
	hm->od_sw = 1;
	info->level = calc_xg_level(st->param_lsb[4], st);
	info->wet = calc_wet_gs(st->param_lsb[9]);
	info->dry = calc_dry_gs(st->param_lsb[9]);
}

static void do_xg_talking_modulator(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_TalkingModulator *info = (Info_XG_TalkingModulator *)ef->info;
	InfoHumanizer *hm = &info->hm;

	send_efx_buffer(ef, buf, count);
	effect_mix_mono(buf, count);
	do_humanizer(buf, count, hm);
	effect_level_stereo(buf, count, info->level);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, 1.0);
}

static void conv_xg_lofi(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_LoFi *info = (Info_XG_LoFi *)ef->info;
	InfoLoFi *lf = &info->lf;

	lf->mode = st->param_lsb[14] ? CH_STEREO : CH_MIX_MONO;
	lf->level_in = otd.xgefx_CustomLFLvIn;
	lf->level_out = pow(10.0, (double)(clip_int(st->param_lsb[2], 0, 18) - 6) * DIV_10) * otd.xgefx_CustomLFLvOut;
	lf->sr_rate = lofi_sampling_freq_table_xg[st->param_lsb[0]];
	lf->pre_fil_type = 0; // lpf off
	lf->pre_fil_freq = 0;
	lf->pre_fil_reso = 0.0;
	lf->bit_length = 4.0 + (double)st->param_lsb[1] * DIV_127 * 12.0; // 4~16bit
	switch(st->param_lsb[4]){
	default:
	case 0: // thru
		lf->post_fil_type = FILTER_NONE; // off
		break;
	case 1: // power bass
		lf->post_fil_type = FILTER_SHELVING_LOW; // eq low
		break;
	case 2: // radio
		lf->post_fil_type = FILTER_LPF12_2; // lpf
		break;
	case 3: // telephon
		lf->post_fil_type = FILTER_BPF12_3; // bpf
		break;
	case 4: // clean
		lf->post_fil_type = FILTER_HPF_BW; // hpf
		break;
	case 5: // low
		lf->post_fil_type = FILTER_LPF_BW; // lpf
		break;
	}
	lf->post_fil_freq = eq_freq_table_xg[clip_int(st->param_lsb[3], 10, 80)];
	lf->post_fil_reso = (double)clip_int(st->param_lsb[5], 10, 120) * DIV_10;		
//	lf->bit_assign = clip_int(st->param_lsb[6], 0, 6);	
//	lf->emphasis = st->param_lsb[7];	
	lf->nz_gen = 0; // noise off
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
}

static void do_xg_lofi(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_LoFi *info = (Info_XG_LoFi *)ef->info;
	InfoLoFi *lf = &info->lf;

	send_efx_buffer(ef, buf, count);
	do_lofi(ef->efx_buf, count, lf);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, 1.0);	
}

static void conv_xg_ds_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_DS_Delay *info= (Info_XG_DS_Delay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoDelayLR *dly = &info->dly;

	// overdrive1
	od->mode = CH_MIX_MONO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[5] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[6], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);	
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[20];
	eq->low_gain = clip_int(st->param_lsb[7] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[43];
	eq->mid_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_width = 1.0;
	eq->high_freq = 0;
	eq->high_gain = 0;
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = (double)clip_int(st->param_msb[0] * 128 + st->param_lsb[0], 1, 14860) * DIV_10;
	dly->rdelay = (double)clip_int(st->param_msb[1] * 128 + st->param_lsb[1], 1, 14860) * DIV_10;
	dly->fdelay1 = (double)clip_int(st->param_msb[2] * 128 + st->param_lsb[2], 1, 14860) * DIV_10;
	dly->fdelay2 = (double)clip_int(st->param_msb[3] * 128 + st->param_lsb[3], 1, 14860) * DIV_10;
	dly->feedback = (double)(st->param_lsb[4] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[5], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[4], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[4], st);
	info->dly_level = 1.0;
}

static void do_xg_ds_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_DS_Delay *info= (Info_XG_DS_Delay *)ef->info;	
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;	
	InfoDelayLR *dly = &info->dly;

	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_od_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_OD_Delay *info= (Info_XG_OD_Delay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoDelayLR *dly = &info->dly;

	// overdrive1
	od->mode = CH_MIX_MONO;
	od->od_type = 0;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[5] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[6], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);	
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[20];
	eq->low_gain = clip_int(st->param_lsb[7] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[43];
	eq->mid_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_width = 1.0;
	eq->high_freq = 0;
	eq->high_gain = 0;
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = (double)clip_int(st->param_msb[0] * 128 + st->param_lsb[0], 1, 14860) * DIV_10;
	dly->rdelay = (double)clip_int(st->param_msb[1] * 128 + st->param_lsb[1], 1, 14860) * DIV_10;
	dly->fdelay1 = (double)clip_int(st->param_msb[2] * 128 + st->param_lsb[2], 1, 14860) * DIV_10;
	dly->fdelay2 = (double)clip_int(st->param_msb[3] * 128 + st->param_lsb[3], 1, 14860) * DIV_10;
	dly->feedback = (double)(st->param_lsb[4] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[5], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[4], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[4], st);
	info->dly_level = 1.0;
}

static void do_xg_od_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_OD_Delay *info= (Info_XG_OD_Delay *)ef->info;	
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;	
	InfoDelayLR *dly = &info->dly;

	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_comp_ds_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Comp_DS_Delay *info= (Info_XG_Comp_DS_Delay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoDelayLR *dly = &info->dly;
	InfoCompressor *cmp = &info->cmp;

	// overdrive1
	od->mode = CH_MONO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[3] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);	
	eq->mode = CH_MONO;
	eq->low_freq = eq_freq_table_xg[20];
	eq->low_gain = clip_int(st->param_lsb[5] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[43];
	eq->mid_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->mid_width = 1.0;
	eq->high_freq = 0;
	eq->high_gain = 0;
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->fdelay1 = dly->rdelay = dly->fdelay2 = (double)clip_int(st->param_msb[0] * 128 + st->param_lsb[0], 1, 14860) * DIV_10;
	dly->feedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = 22000;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[2], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[2], st);
	info->dly_level = 1.0;
	// comp
	cmp->mode = CH_MIX_MONO;
	cmp->attak = compressor_attack_time_table_xg[clip_int(st->param_lsb[10], 0, 19)]; // 10ms-500ms
	cmp->sustain = compressor_release_time_table_xg[clip_int(st->param_lsb[11], 0, 15)]; // 10ms-500ms
	cmp->pre_gain = (double)(127 - clip_int(st->param_lsb[12], 79, 121)); // dB
	cmp->post_gain = 0.0; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 1.0 / compressor_ratio_table_xg[clip_int(st->param_lsb[13], 0, 7)]; // ratio?
	cmp->div_level_0db = div_ins_level * DIV_2;
}

static void do_xg_comp_ds_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Comp_DS_Delay *info= (Info_XG_Comp_DS_Delay *)ef->info;	
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;	
	InfoDelayLR *dly = &info->dly;
	InfoCompressor *cmp = &info->cmp;

	do_compressor_multi(buf, count, cmp);
	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_comp_od_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Comp_OD_Delay *info= (Info_XG_Comp_OD_Delay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoDelayLR *dly = &info->dly;
	InfoCompressor *cmp = &info->cmp;

	// overdrive1
	od->mode = CH_MONO;
	od->od_type = 0;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[3] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);
	eq->mode = CH_MONO;	
	eq->low_freq = eq_freq_table_xg[20];
	eq->low_gain = clip_int(st->param_lsb[5] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[43];
	eq->mid_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->mid_width = 1.0;
	eq->high_freq = 0;
	eq->high_gain = 0;
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->fdelay1 = dly->rdelay = dly->fdelay2 = (double)clip_int(st->param_msb[0] * 128 + st->param_lsb[0], 1, 14860) * DIV_10;
	dly->feedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = 22000;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[2], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[2], st);
	info->dly_level = 1.0;
	// comp
	cmp->mode = CH_MIX_MONO;
	cmp->attak = compressor_attack_time_table_xg[clip_int(st->param_lsb[10], 0, 19)]; // 10ms-500ms
	cmp->sustain = compressor_release_time_table_xg[clip_int(st->param_lsb[11], 0, 15)]; // 10ms-500ms
	cmp->pre_gain = (double)(127 - clip_int(st->param_lsb[12], 79, 121)); // dB
	cmp->post_gain = 0.0; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 1.0 / compressor_ratio_table_xg[clip_int(st->param_lsb[13], 0, 7)]; // ratio?
	cmp->div_level_0db = div_ins_level * DIV_2;
}

static void do_xg_comp_od_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Comp_OD_Delay *info= (Info_XG_Comp_OD_Delay *)ef->info;	
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;	
	InfoDelayLR *dly = &info->dly;
	InfoCompressor *cmp = &info->cmp;

	do_compressor_multi(buf, count, cmp);
	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_wah_ds_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Wah_DS_Delay *info= (Info_XG_Wah_DS_Delay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoDelayLR *dly = &info->dly;
	InfoAutoWah *aw = &info->aw;
	
	// autowah
	aw->mode = CH_MIX_MONO;
	aw->type = 1;
	aw->sens = calc_auto_wah_sens_xg(st->param_lsb[10]);
	aw->depth = 1.0;
	aw->manual = calc_auto_wah_manual_xg(st->param_lsb[11]);
	aw->peak = calc_auto_wah_peak_xg(st->param_lsb[12]);
	aw->release = wah_release_time_table_xg[clip_int(st->param_lsb[13], 52, 67)]; // ms
	aw->pol = 1;
	aw->lfo_sw = 0; // off
	aw->rate = 0.0;
	aw->sens_sw = 1; // on
	info->wah_dry = calc_dry_xg(st->param_lsb[9], st);
	info->wah_wet = calc_wet_xg(st->param_lsb[9], st);
	// overdrive1
	od->mode = CH_MONO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[5] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[6], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);	
	eq->mode = CH_MONO;	
	eq->low_freq = eq_freq_table_xg[20];
	eq->low_gain = clip_int(st->param_lsb[7] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[43];
	eq->mid_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_width = 1.0;
	eq->high_freq = 0;
	eq->high_gain = 0;
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->fdelay1 = dly->rdelay = dly->fdelay2 = (double)clip_int(st->param_msb[0] * 128 + st->param_lsb[0], 1, 14860) * DIV_10;
	dly->feedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = 22000;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[2], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[2], st);
	info->dly_level = 1.0;
}

static void do_xg_wah_ds_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Wah_DS_Delay *info= (Info_XG_Wah_DS_Delay *)ef->info;	
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;	
	InfoDelayLR *dly = &info->dly;
	InfoAutoWah *aw = &info->aw;
	
	send_efx_buffer(ef, buf, count);
	do_auto_wah_multi(buf, count, aw);
	return_efx_buffer(ef, buf, count, info->wah_wet, info->wah_dry, 1.0);
	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_wah_od_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Wah_OD_Delay *info= (Info_XG_Wah_OD_Delay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoDelayLR *dly = &info->dly;
	InfoAutoWah *aw = &info->aw;
	
	// autowah
	aw->mode = CH_MIX_MONO;
	aw->type = 1;
	aw->sens = calc_auto_wah_sens_xg(st->param_lsb[10]);
	aw->depth = 1.0;
	aw->manual = calc_auto_wah_manual_xg(st->param_lsb[11]);
	aw->peak = calc_auto_wah_peak_xg(st->param_lsb[12]);
	aw->release = wah_release_time_table_xg[clip_int(st->param_lsb[13], 52, 67)]; // ms
	aw->pol = 1;
	aw->lfo_sw = 0; // off
	aw->rate = 0.0;
	aw->sens_sw = 1; // on
	info->wah_dry = calc_dry_xg(st->param_lsb[9], st);
	info->wah_wet = calc_wet_xg(st->param_lsb[9], st);
	// overdrive1
	od->mode = CH_MONO;
	od->od_type = 0;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[5] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[6], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);	
	eq->mode = CH_MONO;	
	eq->low_freq = eq_freq_table_xg[20];
	eq->low_gain = clip_int(st->param_lsb[7] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[43];
	eq->mid_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_width = 1.0;
	eq->high_freq = 0;
	eq->high_gain = 0;
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->fdelay1 = dly->rdelay = dly->fdelay2 = (double)clip_int(st->param_msb[0] * 128 + st->param_lsb[0], 1, 14860) * DIV_10;
	dly->feedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = 22000;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[2], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[2], st);
	info->dly_level = 1.0;
}

static void do_xg_wah_od_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Wah_OD_Delay *info= (Info_XG_Wah_OD_Delay *)ef->info;	
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;	
	InfoDelayLR *dly = &info->dly;
	InfoAutoWah *aw = &info->aw;
	
	send_efx_buffer(ef, buf, count);
	do_auto_wah_multi(buf, count, aw);
	return_efx_buffer(ef, buf, count, info->wah_wet, info->wah_dry, 1.0);
	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

const int8 vdsh_od_type[] = {5, 7, 1, 3, 9};
const int8 vdss_od_type[] = {4, 6, 0, 2, 8};
const int8 vds_amp_type[] = {0, 1, 2, 3, 3, 0};
const int8 vds_cab_type[] = {0, 1, 2, 3, 4, 4};

static void conv_xg_v_ds_hard(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_VDistortionHard *info = (Info_XG_VDistortionHard *)ef->info;
	InfoStereoOD *od = &info->od;

	od->mode = CH_MIX_MONO;
	od->od_type = vdsh_od_type[clip_int(st->param_lsb[1], 0, 4)];
	od->amp_type = vds_amp_type[clip_int(st->param_lsb[2], 0, 6)];
	od->cab_type = vds_cab_type[clip_int(st->param_lsb[2], 0, 6)];
	od->drive = (double)st->param_lsb[0] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);
}

static void do_xg_v_ds_hard(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_VDistortionHard *info = (Info_XG_VDistortionHard *)ef->info;
	InfoStereoOD *od = &info->od;

	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
}

static void conv_xg_v_ds_hard_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_VDistortionHard_Delay *info = (Info_XG_VDistortionHard_Delay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoDelayLR *dly = &info->dly;

	od->mode = CH_MIX_MONO;
	od->od_type = vdsh_od_type[clip_int(st->param_lsb[1], 0, 4)];
	od->amp_type = vds_amp_type[clip_int(st->param_lsb[2], 0, 6)];
	od->cab_type = vds_cab_type[clip_int(st->param_lsb[2], 0, 6)];
	od->drive = (double)st->param_lsb[0] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);	
	// delay	
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = (double)clip_int(st->param_msb[5] * 128 + st->param_lsb[5], 1, 14860) * DIV_10;
	dly->rdelay = (double)clip_int(st->param_msb[6] * 128 + st->param_lsb[6], 1, 14860) * DIV_10;
	dly->fdelay1 = (double)clip_int(st->param_msb[7] * 128 + st->param_lsb[7], 1, 14860) * DIV_10;
	dly->fdelay2 = (double)clip_int(st->param_msb[7] * 128 + st->param_lsb[7], 1, 14860) * DIV_10;
	dly->feedback = (double)(st->param_lsb[8] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = 22000;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[10], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[10], st);
	info->dly_level = 1.0;
}

static void do_xg_v_ds_hard_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_VDistortionHard_Delay *info = (Info_XG_VDistortionHard_Delay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoDelayLR *dly = &info->dly;

	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_v_ds_soft(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_VDistortionSoft *info = (Info_XG_VDistortionSoft *)ef->info;
	InfoStereoOD *od = &info->od;

	od->mode = CH_MIX_MONO;
	od->od_type = vdsh_od_type[clip_int(st->param_lsb[1], 0, 4)];
	od->amp_type = vds_amp_type[clip_int(st->param_lsb[2], 0, 6)];
	od->cab_type = vds_cab_type[clip_int(st->param_lsb[2], 0, 6)];
	od->drive = (double)st->param_lsb[0] * DIV_127;
	od->cutoff = eq_freq_table_xg[46];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);
}

static void do_xg_v_ds_soft(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_VDistortionSoft *info = (Info_XG_VDistortionSoft *)ef->info;
	InfoStereoOD *od = &info->od;

	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
}

static void conv_xg_v_ds_soft_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_VDistortionSoft_Delay *info = (Info_XG_VDistortionSoft_Delay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoDelayLR *dly = &info->dly;

	od->mode = CH_MIX_MONO;
	od->od_type = vdsh_od_type[clip_int(st->param_lsb[1], 0, 4)];
	od->amp_type = vds_amp_type[clip_int(st->param_lsb[2], 0, 6)];
	od->cab_type = vds_cab_type[clip_int(st->param_lsb[2], 0, 6)];
	od->drive = (double)st->param_lsb[0] * DIV_127;
	od->cutoff = eq_freq_table_xg[46];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);		
	// delay	
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = (double)clip_int(st->param_msb[5] * 128 + st->param_lsb[5], 1, 14860) * DIV_10;
	dly->rdelay = (double)clip_int(st->param_msb[6] * 128 + st->param_lsb[6], 1, 14860) * DIV_10;
	dly->fdelay1 = (double)clip_int(st->param_msb[7] * 128 + st->param_lsb[7], 1, 14860) * DIV_10;
	dly->fdelay2 = (double)clip_int(st->param_msb[7] * 128 + st->param_lsb[7], 1, 14860) * DIV_10;
	dly->feedback = (double)(st->param_lsb[8] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = 22000;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[10], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[10], st);
	info->dly_level = 1.0;
}

static void do_xg_v_ds_soft_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_VDistortionSoft_Delay *info = (Info_XG_VDistortionSoft_Delay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoDelayLR *dly = &info->dly;
		
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_dual_rotar_speaker(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_DualRotarSpeaker *info = (Info_XG_DualRotarSpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoEQ2 *eq = &info->eq;

	rt->mode = CH_MIX_STEREO;
	rt->low_slow = lfo_freq_table_xg[st->param_lsb[0]];
	rt->hi_slow = lfo_freq_table_xg[st->param_lsb[1]];
	rt->low_fast = lfo_freq_table_xg[st->param_lsb[2]];
	rt->hi_fast = lfo_freq_table_xg[st->param_lsb[3]];
	rt->low_accl = (double)st->param_lsb[4] * DIV_127;
	rt->hi_accl = (double)st->param_lsb[5] * DIV_127;
	rt->low_level = calc_option_level(st->param_lsb[6]) * calc_xg_level(127 - st->param_lsb[8], st);
	rt->hi_level = calc_option_level(st->param_lsb[7]) * calc_xg_level(st->param_lsb[8], st);
	rt->separate = 0.5;
	rt->speed = st->param_lsb[15] ? 1 : 0;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[10], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[12], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[13] - 64, -12, 12);
}

static void do_xg_dual_rotar_speaker(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_DualRotarSpeaker *info = (Info_XG_DualRotarSpeaker *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoEQ2 *eq = &info->eq;

	do_eq2_multi(buf, count, eq);
	do_rotary_multi(buf, count, rt);
}


static void conv_xg_ds_tempo_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_DS_TempoDelay *info= (Info_XG_DS_TempoDelay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoDelayLR *dly = &info->dly;

	// overdrive1
	od->mode = CH_MIX_MONO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[3] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);	
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[20];
	eq->low_gain = clip_int(st->param_lsb[5] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[43];
	eq->mid_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->mid_width = 1.0;
	eq->high_freq = 0;
	eq->high_gain = 0;
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = calc_tempo_xg(clip_int(st->param_lsb[0], 0, 19));
	dly->feedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[10], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[2], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[2], st);
	info->dly_level = 1.0;
}

static void do_xg_ds_tempo_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_DS_TempoDelay *info= (Info_XG_DS_TempoDelay *)ef->info;	
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;	
	InfoDelayLR *dly = &info->dly;

	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_od_tempo_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_OD_TempoDelay *info= (Info_XG_OD_TempoDelay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoDelayLR *dly = &info->dly;

	// overdrive1
	od->mode = CH_MIX_MONO;
	od->od_type = 0;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[3] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[20];
	eq->low_gain = clip_int(st->param_lsb[5] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[43];
	eq->mid_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->mid_width = 1.0;
	eq->high_freq = 0;
	eq->high_gain = 0;
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = calc_tempo_xg(clip_int(st->param_lsb[0], 0, 19));
	dly->feedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[10], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[2], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[2], st);
	info->dly_level = 1.0;
}

static void do_xg_od_tempo_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_OD_TempoDelay *info= (Info_XG_OD_TempoDelay *)ef->info;	
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;	
	InfoDelayLR *dly = &info->dly;

	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_comp_ds_tempo_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Comp_DS_TempoDelay *info= (Info_XG_Comp_DS_TempoDelay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoDelayLR *dly = &info->dly;
	InfoCompressor *cmp = &info->cmp;

	// overdrive1
	od->mode = CH_MONO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[3] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);
	eq->mode = CH_MONO;
	eq->low_freq = eq_freq_table_xg[20];
	eq->low_gain = clip_int(st->param_lsb[5] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[43];
	eq->mid_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->mid_width = 1.0;
	eq->high_freq = 0;
	eq->high_gain = 0;
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = calc_tempo_xg(clip_int(st->param_lsb[0], 0, 19));
	dly->feedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[10], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[2], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[2], st);
	info->dly_level = 1.0;
	// comp
	cmp->mode = CH_MIX_MONO;
	cmp->attak = compressor_attack_time_table_xg[clip_int(st->param_lsb[10], 0, 19)]; // 10ms-500ms
	cmp->sustain = compressor_release_time_table_xg[clip_int(st->param_lsb[11], 0, 15)]; // 10ms-500ms
	cmp->pre_gain = (double)(127 - clip_int(st->param_lsb[12], 79, 121)); // dB
	cmp->post_gain = 0.0;
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 1.0 / compressor_ratio_table_xg[clip_int(st->param_lsb[13], 0, 7)]; // ratio?
	cmp->div_level_0db = div_ins_level * DIV_2;
}

static void do_xg_comp_ds_tempo_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Comp_DS_TempoDelay *info= (Info_XG_Comp_DS_TempoDelay *)ef->info;	
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;	
	InfoDelayLR *dly = &info->dly;
	InfoCompressor *cmp = &info->cmp;

	do_compressor_multi(buf, count, cmp);
	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_comp_od_tempo_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Comp_OD_TempoDelay *info= (Info_XG_Comp_OD_TempoDelay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoDelayLR *dly = &info->dly;
	InfoCompressor *cmp = &info->cmp;

	// overdrive1
	od->mode = CH_MONO;
	od->od_type = 0;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[3] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);
	eq->mode = CH_MONO;	
	eq->low_freq = eq_freq_table_xg[20];
	eq->low_gain = clip_int(st->param_lsb[5] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[43];
	eq->mid_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->mid_width = 1.0;
	eq->high_freq = 0;
	eq->high_gain = 0;
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = calc_tempo_xg(clip_int(st->param_lsb[0], 0, 19));
	dly->feedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[10], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[2], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[2], st);
	info->dly_level = 1.0;
	// comp
	cmp->mode = CH_MIX_MONO;
	cmp->attak = compressor_attack_time_table_xg[clip_int(st->param_lsb[10], 0, 19)]; // 10ms-500ms
	cmp->sustain = compressor_release_time_table_xg[clip_int(st->param_lsb[11], 0, 15)]; // 10ms-500ms
	cmp->pre_gain = (double)(127 - clip_int(st->param_lsb[12], 79, 121)); // dB
	cmp->post_gain = 0.0; // dB
	cmp->threshold = 1.0 ; // threshold(~1.0)
	cmp->slope = 1.0 / compressor_ratio_table_xg[clip_int(st->param_lsb[13], 0, 7)]; // ratio?
	cmp->div_level_0db = div_ins_level * DIV_2;
}

static void do_xg_comp_od_tempo_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Comp_OD_TempoDelay *info= (Info_XG_Comp_OD_TempoDelay *)ef->info;	
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;	
	InfoDelayLR *dly = &info->dly;
	InfoCompressor *cmp = &info->cmp;

	do_compressor_multi(buf, count, cmp);
	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_wah_ds_tempo_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Wah_DS_TempoDelay *info= (Info_XG_Wah_DS_TempoDelay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoDelayLR *dly = &info->dly;
	InfoAutoWah *aw = &info->aw;

	// overdrive1
	od->mode = CH_MONO;
	od->od_type = 1;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[3] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);	
	eq->mode = CH_MONO;	
	eq->low_freq = eq_freq_table_xg[20];
	eq->low_gain = clip_int(st->param_lsb[5] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[43];
	eq->mid_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->mid_width = 1.0;
	eq->high_freq = 0;
	eq->high_gain = 0;
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = calc_tempo_xg(clip_int(st->param_lsb[0], 0, 19));
	dly->feedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[10], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[2], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[2], st);
	info->dly_level = 1.0;
	// autowah
	aw->mode = CH_MIX_MONO;
	aw->type = 1;
	aw->sens = calc_auto_wah_sens_xg(st->param_lsb[10]);
	aw->depth = 1.0;
	aw->manual = calc_auto_wah_manual_xg(st->param_lsb[11]);
	aw->peak = calc_auto_wah_peak_xg(st->param_lsb[12]);
	aw->release = wah_release_time_table_xg[clip_int(st->param_lsb[13], 52, 67)]; // ms
	aw->pol = 1;
	aw->lfo_sw = 0; // off
	aw->rate = 0.0;
	aw->sens_sw = 1; // on
}

static void do_xg_wah_ds_tempo_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Wah_DS_TempoDelay *info= (Info_XG_Wah_DS_TempoDelay *)ef->info;	
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;	
	InfoDelayLR *dly = &info->dly;
	InfoAutoWah *aw = &info->aw;

	do_auto_wah_multi(buf, count, aw);
	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_wah_od_tempo_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_Wah_OD_TempoDelay *info= (Info_XG_Wah_OD_TempoDelay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;
	InfoDelayLR *dly = &info->dly;
	InfoAutoWah *aw = &info->aw;

	// overdrive1
	od->mode = CH_MONO;
	od->od_type = 0;
	od->amp_type = 0;
	od->cab_type = 0;
	od->drive = (double)st->param_lsb[3] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);
	eq->mode = CH_MONO;	
	eq->low_freq = eq_freq_table_xg[20];
	eq->low_gain = clip_int(st->param_lsb[5] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[43];
	eq->mid_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->mid_width = 1.0;
	eq->high_freq = 0;
	eq->high_gain = 0;
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = calc_tempo_xg(clip_int(st->param_lsb[0], 0, 19));
	dly->feedback = (double)(st->param_lsb[1] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[10], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[2], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[2], st);
	info->dly_level = 1.0;
	// autowah
	aw->mode = CH_MIX_MONO;
	aw->type = 1;	
	aw->sens = calc_auto_wah_sens_xg(st->param_lsb[10]);
	aw->depth = 1.0;
	aw->manual = calc_auto_wah_manual_xg(st->param_lsb[11]);
	aw->peak = calc_auto_wah_peak_xg(st->param_lsb[12]);
	aw->release = wah_release_time_table_xg[clip_int(st->param_lsb[13], 52, 67)]; // ms
	aw->pol = 1;
	aw->lfo_sw = 0; // off
	aw->rate = 0.0;
	aw->sens_sw = 1; // on
}

static void do_xg_wah_od_tempo_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_Wah_OD_TempoDelay *info= (Info_XG_Wah_OD_TempoDelay *)ef->info;	
	InfoStereoOD *od = &info->od;
	InfoEQ3 *eq = &info->eq;	
	InfoDelayLR *dly = &info->dly;
	InfoAutoWah *aw = &info->aw;

	do_auto_wah_multi(buf, count, aw);
	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_v_ds_hard_tempo_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_VDistortionHard_TempoDelay *info = (Info_XG_VDistortionHard_TempoDelay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoDelayLR *dly = &info->dly;

	od->mode = CH_MIX_MONO;
	od->od_type = vdsh_od_type[clip_int(st->param_lsb[1], 0, 4)];
	od->amp_type = vds_amp_type[clip_int(st->param_lsb[2], 0, 6)];
	od->cab_type = vds_cab_type[clip_int(st->param_lsb[2], 0, 6)];
	od->drive = (double)st->param_lsb[0] * DIV_127;
	od->cutoff = eq_freq_table_xg[48];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);	
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = calc_tempo_xg(clip_int(st->param_lsb[5], 0, 19));
	dly->feedback = (double)(st->param_lsb[6] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[10], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[10], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[10], st);
	info->dly_level = 1.0;
}

static void do_xg_v_ds_hard_tempo_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_VDistortionHard_TempoDelay *info = (Info_XG_VDistortionHard_TempoDelay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoDelayLR *dly = &info->dly;
	
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_v_ds_soft_tempo_delay(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_VDistortionSoft_TempoDelay *info = (Info_XG_VDistortionSoft_TempoDelay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoDelayLR *dly = &info->dly;

	od->mode = CH_MIX_MONO;
	od->od_type = vdsh_od_type[clip_int(st->param_lsb[1], 0, 4)];
	od->amp_type = vds_amp_type[clip_int(st->param_lsb[2], 0, 6)];
	od->cab_type = vds_cab_type[clip_int(st->param_lsb[2], 0, 6)];
	od->drive = (double)st->param_lsb[0] * DIV_127;
	od->cutoff = eq_freq_table_xg[46];
	info->od_level = calc_xg_level(st->param_lsb[4], st);
	info->od_dry = calc_dry_xg(st->param_lsb[9], st);
	info->od_wet = calc_wet_xg(st->param_lsb[9], st);
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->rdelay = dly->fdelay1 = dly->fdelay2 = calc_tempo_xg(clip_int(st->param_lsb[5], 0, 19));
	dly->feedback = (double)(st->param_lsb[6] - 64) * (0.763 * 2.0 * DIV_100);
	dly->high_damp = (1.0 - (double)clip_int(st->param_lsb[10], 1, 10) * DIV_10) * 22050.0 * div_playmode_rate;
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	info->dly_dry = calc_dry_xg(st->param_lsb[10], st);
	info->dly_wet = calc_wet_xg(st->param_lsb[10], st);
	info->dly_level = 1.0;
}

static void do_xg_v_ds_soft_tempo_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_VDistortionSoft_TempoDelay *info = (Info_XG_VDistortionSoft_TempoDelay *)ef->info;
	InfoStereoOD *od = &info->od;
	InfoDelayLR *dly = &info->dly;
	
	send_efx_buffer(ef, buf, count);
	do_stereo_od(ef->efx_buf, count, od);
	return_efx_buffer(ef, buf, count, info->od_wet, info->od_dry, info->od_level);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->dly_wet, info->dly_dry, info->dly_level);
}

static void conv_xg_v_flanger(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_VFlanger *info = (Info_XG_VFlanger *)ef->info;
	InfoStereoChorus *fl = &info->fl;
	InfoEQ3 *eq = &info->eq;

	fl->mode = CH_STEREO;
	fl->phase = 3;
	fl->filter_type = 0; // off
	fl->filter_cutoff = 22000; // 22000Hz
	fl->rate = lfo_freq_table_xg[st->param_lsb[0]];
	fl->depth_cent = calc_chorus_depth_xg(st->param_lsb[1]);
	fl->feedback = (double)(st->param_lsb[4] - 64) * (0.763 * 2.0 * DIV_100);
	fl->pdelay_ms = mod_delay_offset_table_xg[32];
	fl->phase_diff = (double)(clip_int(st->param_lsb[13], 4, 124) - 64) * 3.0;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = 1.0;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[10], 14, 54)];
	eq->mid_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	eq->mid_width = (double)clip_int(st->param_lsb[12], 10, 120) * DIV_10;	
}

static void do_xg_v_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_VFlanger *info = (Info_XG_VFlanger *)ef->info;
	InfoStereoChorus *fl = &info->fl;
	InfoEQ3 *eq = &info->eq;	

	do_eq3_multi(buf, count, eq);	
	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, fl);
	do_chorus_ex(ef->efx_buf, count, fl);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_xg_tempo_flanger(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_TempoFlanger *info = (Info_XG_TempoFlanger *)ef->info;
	InfoStereoChorus *fl = &info->fl;
	InfoEQ3 *eq = &info->eq;

	fl->mode = CH_STEREO;
	fl->phase = 3;
	fl->filter_type = 0; // off
	fl->filter_cutoff = 22000; // 22000Hz
	fl->rate = 1.0 / calc_tempo_xg(clip_int(st->param_lsb[0], 5, 21)); //  s=1/t
	fl->depth_cent = calc_chorus_depth_xg(st->param_lsb[1]);
	fl->feedback = (double)(st->param_lsb[2] - 64) * (0.763 * 2.0 * DIV_100);
	fl->pdelay_ms = mod_delay_offset_table_xg[st->param_lsb[3]];
	fl->phase_diff = (double)(clip_int(st->param_lsb[13], 4, 124) - 64) * 3.0;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->level = 1.0;
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[10], 14, 54)];
	eq->mid_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	eq->mid_width = (double)clip_int(st->param_lsb[12], 10, 120) * DIV_10;	
}

static void do_xg_tempo_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_TempoFlanger *info = (Info_XG_TempoFlanger *)ef->info;
	InfoStereoChorus *fl = &info->fl;
	InfoEQ3 *eq = &info->eq;	

	do_eq3_multi(buf, count, eq);	
	send_efx_buffer(ef, buf, count);
//	do_chorus_p3(ef->efx_buf, count, fl);
	do_chorus_ex(ef->efx_buf, count, fl);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_xg_tempo_phaser(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_TempoPhaser *info = (Info_XG_TempoPhaser *)ef->info;
	InfoPhaser *ph = &info->ph;
	InfoEQ3 *eq = &info->eq;

	ph->mode = CH_STEREO;
	ph->phase = 4;
	ph->manual = (double)manual_table[64];
	ph->rate = lfo_freq_table_xg[st->param_lsb[0]];
	ph->depth_cent = calc_chorus_depth_xg(st->param_lsb[1]);
	ph->offset = (double)(st->param_lsb[2] - 64) * DIV_64;
	ph->feedback = (double)(st->param_lsb[3] - 64) * DIV_64;	
	ph->reso = 6.0; // 6dB
	ph->phase_diff = 180 + clip_int(st->param_lsb[12] - 64, -60, 60) * 3; // def 0~+360
	info->wet = calc_wet_xg(st->param_lsb[9], st);
	info->dry = calc_dry_xg(st->param_lsb[9], st);
	info->level = 1.0;
	// stage = st->param_lsb[10]
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[5], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[6] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[7], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[8] - 64, -12, 12);
	eq->mid_freq = eq_freq_table_xg[clip_int(st->param_lsb[10], 14, 54)];
	eq->mid_gain = clip_int(st->param_lsb[11] - 64, -12, 12);
	eq->mid_width = (double)clip_int(st->param_lsb[12], 10, 120) * DIV_10;
}

static void do_xg_tempo_phaser(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_TempoPhaser *info = (Info_XG_TempoPhaser *)ef->info;
	InfoPhaser *ph = &info->ph;
	InfoEQ3 *eq = &info->eq;

	do_eq3_multi(buf, count, eq);
	send_efx_buffer(ef, buf, count);
	do_phaser_multi(ef->efx_buf, count, ph);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_xg_ring_modulator(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_RingModulator *info = (Info_XG_RingModulator *)ef->info;
	InfoRingModulator *rm = &info->rm;
	InfoEQ2 *eq = &info->eq;	
	FilterCoefficients *lpf = &info->lpf, *hpf = &info->hpf;
		
	// ring modulator
	rm->mode = CH_STEREO;
	rm->freq = (double)ring_mod_carrier_freq_course_xg[st->param_lsb[0]] * pow(2.0, (double)st->param_lsb[1] * DIV_127 * DIV_12);
	rm->lfo_sw = 1; // lfo on
	rm->wave = st->param_lsb[2] ? LFO_SINE : LFO_TRIANGULAR;
	rm->depth = (double)st->param_lsb[3] * DIV_127;
	rm->rate = (double)lfo_freq_table_xg[st->param_lsb[4]];
	info->rm_dry = calc_dry_xg(st->param_lsb[9], st);
	info->rm_wet = calc_wet_xg(st->param_lsb[9], st);
	info->rm_level = 1.0;
	// filter
	init_sample_filter(hpf, (double)eq_freq_table_xg[clip_int(st->param_lsb[5], 0, 52)], 0, FILTER_HPF_BW);
	init_sample_filter(lpf, (double)eq_freq_table_xg[clip_int(st->param_lsb[6], 34, 60)], 0, FILTER_LPF_BW);
	//eq
	eq->mode = CH_STEREO;	
	eq->low_freq = eq_freq_table_xg[clip_int(st->param_lsb[12], 4, 40)];
	eq->low_gain = clip_int(st->param_lsb[13] - 64, -12, 12);
	eq->high_freq = eq_freq_table_xg[clip_int(st->param_lsb[14], 28, 58)];
	eq->high_gain = clip_int(st->param_lsb[15] - 64, -12, 12);

	info->rm_wet *= 2.0;
}

static void do_xg_ring_modulator(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_RingModulator *info = (Info_XG_RingModulator *)ef->info;
	InfoRingModulator *rm = &info->rm;
	InfoEQ2 *eq = &info->eq;
	FilterCoefficients *lpf = &info->lpf, *hpf = &info->hpf;

	do_eq2_multi(buf, count, eq);	
	send_efx_buffer(ef, buf, count);
	do_ring_modulator_multi(ef->efx_buf, count, rm);
	buffer_filter_stereo(hpf, ef->efx_buf, count);
	buffer_filter_stereo(lpf, ef->efx_buf, count);
	return_efx_buffer(ef, buf, count, info->rm_wet, info->rm_dry, info->rm_level);
}

static void conv_xg_3d_manual(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_3DManual *info = (Info_XG_3DManual *)ef->info;	
	Info3DManual *lc = &info->locate;

	lc->azimuth = (double)(clip_int(st->param_lsb[0], 4, 124) - 64) * 3.0 * DIV_180;
	lc->elevation = st->param_lsb[1];
	lc->distance = st->param_lsb[2];
	lc->out = st->param_lsb[5] ? 1 : 0;	
}

static void do_xg_3d_manual(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_3DManual *info = (Info_XG_3DManual *)ef->info;	
	Info3DManual *lc = &info->locate;

	do_3d_manual(buf, count, lc);	
}

static void conv_xg_3d_auto(struct effect_xg_t *st, EffectList *ef)
{
	Info_XG_3DAuto *info = (Info_XG_3DAuto *)ef->info;	
	Info3DAuto *lc = &info->locate;
	
	lc->azimuth = (double)(clip_int(st->param_lsb[0], 4, 124) - 64) * 3.0 * DIV_180;
	lc->elevation = st->param_lsb[1];
	lc->distance = st->param_lsb[2];
	lc->speed = (double)clip_int(st->param_lsb[3], 0, 100) * DIV_10;
	if(st->param_lsb[4] == 0){
		lc->clockwize = 0;
		lc->turn = 0;
	}else if(st->param_lsb[4] == 1){
		lc->clockwize = 1;
		lc->turn = 0;
	}else { // (st->param_lsb[4] == 2)
		lc->turn = 1;
	}
	lc->out = st->param_lsb[5] ? 1 : 0;
}

static void do_xg_3d_auto(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_XG_3DAuto *info = (Info_XG_3DAuto *)ef->info;	
	Info3DAuto *lc = &info->locate;

	do_3d_auto(buf, count, lc);
}


/********************************** SD EFFECT conv **********************************/

const FLOAT_T eq_freq_table_sd[] = { 200, 250, 315, 400, 500, 630, 800, 1000, 
	1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000, 22000,};
const FLOAT_T eq_q_table_sd[] = { 0.5, 1.0, 2.0, 4.0, 8.0,};
#define EQ_FREQ_SD(val) eq_freq_table_sd[clip_int(val, 0, 16)]
#define EQ_FREQb_SD(val) eq_freq_table_sd[clip_int(val, 0, 17)]
#define EQ_Q_SD(val) eq_q_table_sd[clip_int(val, 0, 4)]
#define EQ_GAIN_SD(val) clip_int(val - 15, -15, 15)

static void conv_sd_stereo_eq(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_StereoEQ *info = (Info_SD_StereoEQ *)ef->info;
	InfoStereoEQ *eq = &info->eq;

	eq->low_freq = (st->parameter[0] == 0) ? 200 : 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[1]);
	eq->high_freq = (st->parameter[2] == 0) ? 2000 : (st->parameter[2] == 1) ? 4000 : 8000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[3]);
	eq->m1_freq = EQ_FREQ_SD(st->parameter[4]);
	eq->m1_q = EQ_Q_SD(st->parameter[5]);
	eq->m1_gain = EQ_GAIN_SD(st->parameter[6]);
	eq->m2_freq = EQ_FREQ_SD(st->parameter[7]);
	eq->m2_q = EQ_Q_SD(st->parameter[8]);
	eq->m2_gain = clip_int(st->parameter[9] - 15, -15, 15);
	info->level = calc_sd_level(st->parameter[10]);
}

void do_sd_stereo_eq(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_StereoEQ *info = (Info_SD_StereoEQ *)ef->info;
	InfoStereoEQ *eq = &info->eq;

	do_stereo_eq(buf, count, eq);
	effect_level_stereo(buf, count, info->level);
}


static void conv_sd_overdrive(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Overdrive *info = (Info_SD_Overdrive *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoDistortion *od = &info->od;	
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
	
	//od->mode = CH_LEFT;
	//od->type = 0; // od
	//od->drive = clip_int(st->parameter[0], 0, 127);
	//od->amp_type = clip_int(st->parameter[2], 0, 3);
	//od->amp_sw = 1;
	//od->level = 1.0; 	

	od->mode = CH_LEFT;
	od->bass_od = 0; // gtr/bass
	od->od_type = 0; // od/ds
	od->drive = (double)st->parameter[0] * DIV_127;
	od->tone = 8000; //200 + 100 * st->parameter[1];
	od->level = 1.0;
	od->edge = 0.6;	
	amp->mode = CH_LEFT;
	amp->amp_sw = 0;
	amp->cab_sw = 1; // on
	switch(st->parameter[1]){
	default:
	case 0: // small
		amp->amp_type = 2;
		amp->cab_type = 1;
		break;
	case 1: // built in
		amp->amp_type = 4;
		amp->cab_type = 5;
		break;
	case 2: // 2 stack
		amp->amp_type = 8;
		amp->cab_type = 15;
		break;
	case 3: // 3 stack
		amp->amp_type = 9;
		amp->cab_type = 16;
		break;
	}
	amp->gain1 = 0.5;
	amp->gain2 = 0.5;
	amp->level = 1.0;
	amp->tone = 5000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->bright = 0;	
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;
	eq->mode = CH_LEFT;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[3]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[4]);
	info->panl = calc_pan_sd_left(st->parameter[1]);
	info->panr = calc_pan_sd_right(st->parameter[1]);
	info->level = calc_sd_level(clip_int(st->parameter[5], 0, 127));
}

static void do_sd_overdrive(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Overdrive *info = (Info_SD_Overdrive *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoDistortion *od = &info->od;	
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
	
	effect_mix_mono(buf, count);
//	do_od_ds_multi(buf, count, od);
	do_distortion(buf, count, od);
	do_amp_simulator(buf, count, amp);
	effect_panning_mono_stereo(buf, count, info->panl, info->panr);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_distortion(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Overdrive *info = (Info_SD_Overdrive *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoDistortion *od = &info->od;	
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
	
	//od->mode = CH_LEFT;
	//od->type = 1; // ds
	//od->drive = clip_int(st->parameter[0], 0, 127);
	//od->amp_type = clip_int(st->parameter[2], 0, 3);
	//od->amp_sw = 1;
	//od->level = 1.0; 		

	od->mode = CH_LEFT;
	od->bass_od = 0; // gtr/bass
	od->od_type = 1; // od/ds
	od->drive = (double)st->parameter[0] * DIV_127;
	od->tone = 8000; //200 + 100 * st->parameter[1];
	od->level = 1.0;
	od->edge = 0.8;	
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	switch(st->parameter[1]){
	default:
	case 0: // small
		amp->amp_type = 2;
		amp->cab_type = 1;
		break;
	case 1: // built in
		amp->amp_type = 4;
		amp->cab_type = 5;
		break;
	case 2: // 2 stack
		amp->amp_type = 8;
		amp->cab_type = 15;
		break;
	case 3: // 3 stack
		amp->amp_type = 9;
		amp->cab_type = 16;
		break;
	}
	amp->gain1 = 0.5;
	amp->gain2 = 0.5;
	amp->level = 1.0;
	amp->tone = 5000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->bright = 0;	
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;
	eq->mode = CH_LEFT;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[3]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[4]);
	info->panl = calc_pan_sd_left(st->parameter[1]);
	info->panr = calc_pan_sd_right(st->parameter[1]);
	info->level = calc_sd_level(clip_int(st->parameter[5], 0, 127));
}

static void do_sd_distortion(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Overdrive *info = (Info_SD_Overdrive *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoDistortion *od = &info->od;	
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
	
	effect_mix_mono(buf, count);
//	do_od_ds_multi(buf, count, od);
	do_distortion(buf, count, od);
	do_amp_simulator(buf, count, amp);
	do_eq2_multi(buf, count, eq);
	effect_panning_mono_stereo(buf, count, info->panl, info->panr);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_phaser(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Phaser *info = (Info_SD_Phaser *)ef->info;
	InfoPhaser *ph = &info->ph;

	ph->mode = CH_LEFT;
	ph->phase = 2;
	ph->manual = manual_table[clip_int(st->parameter[0], 0, 127)];
	ph->rate = rate1_table[clip_int(st->parameter[1], 0, 127)];
	ph->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[2], 0, 127));	
	ph->offset = 0.0;
	ph->phase_diff = 0; // deg 0~360
	ph->reso = (double)clip_int(st->parameter[3], 0, 127) * DIV_127 * 12.0; // 12dB
	info->wet = calc_mix_wet_sd(st->parameter[4]);
	info->dry = 1.0; //calc_mix_dry_sd(st->parameter[4]);
	info->panl = calc_pan_sd_left(st->parameter[5]);
	info->panr = calc_pan_sd_right(st->parameter[5]);
	info->level = calc_sd_level(st->parameter[6]);
}

static void do_sd_phaser(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Phaser *info = (Info_SD_Phaser *)ef->info;
	InfoPhaser *ph = &info->ph;
		
	effect_mix_mono(buf, count);
	send_efx_buffer(ef, buf, count);
	do_phaser_multi(ef->efx_buf, count, ph);
	return_efx_buffer_left(ef, buf, count, info->wet, info->dry, info->level);
	effect_panning_mono_stereo(buf, count, info->panl, info->panr);
}

static void conv_sd_spectrum(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Spectrum *info = (Info_SD_Spectrum *)ef->info;
	InfoSpectrum *eq = &info->eq;
	
	eq->mode = CH_LEFT;
	eq->freq[0] = 250;
	eq->freq[1] = 500;
	eq->freq[2] = 1000;
	eq->freq[3] = 1250;
	eq->freq[4] = 2000;
	eq->freq[5] = 3150;
	eq->freq[6] = 4000;
	eq->freq[7] = 8000;
	eq->gain[0] = EQ_GAIN_SD(st->parameter[0]);
	eq->gain[1] = EQ_GAIN_SD(st->parameter[1]);
	eq->gain[2] = EQ_GAIN_SD(st->parameter[2]);
	eq->gain[3] = EQ_GAIN_SD(st->parameter[3]);
	eq->gain[4] = EQ_GAIN_SD(st->parameter[4]);
	eq->gain[5] = EQ_GAIN_SD(st->parameter[5]);
	eq->gain[6] = EQ_GAIN_SD(st->parameter[6]);
	eq->gain[7] = EQ_GAIN_SD(st->parameter[7]);
	eq->width = (double)EQ_Q_SD(st->parameter[8]);
	info->panl = calc_pan_sd_left(st->parameter[9]);
	info->panr = calc_pan_sd_right(st->parameter[9]);
	info->level = calc_sd_level(st->parameter[10]);
}

static void do_sd_spectrum(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Spectrum *info = (Info_SD_Spectrum *)ef->info;
	InfoSpectrum *eq = &info->eq;

	effect_mix_mono(buf, count);
	do_spectrum(buf, count, eq);
	effect_panning_mono_stereo(buf, count, info->panl, info->panr);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_enhancer(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Enhancer *info = (Info_SD_Enhancer *)ef->info;
	InfoEnhancer *eh = &info->eh;
	InfoEQ2 *eq = &info->eq; 

	// Enhancer
	eh->mode = CH_STEREO;
	eh->hpf_cutoff = 3200;
	eh->sens = (double)st->parameter[0] * DIV_127;	
	info->wet = (double)st->parameter[1] * DIV_127;	
	info->dry = 1.0;
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[2]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[3]);
	info->level = calc_sd_level(st->parameter[4]);
}

static void do_sd_enhancer(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Enhancer *info = (Info_SD_Enhancer *)ef->info;
	InfoEnhancer *eh = &info->eh;
	InfoEQ2 *eq = &info->eq; 

	send_efx_buffer(ef, buf, count);
	do_enhancer_multi(ef->efx_buf, count, eh);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_auto_wah(struct mfx_effect_sd_t *st, EffectList *ef)
{	
	Info_SD_AutoWah *info = (Info_SD_AutoWah *)ef->info;
	InfoAutoWah *aw = &info->aw;

	aw->mode = CH_MONO;
	aw->type = st->parameter[0] ? 1 : 0;
	aw->rate = (double)rate1_table[st->parameter[1]];
	aw->depth = (double)st->parameter[2] * DIV_127;
	aw->sens = calc_auto_wah_sens_gs(st->parameter[3]);	
	aw->release = 100.0; // ms
	aw->manual = calc_auto_wah_manual_gs(st->parameter[4]);
	aw->peak = calc_auto_wah_peak_gs(st->parameter[5]);
	aw->pol = 1;
	aw->lfo_sw = 1; // on
	aw->sens_sw = 1; // on
	info->level = calc_sd_level(st->parameter[6]);
}

static void do_sd_auto_wah(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_AutoWah *info = (Info_SD_AutoWah *)ef->info;
	InfoAutoWah *aw = &info->aw;
	
	effect_mix_mono(buf, count);
	do_auto_wah_multi(buf, count, aw);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_rotary(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Rotary *info = (Info_SD_Rotary *)ef->info;
	InfoRotary *rt = &info->rt;

	rt->mode = CH_MIX_STEREO;
	rt->hi_slow = (double)rate1_table[st->parameter[0]];
	rt->low_slow = (double)rate1_table[st->parameter[10]];
	rt->hi_fast = (double)rate1_table[st->parameter[2]];
	rt->low_fast = (double)rate1_table[st->parameter[3]];
	rt->speed = st->parameter[4] ? 1 : 0;
	rt->hi_accl = (double)clip_int(st->parameter[5], 0, 15) * DIV_15;
	rt->low_accl = (double)clip_int(st->parameter[6], 0, 15) * DIV_15;
	rt->hi_level = calc_option_level(st->parameter[7]);
	rt->low_level = calc_option_level(st->parameter[8]);
	rt->separate = (double)st->parameter[9] * DIV_127;
	info->level = calc_sd_level(st->parameter[10]);
}

static void do_sd_rotary(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Rotary *info = (Info_SD_Rotary *)ef->info;
	InfoRotary *rt = &info->rt;

	do_rotary_multi(buf, count, rt);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_compressor(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Compressor *info = (Info_SD_Compressor *)ef->info;
	InfoCompressor *cmp = &info->cmp;
	InfoEQ2 *eq = &info->eq; 

	cmp->mode = CH_LEFT;
	cmp->sustain = mix_double ((double)st->parameter[0] * DIV_127, 10, 500); // 10ms-500ms
	cmp->attak = mix_double ((double)st->parameter[1] * DIV_127, 10, 500); // 10ms-500ms
	cmp->post_gain = cmp_lmt_gain_table_gs[clip_int(st->parameter[3], 0, 3)];; // dB
	cmp->pre_gain = 0.0; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 0.5; // ratio? 1/2
	eq->mode = CH_LEFT;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[4]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[5]);
	info->panl = calc_pan_sd_left(st->parameter[2]);
	info->panr = calc_pan_sd_right(st->parameter[2]);
	info->level = calc_sd_level(st->parameter[6]);
}

static void do_sd_compressor(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Compressor *info = (Info_SD_Compressor *)ef->info;
	InfoCompressor *cmp = &info->cmp;
	InfoEQ2 *eq = &info->eq; 

	effect_mix_mono(buf, count);
	do_compressor_multi(buf, count, cmp);
	do_eq2_multi(buf, count, eq);
	effect_panning_mono_stereo(buf, count, info->panl, info->panl);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_limiter(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Limiter *info = (Info_SD_Limiter *)ef->info;
	InfoLimiter *lmt = &info->lmt;
	InfoEQ2 *eq = &info->eq; 

	lmt->mode = CH_LEFT;
	lmt->threshold = (double)clip_int(st->parameter[0], 1, 127) * DIV_127;
	lmt->release = mix_double ((double)st->parameter[1] * DIV_127, 10, 200); // 10ms-200ms
	lmt->ratio = limiter_ratio_table_gs[clip_int(st->parameter[2], 0, 3)];
	lmt->ahead = 10; // 10ms
	lmt->pre_gain = 0;
	lmt->post_gain = cmp_lmt_gain_table_gs[clip_int(st->parameter[4], 0, 3)];
	eq->mode = CH_LEFT;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[5]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[6]);
	info->panl = calc_pan_sd_left(st->parameter[3]);
	info->panr = calc_pan_sd_right(st->parameter[3]);
	info->level = calc_gs_level(st->parameter[7]);
}

static void do_sd_limiter(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Limiter *info = (Info_SD_Limiter *)ef->info;
	InfoLimiter *lmt = &info->lmt;
	InfoEQ2 *eq = &info->eq; 
	
	effect_mix_mono(buf, count);
	do_limiter_multi(buf, count, lmt);
	do_eq2_multi(buf, count, eq);
	effect_panning_mono_stereo(buf, count, info->panl, info->panl);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_hexa_chorus(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_HexaChorus *info = (Info_SD_HexaChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;	

	cho->mode = CH_MIX_STEREO;
	cho->phase = 6;
	cho->filter_type = 0; // off
	cho->filter_cutoff = cutoff_freq_table_gs[127];
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[0], 0, 125)];
	cho->rate = rate1_table[clip_int(st->parameter[1], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[2], 0, 127));
	cho->pdelay_dev = clip_int(st->parameter[3], 0, 20);
	cho->depth_dev = clip_int(st->parameter[4] - 20, -20, 20);
	cho->pan_dev = clip_int(st->parameter[5], 0, 20);
	info->wet = calc_balance_wet_sd(st->parameter[6]);
	info->dry = calc_balance_dry_sd(st->parameter[6]);
	info->level = calc_sd_level(st->parameter[7]);
}

static void do_sd_hexa_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_HexaChorus *info = (Info_SD_HexaChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_sd_tremolo_chorus(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_TremoloChorus *info = (Info_SD_TremoloChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	InfoTremolo *trm = &info->trm;

	cho->mode = CH_MIX_MONO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = cutoff_freq_table_gs[127];
	cho->pdelay_ms = (double)pre_delay_time_table[clip_int(st->parameter[0], 0, 125)];
	cho->rate = (double)rate1_table[clip_int(st->parameter[1], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[2], 0, 127));
	cho->feedback = 0.0;
	cho->phase_diff = 0.0;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	trm->mode = CH_MONO_STEREO;
	trm->type = 1;
	trm->wave = lfo_wave_table_gs[0];
	trm->rate = (double)rate1_table[clip_int(st->parameter[3], 0, 125)];
	trm->depth = (double)0.75 * clip_int(st->parameter[4], 0, 127) * DIV_127;
	trm->phase = (double)2.0 * clip_int(st->parameter[5], 0, 0x5A); // 0~180
	info->wet = calc_balance_wet_sd(st->parameter[6]);
	info->dry = calc_balance_dry_sd(st->parameter[6]);
	info->level = calc_sd_level(st->parameter[7]);
}

static void do_sd_tremolo_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_TremoloChorus *info = (Info_SD_TremoloChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	InfoTremolo *trm = &info->trm;

	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, cho);
	do_tremolo_autopan(ef->efx_buf, count, trm);	
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_sd_space_d(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_StereoChorus *info = (Info_SD_StereoChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;	
	InfoEQ2 *eq = &info->eq; 

	cho->mode = CH_STEREO;
	cho->phase = 2;
	cho->filter_type = 0;
	cho->filter_cutoff = cutoff_freq_table_gs[127];
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[0], 0, 125)];
	cho->rate = rate1_table[clip_int(st->parameter[1], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[2], 0, 127));
	cho->feedback = 0.0;
	cho->phase_diff = (double)2.0 * clip_int(st->parameter[3], 0, 0x5A); // 0~180
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[4]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[5]);
	info->wet = calc_balance_wet_sd(st->parameter[6]);
	info->dry = calc_balance_dry_sd(st->parameter[6]);
	info->level = calc_sd_level(st->parameter[7]);
}

static void do_sd_space_d(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_SpaceD *info = (Info_SD_SpaceD *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	InfoEQ2 *eq = &info->eq; 
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_stereo_chorus(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_StereoChorus *info = (Info_SD_StereoChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;	
	InfoEQ2 *eq = &info->eq; 

	cho->mode = CH_STEREO;
	cho->phase = 3;
	cho->filter_type = clip_int(st->parameter[0], 0, 2);
	cho->filter_cutoff = EQ_FREQ_SD(st->parameter[1]);
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[2], 0, 125)];
	cho->rate = rate1_table[clip_int(st->parameter[3], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[4], 0, 127));
	cho->feedback = 0.0;
	cho->phase_diff = (double)2.0 * clip_int(st->parameter[5], 0, 0x5A); // 0~180
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[7]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[8]);
	info->wet = calc_balance_wet_sd(st->parameter[9]);
	info->dry = calc_balance_dry_sd(st->parameter[9]);
	info->level = calc_sd_level(st->parameter[10]);
}

static void do_sd_stereo_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_StereoChorus *info = (Info_SD_StereoChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	InfoEQ2 *eq = &info->eq; 
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_stereo_flanger(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_StereoChorus *info = (Info_SD_StereoChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;	
	InfoEQ2 *eq = &info->eq; 

	cho->mode = CH_STEREO;
	cho->phase = 3;
	cho->filter_type = clip_int(st->parameter[0], 0, 2);
	cho->filter_cutoff = EQ_FREQ_SD(st->parameter[1]);
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[2], 0, 125)];
	cho->rate = rate1_table[clip_int(st->parameter[3], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[4], 0, 127));
	cho->phase_diff = (double)2.0 * clip_int(st->parameter[5], 0, 0x5A); // 0~180
	cho->feedback = (double)(clip_int(st->parameter[6], 0, 98) - 49) * (2.0 * DIV_100);
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[7]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[8]);
	info->wet = calc_balance_wet_sd(st->parameter[9]);
	info->dry = calc_balance_dry_sd(st->parameter[9]);
	info->level = calc_sd_level(st->parameter[10]);
}

static void do_sd_stereo_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_StereoChorus *info = (Info_SD_StereoChorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	InfoEQ2 *eq = &info->eq; 
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_step_flanger(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_StepFlanger *info = (Info_SD_StepFlanger *)ef->info;
	InfoStereoChorus *cho = &info->cho;	
	InfoEQ2 *eq = &info->eq; 

	cho->mode = CH_STEREO;
	cho->phase = 3;
	cho->filter_type = 2; // hpf
	cho->filter_cutoff = eq_freq_table_sd[7];
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[0], 0, 125)];
	cho->rate = rate1_table[clip_int(st->parameter[1], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[2], 0, 127));
	cho->feedback = (double)(clip_int(st->parameter[3], 0, 98) - 49) * (2.0 * DIV_100);
	// step rate st->parameter[4]
	cho->phase_diff = (double)2.0 * clip_int(st->parameter[5], 0, 0x5A); // 0~180
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[6]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[7]);
	info->wet = calc_balance_wet_sd(st->parameter[8]);
	info->dry = calc_balance_dry_sd(st->parameter[8]);
	info->level = calc_sd_level(st->parameter[9]);
}

static void do_sd_step_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_StepFlanger *info = (Info_SD_StepFlanger *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	InfoEQ2 *eq = &info->eq; 
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_stereo_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_StereoDelay *info = (Info_SD_StereoDelay *)ef->info;
	InfoDelayLR *dly = &info->dly;
	InfoEQ2 *eq = &info->eq; 

	dly->mode = CH_STEREO;
	dly->fb_mode = st->parameter[0] ? 1 : 0;
	dly->ldelay = dly->fdelay1 = (double)delay_time_3_table[clip_int(st->parameter[1], 0, 126)];
	dly->rdelay = dly->fdelay2 = (double)delay_time_3_table[clip_int(st->parameter[2], 0, 126)];
	dly->phasel = st->parameter[3] ? 1 : 0;
	dly->phaser = st->parameter[4] ? 1 : 0;
	dly->feedback = (double)(clip_int(st->parameter[5], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[6]);
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[7]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[8]);
	info->wet = calc_balance_wet_sd(st->parameter[9]);
	info->dry = calc_balance_dry_sd(st->parameter[9]);
	info->level = calc_sd_level(st->parameter[10]);
}

static void do_sd_stereo_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_StereoDelay *info = (Info_SD_StereoDelay *)ef->info;
	InfoDelayLR *dly = &info->dly;
	InfoEQ2 *eq = &info->eq; 

	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_mod_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_ModDelay *info = (Info_SD_ModDelay *)ef->info;
	InfoModDelay *dly = &info->dly;	
	InfoEQ2 *eq = &info->eq; 
	
	dly->mode = CH_STEREO;
	dly->fb_mode = st->parameter[0] ? 1 : 0;
	dly->ldelay_ms = (double)delay_time_3_table[clip_int(st->parameter[1], 0, 126)];
	dly->rdelay_ms = (double)delay_time_3_table[clip_int(st->parameter[2], 0, 126)];
	dly->feedback = (double)(clip_int(st->parameter[3], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[4]);
	dly->rate = rate1_table[clip_int(st->parameter[5], 0, 125)];
	dly->depth_cent = calc_chorus_depth_gs(st->parameter[6]);
	dly->phase = (double)2.0 * clip_int(st->parameter[7], 0, 0x5A); // 0~180
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[8]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[9]);
	info->wet = calc_balance_wet_sd(st->parameter[10]);
	info->dry = calc_balance_dry_sd(st->parameter[10]);
	info->level = calc_sd_level(st->parameter[11]);
}

static void do_sd_mod_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_ModDelay *info = (Info_SD_ModDelay *)ef->info;
	InfoModDelay *dly = &info->dly;
	InfoEQ2 *eq = &info->eq; 

	send_efx_buffer(ef, buf, count);
	do_mod_delay_multi(ef->efx_buf, count, dly);	
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_3tap_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_3TapDelay *info = (Info_SD_3TapDelay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;
	InfoEQ2 *eq = &info->eq; 

	dly->mode = CH_MIX_STEREO;
	dly->tap = 3;
	dly->dtime[1] = (double)delay_time_1_table[clip_int(st->parameter[0], 0, 125)];
	dly->dtime[2] = (double)delay_time_1_table[clip_int(st->parameter[1], 0, 125)];
	dly->dtime[0] = (double)delay_time_1_table[clip_int(st->parameter[2], 0, 125)];
	dly->dtime[3] = dly->dtime[0]; // [tap] for feedback_delay // dtime[0]と同じ
	dly->pan[0] = 0x40;
	dly->pan[1] = 0x00;
	dly->pan[2] = 0x7F;
	dly->pan[3] = 0x40; // [tap] for feedback_delay
	dly->feedback = (double)(clip_int(st->parameter[3], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[4]);
	dly->dlevel[1] = calc_option_level(st->parameter[5]);
	dly->dlevel[2] = calc_option_level(st->parameter[6]);
	dly->dlevel[0] = calc_option_level(st->parameter[7]);
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[8]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[9]);
	info->wet = calc_balance_wet_sd(st->parameter[10]);
	info->dry = calc_balance_dry_sd(st->parameter[10]);
	info->level = calc_sd_level(st->parameter[11]);
}

static void do_sd_3tap_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_3TapDelay *info = (Info_SD_3TapDelay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;
	InfoEQ2 *eq = &info->eq; 

	send_efx_buffer(ef, buf, count);
	do_multi_tap_delay(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_4tap_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_4TapDelay *info = (Info_SD_4TapDelay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;
	
	dly->mode = CH_MIX_STEREO;
	dly->tap = 4;
	dly->dtime[0] = (double)delay_time_1_table[clip_int(st->parameter[0], 0, 125)];
	dly->dtime[1] = (double)delay_time_1_table[clip_int(st->parameter[1], 0, 125)];
	dly->dtime[2] = (double)delay_time_1_table[clip_int(st->parameter[2], 0, 125)];
	dly->dtime[3] = (double)delay_time_1_table[clip_int(st->parameter[3], 0, 125)];
	dly->dtime[4] = dly->dtime[0]; // [tap] for feedback_delay // dtime[0]と同じ
	dly->pan[0] = 0x50;
	dly->pan[1] = 0x30;
	dly->pan[2] = 0x70;
	dly->pan[3] = 0x10;
	dly->pan[4] = 0x40; // [tap] for feedback_delay
	dly->dlevel[0] = calc_option_level(st->parameter[4]);
	dly->dlevel[1] = calc_option_level(st->parameter[5]);
	dly->dlevel[2] = calc_option_level(st->parameter[6]);
	dly->dlevel[3] = calc_option_level(st->parameter[7]);
	dly->feedback = (double)(clip_int(st->parameter[8], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[9]);
	info->wet = calc_balance_wet_sd(st->parameter[10]);
	info->dry = calc_balance_dry_sd(st->parameter[10]);
	info->level = calc_sd_level(st->parameter[11]);
}

static void do_sd_4tap_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_4TapDelay *info = (Info_SD_4TapDelay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;

	send_efx_buffer(ef, buf, count);
	do_multi_tap_delay(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_sd_tm_ctrl_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_TmCtrlDelay *info = (Info_SD_TmCtrlDelay *)ef->info;
	InfoDelayShifter *dly = &info->dly;
	InfoEQ2 *eq = &info->eq; 

	dly->mode = CH_MIX_MONO;
	dly->ldelay = dly->rdelay = (double)delay_time_2_table[clip_int(st->parameter[0], 0, 125)];
	dly->feedback = (double)(clip_int(st->parameter[1], 0, 98) - 49) * (2.0 * DIV_100);
	dly->accel = clip_int(st->parameter[2], 0, 15); // 0 ~ 15
	dly->high_damp = EQ_FREQb_SD(st->parameter[3]);
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[5]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[6]);
	info->panl = calc_pan_sd_left(st->parameter[4]);
	info->panr = calc_pan_sd_right(st->parameter[4]);
	info->wet = calc_balance_wet_sd(st->parameter[7]);
	info->dry = calc_balance_dry_sd(st->parameter[7]);
	info->level = calc_sd_level(st->parameter[8]);
}

static void do_sd_tm_ctrl_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_TmCtrlDelay *info = (Info_SD_TmCtrlDelay *)ef->info;
	InfoDelayShifter *dly = &info->dly;
	InfoEQ2 *eq = &info->eq; 

	send_efx_buffer(ef, buf, count);
	do_delay_shifter(ef->efx_buf, count, dly);	
	effect_panning_mono_stereo(ef->efx_buf, count, info->panl, info->panr);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_2pitch_shifter(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_2PitchShifter *info = (Info_SD_2PitchShifter *)ef->info;
	InfoPitchShifter_core *psl = &info->ps.psl;
	InfoPitchShifter_core *psr = &info->ps.psr;

	info->ps.mode = CH_MIX_STEREO;
	psl->ps_delay_ms = psr->ps_delay_ms = PS_CF_DELAY + clip_int(st->parameter[0], 0x00, 0x04) * 4; // PS_CF_DELAY + 16ms
	psl->pitch_cent = (double)(clip_int(st->parameter[1], 0, 36) - 12) * 100 + (clip_int(st->parameter[3], 0, 100) - 50) * 2;
	psr->pitch_cent = (double)(clip_int(st->parameter[2], 0, 36) - 12) * 100 + (clip_int(st->parameter[4], 0, 100) - 50) * 2;
	psl->pre_delay_ms = (double)delay_time_3_table[clip_int(st->parameter[5], 0, 126)];
	psr->pre_delay_ms = (double)delay_time_3_table[clip_int(st->parameter[6], 0, 126)];
	psl->feedback = 0.0;
	psr->feedback = 0.0;
	info->panll = calc_pan_sd_left(st->parameter[7]);
	info->panlr = calc_pan_sd_right(st->parameter[7]);
	info->panrl = calc_pan_sd_left(st->parameter[8]);
	info->panrr = calc_pan_sd_right(st->parameter[8]);
	info->bal1 = calc_balance_wet_sd(st->parameter[9]);
	info->bal2 = calc_balance_dry_sd(st->parameter[9]);
	info->wet = calc_balance_wet_sd(st->parameter[10]);
	info->dry = calc_balance_dry_sd(st->parameter[10]);
	info->level = calc_sd_level(st->parameter[11]);
}

static void do_sd_2pitch_shifter(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_2PitchShifter *info = (Info_SD_2PitchShifter *)ef->info;
	InfoPitchShifter *ps = &info->ps;
	
	send_efx_buffer(ef, buf, count);
	do_pitch_shifter_multi(ef->efx_buf, count, ps);
	effect_level_left(ef->efx_buf, count, info->bal1);
	effect_level_right(ef->efx_buf, count, info->bal2);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_sd_fb_pitch_shifter(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_FbPitchShifter *info = (Info_SD_FbPitchShifter *)ef->info;
	InfoPitchShifter *ps = &info->ps;
	InfoEQ2 *eq = &info->eq; 
	
	info->ps.mode = CH_MIX_MONO;
	ps->psl.ps_delay_ms = PS_CF_DELAY + clip_int(st->parameter[0], 0x00, 0x04) * 4; // PS_CF_DELAY + 16ms
	ps->psl.pitch_cent = (double)(clip_int(st->parameter[1], 0, 36) - 12) * 100 + (clip_int(st->parameter[2], 0, 100) - 50) * 2;
	ps->psl.pre_delay_ms = (double)delay_time_3_table[clip_int(st->parameter[3], 0, 126)];
	ps->psl.feedback = (double)(clip_int(st->parameter[4], 0, 98) - 49) * (2.0 * DIV_100);
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[7]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[8]);
	info->panl = calc_pan_sd_left(st->parameter[5]);
	info->panr = calc_pan_sd_right(st->parameter[5]);
	info->wet = calc_balance_wet_sd(st->parameter[15]);
	info->dry = calc_balance_dry_sd(st->parameter[15]);
	info->level = calc_gs_level(st->parameter[19]);
}

static void do_sd_fb_pitch_shifter(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_FbPitchShifter *info = (Info_SD_FbPitchShifter *)ef->info;	
	InfoPitchShifter *ps = &info->ps;
	InfoEQ2 *eq = &info->eq; 

	send_efx_buffer(ef, buf, count); 
	do_pitch_shifter_multi(ef->efx_buf, count, ps);
	effect_panning_mono_stereo(ef->efx_buf, count, info->panl, info->panr);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level); 
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_reverb(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Reverb *info = (Info_SD_Reverb *)ef->info;
	InfoFreeverb *rvb = &info->rvb;	
	InfoReverbEX *rvb2 = &info->rvb2;	
#ifdef REV_EX2
	InfoReverbEX2 *rvb3 = &info->rvb3;
#endif
	InfoEQ2 *eq = &info->eq; 

#ifdef REV_EX2			
	if((opt_reverb_control >= 7 && opt_reverb_control < 9) || (opt_reverb_control <= -768 && opt_reverb_control > -1024)){
		info->rev_type = 2; // reverb ex2
		rvb3->mode = CH_MIX_STEREO;
		switch(clip_int(st->parameter[0], 0x00, 0x05)){
		case 0: // room1
			rvb3->height = 3.0; // m
			rvb3->width = 5.0; // m
			rvb3->depth = 7.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.65;
			rvb3->er_level = 0.50;
			rvb3->rev_level = 0.50;
			rvb3->density = 1.0;
			break;
		case 1: // room2
			rvb3->height = 4.0; // m
			rvb3->width = 8.0; // m
			rvb3->depth = 10.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.99;
			rvb3->er_level = 0.45;
			rvb3->rev_level = 0.55;
			rvb3->density = 0.75;
			break;
		case 2: // stage1
			rvb3->height = 10.0; // m
			rvb3->width = 12.0; // m
			rvb3->depth = 15.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.85;
			rvb3->er_level = 0.40;
			rvb3->rev_level = 0.60;
			rvb3->density = 0.75;
			break;
		case 3: // stage2
			rvb3->height = 12.0; // m
			rvb3->width = 13.0; // m
			rvb3->depth = 18.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.95;
			rvb3->er_level = 0.60;
			rvb3->rev_level = 0.40;
			rvb3->density = 1.0;
			break;
		case 4: // hall1
			rvb3->height = 12.0; // m
			rvb3->width = 16.0; // m
			rvb3->depth = 20.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.65;
			rvb3->er_level = 0.50;
			rvb3->rev_level = 0.50;
			rvb3->density = 1.0;
			break;
		default:
		case 5: // hall2
			rvb3->height = 16.0; // m
			rvb3->width = 20.0; // m
			rvb3->depth = 31.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.95;
			rvb3->er_level = 0.45;
			rvb3->rev_level = 0.55;
			rvb3->density = 0.75;
			break;
		}		
		rvb3->er_time_ms = pre_delay_time_table[st->parameter[1]];
		rvb3->rev_time_sec = reverb_time_table[clip_int(st->parameter[2], 0, 127)];
		rvb3->rev_damp_freq = EQ_FREQb_SD(st->parameter[3]);
		rvb3->er_damp_freq = EQ_FREQb_SD(st->parameter[3]);
		rvb3->rev_feedback = 0.0; // reverb_status_gs.delay_feedback
		rvb3->rev_dly_ms = 0;
		rvb3->density = 1.0;
		rvb3->level = 1.0;
	}else 
#endif
	if(otd.efx_CustomRevType){
		info->rev_type = 1; // reverb ex
		rvb2->mode = CH_MIX_STEREO;
		switch(clip_int(st->parameter[0], 0x00, 0x05)){
		case 0: // room1
			rvb2->height = 3.0; // m
			rvb2->width = 5.0; // m
			rvb2->depth = 7.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.65;
			rvb2->er_level = 0.50;
			rvb2->rev_level = 0.50;
			rvb2->density = 1.0;
			break;
		case 1: // room2
			rvb2->height = 4.0; // m
			rvb2->width = 8.0; // m
			rvb2->depth = 10.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.99;
			rvb2->er_level = 0.45;
			rvb2->rev_level = 0.55;
			rvb2->density = 0.75;
			break;
		case 2: // stage1
			rvb2->height = 10.0; // m
			rvb2->width = 12.0; // m
			rvb2->depth = 15.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.85;
			rvb2->er_level = 0.40;
			rvb2->rev_level = 0.60;
			rvb2->density = 0.75;
			break;
		case 3: // stage2
			rvb2->height = 12.0; // m
			rvb2->width = 13.0; // m
			rvb2->depth = 18.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.95;
			rvb2->er_level = 0.60;
			rvb2->rev_level = 0.40;
			rvb2->density = 1.0;
			break;
		case 4: // hall1
			rvb2->height = 12.0; // m
			rvb2->width = 16.0; // m
			rvb2->depth = 20.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.65;
			rvb2->er_level = 0.50;
			rvb2->rev_level = 0.50;
			rvb2->density = 1.0;
			break;
		default:
		case 5: // hall2
			rvb2->height = 16.0; // m
			rvb2->width = 20.0; // m
			rvb2->depth = 31.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.95;
			rvb2->er_level = 0.45;
			rvb2->rev_level = 0.55;
			rvb2->density = 0.75;
			break;
		}		
		rvb2->er_time_ms = pre_delay_time_table[st->parameter[1]];
		rvb2->rev_time_sec = reverb_time_table[clip_int(st->parameter[2], 0, 127)];
		rvb2->rev_damp_freq = EQ_FREQb_SD(st->parameter[3]);
		rvb2->er_damp_freq = EQ_FREQb_SD(st->parameter[3]);
		rvb2->rev_feedback = 0.0; // reverb_status_gs.delay_feedback
		rvb2->rev_dly_ms = 0;
		rvb2->density = 1.0;
		rvb2->level = 1.0;
	}else{
// freeverb
		info->rev_type = 0;
		rvb->mode = CH_MIX_STEREO;
		rvb->rev_rt = ins_gs_revchar_to_rt(clip_int(st->parameter[0], 0x00, 0x05));
		rvb->rev_roomsize = ins_gs_revchar_to_roomsize(clip_int(st->parameter[0], 0x00, 0x05)); 
		rvb->er_time_ms = pre_delay_time_table[clip_int(st->parameter[1], 0, 125)];
		rvb->rev_time_sec = reverb_time_table[clip_int(st->parameter[2], 0, 127)];
		rvb->er_damp_freq = EQ_FREQb_SD(st->parameter[3]);
		rvb->rev_damp = EQ_FREQb_SD(st->parameter[3]);
		rvb->er_level = 0.35;
		rvb->rev_wet = 1.0;//ins_gs_revchar_to_level(clip_int(st->parameter[0], 0x00, 0x05));
		rvb->rev_width = initialwidth;
		rvb->rev_feedback = 0.0;
		rvb->rev_dly_ms = 0;
		rvb->rev_level = 0.65;
		rvb->rev_dif = 1.0;
	}
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[4]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[4]);
	info->rev_wet = calc_balance_wet_sd(st->parameter[6]);
	info->rev_dry = calc_balance_dry_sd(st->parameter[6]);
	info->rev_level = calc_sd_level(st->parameter[7]);
}

static void do_sd_reverb(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Reverb *info = (Info_SD_Reverb *)ef->info;
	InfoFreeverb *rvb = &info->rvb;
	InfoReverbEX *rvb2 = &info->rvb2;
#ifdef REV_EX2
	InfoReverbEX2 *rvb3 = &info->rvb3;
#endif
	InfoEQ2 *eq = &info->eq; 

	send_efx_buffer(ef, buf, count);
#ifdef REV_EX2	
	if(info->rev_type == 2)
		do_reverb_ex2(ef->efx_buf, count, rvb3);
	else 
#endif
	if(info->rev_type)
		do_reverb_ex(ef->efx_buf, count, rvb2);
	else
		do_freeverb(ef->efx_buf, count, rvb);
	return_efx_buffer(ef, buf, count, info->rev_wet, info->rev_dry, info->rev_level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_gate_reverb(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_GateReverb *info = (Info_SD_GateReverb *)ef->info;
	InfoGateReverb *gr = &info->gr;
	InfoEQ2 *eq = &info->eq; 
	
	gr->mode = CH_MIX_STEREO;
	gr->rev_time_sec = 2.0;
	gr->rev_damp_type = FILTER_LPF6;
	gr->rev_damp_bal = 0.85;
	gr->er_level = 0.5;
	gr->rev_level = 0.5;
	gr->room_size = 3.0;
	gr->rev_feedback = 0.0;
	gr->density = 1.0;	
	gr->rev_damp_freq = 16000;
	gr->er_damp_freq = 16000;	
	gr->type = clip_int(st->parameter[0], 0x00, 0x03);
	gr->er_time_ms = pre_delay_time_table[clip_int(st->parameter[1], 0, 125)];
	gr->gate_time_ms = clip_int(st->parameter[2] + 1, 0x01, 0x64) * 5.0;
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[3]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[4]);
	info->gr_wet = calc_balance_wet_sd(st->parameter[5]);
	info->gr_dry = calc_balance_dry_sd(st->parameter[5]);
	info->gr_level = calc_sd_level(st->parameter[6]);
}

static void do_sd_gate_reverb(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_GateReverb *info = (Info_SD_GateReverb *)ef->info;
	InfoGateReverb *gr = &info->gr;
	InfoEQ2 *eq = &info->eq; 

	send_efx_buffer(ef, buf, count);
	do_gate_reverb(ef->efx_buf, count, gr);	
	return_efx_buffer(ef, buf, count, info->gr_wet, info->gr_dry, info->gr_level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_s_od_chorus(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_OD_Chorus *pe= (Info_SD_S_OD_Chorus *)ef->info;
//	InfoOverdrive *od = &pe->info_od;
	InfoDistortion *od = &pe->info_od;
	InfoAmpSimulator *amp = &pe->info_amp;
	InfoStereoChorus *cho = &pe->info_cho;

	// overdrive1
	//od->mode = CH_MIX_MONO;
	//od->type = 0; // od
	//od->amp_sw = 1;	
	//od->amp_type = 1;
	//od->drive = clip_int(st->parameter[0], 0, 127);

	od->mode = CH_MIX_MONO;
	od->bass_od = 0; // gtr/bass
	od->od_type = 0; // od/ds
	od->drive = (double)st->parameter[0] * DIV_127;
	od->tone = 8000; //200 + 100 * st->parameter[1];
	od->level = 1.0;
	od->edge = 0.6;	
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	amp->amp_type = 4;
	amp->cab_type = 5;
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->bright = 0;	
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;
	pe->od_panl = calc_pan_sd_left(st->parameter[1]);	
	pe->od_panr = calc_pan_sd_right(st->parameter[1]);	
	od->level = 1.0; 
	// chorus
	cho->mode = CH_MONO_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[2], 0, 125)];
	cho->rate = (double)rate1_table[clip_int(st->parameter[3], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[4], 0, 127));	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_balance_wet_sd(st->parameter[6]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[6]);
	// mix
	pe->level = calc_sd_level(st->parameter[7]);
}

static void do_sd_s_od_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_OD_Chorus *pe= (Info_SD_S_OD_Chorus *)ef->info;

//	do_od_ds_multi(buf, count, &pe->info_od);
	do_distortion(buf, count, &pe->info_od);
	do_amp_simulator(buf, count, &pe->info_amp);
	effect_panning_mono_stereo(buf, count, pe->od_panl, pe->od_panr);
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_s_od_flanger(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_OD_Flanger *pe= (Info_SD_S_OD_Flanger *)ef->info;
//	InfoOverdrive *od = &pe->info_od;
	InfoDistortion *od = &pe->info_od;
	InfoAmpSimulator *amp = &pe->info_amp;
	InfoStereoChorus *fl = &pe->info_fl;

	// overdrive1
	//od->mode = CH_MIX_MONO;
	//od->type = 0; // od
	//od->amp_sw = 1;	
	//od->amp_type = 1;
	//od->drive = clip_int(st->parameter[0], 0, 127);

	od->mode = CH_MIX_MONO;
	od->bass_od = 0; // gtr/bass
	od->od_type = 0; // od/ds
	od->drive = (double)st->parameter[0] * DIV_127;
	od->tone = 8000; //200 + 100 * st->parameter[1];
	od->level = 1.0;
	od->edge = 0.6;	
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	amp->amp_type = 4;
	amp->cab_type = 5;
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->bright = 0;	
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;
	pe->od_panl = calc_pan_sd_left(st->parameter[1]);	
	pe->od_panr = calc_pan_sd_right(st->parameter[1]);	
	od->level = 1.0; 
	// flanger
	fl->mode = CH_MONO_STEREO;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[2], 0, 125)];
	fl->rate = (double)rate1_table[clip_int(st->parameter[3], 0, 125)];
	fl->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[4], 0, 127));	
	fl->feedback = (double)(clip_int(st->parameter[5], 0, 98) - 49) * (2.0 * DIV_100);
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_balance_wet_sd(st->parameter[6]);
	pe->fl_dry = calc_balance_dry_sd(st->parameter[6]);
	// mix
	pe->level = calc_sd_level(st->parameter[7]);
}

static void do_sd_s_od_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_OD_Flanger *pe= (Info_SD_S_OD_Flanger *)ef->info;
	
//	do_od_ds_multi(buf, count, &pe->info_od);
	do_distortion(buf, count, &pe->info_od);
	do_amp_simulator(buf, count, &pe->info_amp);
	effect_panning_mono_stereo(buf, count, pe->od_panl, pe->od_panr);
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_s_od_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_OD_Delay *pe= (Info_SD_S_OD_Delay *)ef->info;	
//	InfoOverdrive *od = &pe->info_od;
	InfoDistortion *od = &pe->info_od;
	InfoAmpSimulator *amp = &pe->info_amp;
	InfoDelayLR *dly = &pe->info_dly;

	// overdrive1
	//od->mode = CH_MIX_MONO;
	//od->type = 0; // od
	//od->amp_sw = 1;	
	//od->amp_type = 1;
	//od->drive = clip_int(st->parameter[0], 0, 127);

	od->mode = CH_MIX_MONO;
	od->bass_od = 0; // gtr/bass
	od->od_type = 0; // od/ds
	od->drive = (double)st->parameter[0] * DIV_127;
	od->tone = 8000; //200 + 100 * st->parameter[1];
	od->level = 1.0;
	od->edge = 0.6;	
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	amp->amp_type = 4;
	amp->cab_type = 5;
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->bright = 0;	
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;
	pe->od_panl = calc_pan_sd_left(st->parameter[1]);	
	pe->od_panr = calc_pan_sd_right(st->parameter[1]);	
	od->level = 1.0; 
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->fdelay1 = dly->rdelay = dly->fdelay2 = (double)delay_time_3_table[clip_int(st->parameter[2], 0, 126)];
	dly->feedback = (double)(clip_int(st->parameter[3], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[4]);
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	pe->dly_wet = calc_balance_wet_sd(st->parameter[5]);
	pe->dly_dry = calc_balance_dry_sd(st->parameter[5]);
	// mix
	pe->level = calc_sd_level(st->parameter[6]);
}

static void do_sd_s_od_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_OD_Delay *pe= (Info_SD_S_OD_Delay *)ef->info;	
	
//	do_od_ds_multi(buf, count, &pe->info_od);
	do_distortion(buf, count, &pe->info_od);
	do_amp_simulator(buf, count, &pe->info_amp);
	send_efx_buffer(ef, buf, count);
	effect_panning_mono_stereo(buf, count, pe->od_panl, pe->od_panr);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_s_ds_chorus(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_DS_Chorus *pe= (Info_SD_S_DS_Chorus *)ef->info;
//	InfoOverdrive *od = &pe->info_od;
	InfoDistortion *od = &pe->info_od;
	InfoAmpSimulator *amp = &pe->info_amp;
	InfoStereoChorus *cho = &pe->info_cho;

	// distortion
	//od->mode = CH_MIX_MONO;
	//od->type = 1; // ds
	//od->amp_sw = 1;	
	//od->amp_type = 2;
	//od->drive = clip_int(st->parameter[0], 0, 127);

	od->mode = CH_MIX_MONO;
	od->bass_od = 0; // gtr/bass
	od->od_type = 1; // od/ds
	od->drive = (double)st->parameter[0] * DIV_127;
	od->tone = 8000; //200 + 100 * st->parameter[1];
	od->level = 1.0;
	od->edge = 0.6;	
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	amp->amp_type = 4;
	amp->cab_type = 5;
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->bright = 0;	
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;
	pe->od_panl = calc_pan_sd_left(st->parameter[1]);	
	pe->od_panr = calc_pan_sd_right(st->parameter[1]);	
	od->level = 1.0; 
	// chorus
	cho->mode = CH_MONO_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[2], 0, 125)];
	cho->rate = (double)rate1_table[clip_int(st->parameter[3], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[4], 0, 127));	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_balance_wet_sd(st->parameter[6]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[6]);
	// mix
	pe->level = calc_sd_level(st->parameter[7]);
}

static void do_sd_s_ds_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_DS_Chorus *pe= (Info_SD_S_DS_Chorus *)ef->info;
	
//	do_od_ds_multi(buf, count, &pe->info_od);
	do_distortion(buf, count, &pe->info_od);
	do_amp_simulator(buf, count, &pe->info_amp);
	effect_panning_mono_stereo(buf, count, pe->od_panl, pe->od_panr);
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_s_ds_flanger(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_DS_Flanger *pe= (Info_SD_S_DS_Flanger *)ef->info;
//	InfoOverdrive *od = &pe->info_od;
	InfoDistortion *od = &pe->info_od;
	InfoAmpSimulator *amp = &pe->info_amp;
	InfoStereoChorus *fl = &pe->info_fl;

	// distortion
	//od->mode = CH_MIX_MONO;
	//od->type = 1; // ds
	//od->amp_sw = 1;	
	//od->amp_type = 2;
	//od->drive = clip_int(st->parameter[0], 0, 127);

	od->mode = CH_MIX_MONO;
	od->bass_od = 0; // gtr/bass
	od->od_type = 1; // od/ds
	od->drive = (double)st->parameter[0] * DIV_127;
	od->tone = 8000; //200 + 100 * st->parameter[1];
	od->level = 1.0;
	od->edge = 0.6;	
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	amp->amp_type = 4;
	amp->cab_type = 5;
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->bright = 0;	
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;
	pe->od_panl = calc_pan_sd_left(st->parameter[1]);	
	pe->od_panr = calc_pan_sd_right(st->parameter[1]);	
	od->level = 1.0; 
	// flanger
	fl->mode = CH_MONO_STEREO;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[2], 0, 125)];
	fl->rate = (double)rate1_table[clip_int(st->parameter[3], 0, 125)];
	fl->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[4], 0, 127));	
	fl->feedback = (double)(clip_int(st->parameter[5], 0, 98) - 49) * (2.0 * DIV_100);
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_balance_wet_sd(st->parameter[6]);
	pe->fl_dry = calc_balance_dry_sd(st->parameter[6]);
	// mix
	pe->level = calc_sd_level(st->parameter[7]);
}

static void do_sd_s_ds_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_DS_Flanger *pe= (Info_SD_S_DS_Flanger *)ef->info;
	
//	do_od_ds_multi(buf, count, &pe->info_od);
	do_distortion(buf, count, &pe->info_od);
	do_amp_simulator(buf, count, &pe->info_amp);
	effect_panning_mono_stereo(buf, count, pe->od_panl, pe->od_panr);
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_s_ds_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_DS_Delay *pe= (Info_SD_S_DS_Delay *)ef->info;	
//	InfoOverdrive *od = &pe->info_od;
	InfoDistortion *od = &pe->info_od;
	InfoAmpSimulator *amp = &pe->info_amp;
	InfoDelayLR *dly = &pe->info_dly;

	// distortion
	//od->mode = CH_MIX_MONO;
	//od->type = 1; // ds
	//od->amp_sw = 1;	
	//od->amp_type = 2;
	//od->drive = clip_int(st->parameter[0], 0, 127);

	od->mode = CH_MIX_MONO;
	od->bass_od = 0; // gtr/bass
	od->od_type = 1; // od/ds
	od->drive = (double)st->parameter[0] * DIV_127;
	od->tone = 8000; //200 + 100 * st->parameter[1];
	od->level = 1.0;
	od->edge = 0.6;	
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	amp->amp_type = 4;
	amp->cab_type = 5;
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->bright = 0;	
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;
	pe->od_panl = calc_pan_sd_left(st->parameter[1]);	
	pe->od_panr = calc_pan_sd_right(st->parameter[1]);	
	od->level = 1.0; 
	// delay
	dly->mode = CH_MONO_STEREO;
	dly->ldelay = dly->fdelay1 = dly->rdelay = dly->fdelay2 = (double)delay_time_3_table[clip_int(st->parameter[2], 0, 126)];
	dly->feedback = (double)(clip_int(st->parameter[3], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[4]);
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	pe->dly_wet = calc_balance_wet_sd(st->parameter[5]);
	pe->dly_dry = calc_balance_dry_sd(st->parameter[5]);
	// mix
	pe->level = calc_sd_level(st->parameter[6]);
}

static void do_sd_s_ds_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_DS_Delay *pe= (Info_SD_S_DS_Delay *)ef->info;	
	
//	do_od_ds_multi(buf, count, &pe->info_od);
	do_distortion(buf, count, &pe->info_od);
	do_amp_simulator(buf, count, &pe->info_amp);
	send_efx_buffer(ef, buf, count);
	effect_panning_mono_stereo(buf, count, pe->od_panl, pe->od_panr);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_s_enhancer_chorus(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_EH_Chorus *pe= (Info_SD_S_EH_Chorus *)ef->info;
	InfoEnhancer *eh = &pe->info_eh;
	InfoStereoChorus *cho = &pe->info_cho;

	// Enhancer
	eh->mode = CH_STEREO;
	eh->hpf_cutoff = 3200;
	eh->sens = (double)clip_int(st->parameter[0], 0, 127) * DIV_127;	
	pe->eh_wet = (double)clip_int(st->parameter[1], 0, 127) * DIV_127;	
	pe->eh_dry = 1.0;
	// chorus
	cho->mode = CH_MIX_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[2], 0, 125)];
	cho->rate = (double)rate1_table[clip_int(st->parameter[3], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[4], 0, 127));	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_balance_wet_sd(st->parameter[6]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[6]);
	// mix
	pe->level = calc_sd_level(st->parameter[7]);
}

static void do_sd_s_enhancer_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_EH_Chorus *pe= (Info_SD_S_EH_Chorus *)ef->info;

	send_efx_buffer(ef, buf, count);
	do_enhancer_multi(ef->efx_buf, count, &pe->info_eh);
	return_efx_buffer(ef, buf, count, pe->eh_wet, pe->eh_dry, 1.0);
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_s_enhancer_flanger(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_EH_Flanger *pe= (Info_SD_S_EH_Flanger *)ef->info;
	InfoEnhancer *eh = &pe->info_eh;
	InfoStereoChorus *fl = &pe->info_fl;
	
	// Enhancer
	eh->mode = CH_STEREO;
	eh->hpf_cutoff = 3200;
	eh->sens = (double)clip_int(st->parameter[0], 0, 127) * DIV_127;	
	pe->eh_wet = (double)clip_int(st->parameter[1], 0, 127) * DIV_127;	
	pe->eh_dry = 1.0;
	// flanger
	fl->mode = CH_MIX_STEREO;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[2], 0, 125)];
	fl->rate = (double)rate1_table[clip_int(st->parameter[3], 0, 125)];
	fl->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[4], 0, 127));	
	fl->feedback = (double)(clip_int(st->parameter[5], 0, 98) - 49) * (2.0 * DIV_100);
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_balance_wet_sd(st->parameter[6]);
	pe->fl_dry = calc_balance_dry_sd(st->parameter[6]);
	// mix
	pe->level = calc_sd_level(st->parameter[7]);
}

static void do_sd_s_enhancer_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_EH_Flanger *pe= (Info_SD_S_EH_Flanger *)ef->info;

	send_efx_buffer(ef, buf, count);
	do_enhancer_multi(ef->efx_buf, count, &pe->info_eh);
	return_efx_buffer(ef, buf, count, pe->eh_wet, pe->eh_dry, 1.0);
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_s_enhancer_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_EH_Delay *pe= (Info_SD_S_EH_Delay *)ef->info;
	InfoEnhancer *eh = &pe->info_eh;
	InfoDelayLR *dly = &pe->info_dly;

	// Enhancer
	eh->mode = CH_STEREO;
	eh->hpf_cutoff = 3200;
	eh->sens = (double)clip_int(st->parameter[0], 0, 127) * DIV_127;	
	pe->eh_wet = (double)clip_int(st->parameter[1], 0, 127) * DIV_127;	
	pe->eh_dry = 1.0;
	// delay
	dly->mode = CH_MIX_STEREO;
	dly->ldelay = dly->fdelay1 = dly->rdelay = dly->fdelay2 = (double)delay_time_3_table[clip_int(st->parameter[2], 0, 126)];
	dly->feedback = (double)(clip_int(st->parameter[3], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[4]);
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	pe->dly_wet = calc_balance_wet_sd(st->parameter[5]);
	pe->dly_dry = calc_balance_dry_sd(st->parameter[5]);
	// mix
	pe->level = calc_sd_level(st->parameter[6]);
}

static void do_sd_s_enhancer_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_EH_Delay *pe= (Info_SD_S_EH_Delay *)ef->info;

	send_efx_buffer(ef, buf, count);
	do_enhancer_multi(ef->efx_buf, count, &pe->info_eh);
	return_efx_buffer(ef, buf, count, pe->eh_wet, pe->eh_dry, 1.0);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_s_chorus_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{	
	Info_SD_S_Cho_Delay *pe= (Info_SD_S_Cho_Delay *)ef->info;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoDelayLR *dly = &pe->info_dly;
	
	// chorus
	cho->mode = CH_MIX_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[0], 0, 125)];
	cho->rate = (double)rate1_table[clip_int(st->parameter[1], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[2], 0, 127));	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_balance_wet_sd(st->parameter[4]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[4]);
	// delay
	dly->mode = CH_MIX_STEREO;
	dly->ldelay = dly->fdelay1 = dly->rdelay = dly->fdelay2 = (double)delay_time_3_table[clip_int(st->parameter[5], 0, 126)];
	dly->feedback = (double)(clip_int(st->parameter[6], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[7]);
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	pe->dly_wet = calc_balance_wet_sd(st->parameter[8]);
	pe->dly_dry = calc_balance_dry_sd(st->parameter[8]);
	// mix
	pe->level = calc_sd_level(st->parameter[9]);
}

static void do_sd_s_chorus_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_Cho_Delay *pe= (Info_SD_S_Cho_Delay *)ef->info;

	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_s_flanger_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_FL_Delay *pe= (Info_SD_S_FL_Delay *)ef->info;
	InfoStereoChorus *fl = &pe->info_fl;
	InfoDelayLR *dly = &pe->info_dly;

	// flanger
	fl->mode = CH_MIX_STEREO;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[0], 0, 125)];
	fl->rate = (double)rate1_table[clip_int(st->parameter[1], 0, 125)];
	fl->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[2], 0, 127));	
	fl->feedback = (double)(clip_int(st->parameter[3], 0, 98) - 49) * (2.0 * DIV_100);
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_balance_wet_sd(st->parameter[4]);
	pe->fl_dry = calc_balance_dry_sd(st->parameter[4]);
	// delay
	dly->mode = CH_MIX_STEREO;
	dly->ldelay = dly->fdelay1 = dly->rdelay = dly->fdelay2 = (double)delay_time_3_table[clip_int(st->parameter[5], 0, 126)];
	dly->feedback = (double)(clip_int(st->parameter[6], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[7]);
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	pe->dly_wet = calc_balance_wet_sd(st->parameter[8]);
	pe->dly_dry = calc_balance_dry_sd(st->parameter[8]);
	// mix
	pe->level = calc_sd_level(st->parameter[9]);
}

static void do_sd_s_flanger_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_FL_Delay *pe= (Info_SD_S_FL_Delay *)ef->info;	

	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	send_efx_buffer(ef, buf, count);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_s_chorus_flanger(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_Cho_Flanger *pe= (Info_SD_S_Cho_Flanger *)ef->info;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoStereoChorus *fl = &pe->info_fl;	

	// chorus
	cho->mode = CH_MIX_STEREO;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[0], 0, 125)];
	cho->rate = (double)rate1_table[clip_int(st->parameter[1], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[2], 0, 127));	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_balance_wet_sd(st->parameter[3]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[3]);
	// flanger
	fl->mode = CH_MIX_STEREO;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[4], 0, 125)];
	fl->rate = (double)rate1_table[clip_int(st->parameter[5], 0, 125)];
	fl->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[6], 0, 127));	
	fl->feedback = (double)(clip_int(st->parameter[7], 0, 98) - 49) * (2.0 * DIV_100);
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_balance_wet_sd(st->parameter[8]);
	pe->fl_dry = calc_balance_dry_sd(st->parameter[8]);
	// mix
	pe->level = calc_sd_level(st->parameter[9]);
}

static void do_sd_s_chorus_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_Cho_Flanger *pe= (Info_SD_S_Cho_Flanger *)ef->info;
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_p_chorus_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_P_Cho_Delay *pe= (Info_SD_P_Cho_Delay *)ef->info;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoDelayLR *dly = &pe->info_dly;

	// chorus
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[0], 0, 125)];
	cho->rate = (double)rate1_table[clip_int(st->parameter[1], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[2], 0, 127));	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_balance_wet_sd(st->parameter[4]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[4]);
	// delay
	dly->mode = CH_RIGHT;
	dly->ldelay = dly->fdelay1 = dly->rdelay = dly->fdelay2 = (double)delay_time_3_table[clip_int(st->parameter[5], 0, 126)];
	dly->feedback = (double)(clip_int(st->parameter[6], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[7]);
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	pe->dly_wet = calc_balance_wet_sd(st->parameter[8]);
	pe->dly_dry = calc_balance_dry_sd(st->parameter[8]);
	// mix
	pe->level = calc_sd_level(st->parameter[9]);
}

static void do_sd_p_chorus_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_P_Cho_Delay *pe= (Info_SD_P_Cho_Delay *)ef->info;	
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer_right(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_p_flanger_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_P_FL_Delay *pe= (Info_SD_P_FL_Delay *)ef->info;
	InfoStereoChorus *fl = &pe->info_fl;
	InfoDelayLR *dly = &pe->info_dly;

	// flanger
	fl->mode = CH_LEFT;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[0], 0, 125)];
	fl->rate = (double)rate1_table[clip_int(st->parameter[1], 0, 125)];
	fl->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[2], 0, 127));	
	fl->feedback = (double)(clip_int(st->parameter[3], 0, 98) - 49) * (2.0 * DIV_100);
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_balance_wet_sd(st->parameter[4]);
	pe->fl_dry = calc_balance_dry_sd(st->parameter[4]);
	// delay
	dly->mode = CH_RIGHT;
	dly->ldelay = dly->fdelay1 = dly->rdelay = dly->fdelay2 = (double)delay_time_3_table[clip_int(st->parameter[5], 0, 126)];
	dly->feedback = (double)(clip_int(st->parameter[6], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[7]);
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	pe->dly_wet = calc_balance_wet_sd(st->parameter[8]);
	pe->dly_dry = calc_balance_dry_sd(st->parameter[8]);
	// mix
	pe->level = calc_sd_level(st->parameter[9]);
}

static void do_sd_p_flanger_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_P_FL_Delay *pe= (Info_SD_P_FL_Delay *)ef->info;	
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer_left(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
	return_efx_buffer_right(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_p_chorus_flanger(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_P_Cho_Flanger *pe= (Info_SD_P_Cho_Flanger *)ef->info;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoStereoChorus *fl = &pe->info_fl;	

	// chorus
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->filter_type = 0;
	cho->filter_cutoff = 200;
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[0], 0, 125)];
	cho->rate = (double)rate1_table[clip_int(st->parameter[1], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[2], 0, 127));	
	cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	pe->cho_wet = calc_balance_wet_sd(st->parameter[3]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[3]);
	// flanger
	fl->mode = CH_RIGHT;
	fl->phase = 3;
	fl->filter_type = 0;
	fl->filter_cutoff = 200;
	fl->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[4], 0, 125)];
	fl->rate = (double)rate1_table[clip_int(st->parameter[5], 0, 125)];
	fl->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[6], 0, 127));	
	fl->feedback = (double)(clip_int(st->parameter[7], 0, 98) - 49) * (2.0 * DIV_100);
	fl->phase_diff = 90;
	fl->pdelay_dev = 0; // 0~20
	fl->depth_dev = 0; // -20~+20
	fl->pan_dev = 20; // 0~20
	pe->fl_wet = calc_balance_wet_sd(st->parameter[8]);
	pe->fl_dry = calc_balance_dry_sd(st->parameter[8]);
	// mix
	pe->level = calc_sd_level(st->parameter[9]);
}

static void do_sd_p_chorus_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_P_Cho_Flanger *pe= (Info_SD_P_Cho_Flanger *)ef->info;	
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
	return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	do_chorus_ex(ef->efx_buf, count, &pe->info_fl);
	return_efx_buffer_right(ef, buf, count, pe->fl_wet, pe->fl_dry, 1.0);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_stereo_phaser(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Phaser *info = (Info_SD_Phaser *)ef->info;
	InfoPhaser *ph = &info->ph;
	InfoEQ2 *eq = &info->eq; 

	ph->mode = CH_STEREO;
	//type st->parameter[0]
	ph->phase = st->parameter[1] ? 8 : 2;
	//polarity st->parameter[2]
	ph->rate = st->parameter[3] > 200 ? (1.0 / calc_note2_sd(st->parameter[3])) : ((double)clip_int(st->parameter[3], 1, 200) * 0.05);
	ph->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[4], 0, 127));	
	ph->manual = manual_table[clip_int(st->parameter[5], 0, 127)];
	ph->reso = (double)clip_int(st->parameter[6], 0, 127) * DIV_127 * 12.0; // 12dB
	ph->offset = 0.0;
	ph->phase_diff = 0; // deg 0~360
	//xfb st->parameter[7]
	//step rt sw st->parameter[8]
	//step rate st->parameter[9]
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[11]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[12]);
	info->wet = calc_mix_wet_sd(st->parameter[10]);
	info->dry = 1.0; //calc_mix_dry_sd(st->parameter[10]);
	info->level = calc_sd_level(st->parameter[13]);
}

static void do_sd_stereo_phaser(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Phaser *info = (Info_SD_Phaser *)ef->info;
	InfoPhaser *ph = &info->ph;
	InfoEQ2 *eq = &info->eq; 
		
	send_efx_buffer(ef, buf, count);
	do_phaser_multi(ef->efx_buf, count, ph);
	return_efx_buffer_left(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_keysync_flanger(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_KeysyncFlanger *info = (Info_SD_KeysyncFlanger *)ef->info;
	InfoStereoChorus *cho = &info->fl;	
	InfoEQ2 *eq = &info->eq; 

	cho->mode = CH_STEREO;
	cho->phase = 3;
	cho->filter_type = clip_int(st->parameter[0], 0, 2);
	cho->filter_cutoff = EQ_GAIN_SD(st->parameter[1]);
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[2], 0, 125)];
	cho->rate = st->parameter[3] > 200 ? (1.0 / calc_note2_sd(st->parameter[3])) : ((double)clip_int(st->parameter[3], 1, 200) * 0.05);
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[4], 0, 127));
	cho->feedback = (double)(clip_int(st->parameter[5], 0, 98) - 49) * (2.0 * DIV_100);
	// step rt sw st->parameter[6]
	// step rate st->parameter[7]
	cho->phase_diff = (double)2.0 * clip_int(st->parameter[8], 0, 0x5A); // 0~180
	// keys sw st->parameter[9]
	// keys thres st->parameter[10]
	// keys phase st->parameter[11]
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[12]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[13]);
	info->wet = calc_balance_wet_sd(st->parameter[14]);
	info->dry = calc_balance_dry_sd(st->parameter[14]);
	info->level = calc_sd_level(st->parameter[15]);
}

static void do_sd_keysync_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_KeysyncFlanger *info = (Info_SD_KeysyncFlanger *)ef->info;
	InfoStereoChorus *cho = &info->fl;
	InfoEQ2 *eq = &info->eq; 
	
	send_efx_buffer(ef, buf, count);
	do_chorus_ex(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_formant_filter(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_FormantFilter *info = (Info_SD_FormantFilter *)ef->info;
	InfoHumanizer *hm = &info->hm;
	InfoEQ2 *eq = &info->eq; 

	hm->mode = CH_LEFT;
	hm->od_sw = st->parameter[0] ? 1 : 0;
	hm->drive = 1.0 + (double)st->parameter[1] * DIV_127 * 3.0;
	hm->vowel = clip_int(st->parameter[2], 0, 4);
	//vowel2 clip_int(st->parameter[3], 0, 4);
	//flt rate st->parameter[4]
	//flt depth st->parameter[5]
	//keys sw st->parameter[6]
	//keys thres st->parameter[7]
	//flt manual st->parameter[8]
	hm->accel = 200.0; // ms 1000ms~7.8ms
	eq->mode = CH_LEFT;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[9]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[10]);
	info->panl = calc_pan_sd_left(st->parameter[11]);
	info->panr = calc_pan_sd_right(st->parameter[11]);
	info->level = calc_sd_level(st->parameter[12]);
}

static void do_sd_formant_filter(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_FormantFilter *info = (Info_SD_FormantFilter *)ef->info;
	InfoHumanizer *hm = &info->hm;
	InfoEQ2 *eq = &info->eq; 

	effect_mix_mono(buf, count);
	do_humanizer(buf, count, hm);
	do_eq2_multi(buf, count, eq);
	effect_panning_mono_stereo(buf, count, info->panl, info->panr);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_ring_modulator(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_RingModulator *info = (Info_SD_RingModulator *)ef->info;
	InfoRingModulator *rm = &info->rm;
	InfoEQ2 *eq = &info->eq;	
		
	// ring modulator
	rm->mode = CH_STEREO;
	rm->freq = (double)freq_table[clip_int(st->parameter[0], 0, 127)] * DIV_1000;
	//mod source st->parameter[1]
	//mod monitor st->parameter[2]
	//sens  st->parameter[3]
	//porality  st->parameter[4]
	rm->lfo_sw = 1; // lfo off
	//eq
	eq->mode = CH_STEREO;	
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[5]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[6]);
	info->wet = calc_balance_wet_sd(st->parameter[8]);
	info->dry = calc_balance_dry_sd(st->parameter[8]);
	info->level = calc_sd_level(st->parameter[12]);
}

static void do_sd_ring_modulator(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_RingModulator *info = (Info_SD_RingModulator *)ef->info;
	InfoRingModulator *rm = &info->rm;
	InfoEQ2 *eq = &info->eq;
	
	send_efx_buffer(ef, buf, count);
	do_ring_modulator_multi(ef->efx_buf, count, rm);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);	
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_multitap_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_MultiTapDelay *info = (Info_SD_MultiTapDelay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;
	
	dly->mode = CH_MIX_STEREO;
	dly->tap = 4;
	dly->dtime[0] = st->parameter[0] > 1800 ? calc_note2_sd(st->parameter[0] - 1800) * 1000 : st->parameter[0];
	dly->dtime[1] = st->parameter[0] > 1800 ? calc_note2_sd(st->parameter[0] - 1800) * 1000 : st->parameter[0];
	dly->dtime[2] = st->parameter[0] > 1800 ? calc_note2_sd(st->parameter[0] - 1800) * 1000 : st->parameter[0];
	dly->dtime[3] = st->parameter[0] > 1800 ? calc_note2_sd(st->parameter[0] - 1800) * 1000 : st->parameter[0];
	dly->dtime[4] = dly->dtime[0]; // [tap] for feedback_delay // dtime[0]と同じ
	dly->pan[0] = clip_int(st->parameter[4], 0, 127);
	dly->pan[1] = clip_int(st->parameter[5], 0, 127);
	dly->pan[2] = clip_int(st->parameter[6], 0, 127);
	dly->pan[3] = clip_int(st->parameter[7], 0, 127);
	dly->pan[4] = 0x40; // [tap] for feedback_delay
	dly->dlevel[0] = calc_option_level(st->parameter[8]);
	dly->dlevel[1] = calc_option_level(st->parameter[9]);
	dly->dlevel[2] = calc_option_level(st->parameter[10]);
	dly->dlevel[3] = calc_option_level(st->parameter[11]);
	dly->feedback = (double)(clip_int(st->parameter[12], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[13]);
	//eq
	eq->mode = CH_STEREO;	
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[14]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[15]);
	info->wet = calc_balance_wet_sd(st->parameter[16]);
	info->dry = calc_balance_dry_sd(st->parameter[16]);
	info->level = calc_sd_level(st->parameter[17]);
}

static void do_sd_multitap_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_MultiTapDelay *info = (Info_SD_MultiTapDelay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;

	send_efx_buffer(ef, buf, count);
	do_multi_tap_delay(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);	
}

static void conv_sd_reverse_delay(struct mfx_effect_sd_t *st, EffectList *ef){}
static void do_sd_reverse_delay(DATA_T *buf, int32 count, EffectList *ef){}
static void conv_sd_shuffle_delay(struct mfx_effect_sd_t *st, EffectList *ef){}
static void do_sd_shuffle_delay(DATA_T *buf, int32 count, EffectList *ef){}

static void conv_sd_3d_delay(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_3DDelay *info = (Info_SD_3DDelay *)ef->info;
	Info3DMultiTapDelay *dly = &info->dly;
	InfoEQ2 *eq = &info->eq; 

	dly->mode = CH_MIX_STEREO;
	dly->tap = 3;
	dly->dtime[1] = st->parameter[0] > 1800 ? calc_note2_sd(st->parameter[0] - 1800) * 1000 : st->parameter[0];
	dly->dtime[2] = st->parameter[1] > 1800 ? calc_note2_sd(st->parameter[1] - 1800) * 1000 : st->parameter[1];
	dly->dtime[0] = st->parameter[2] > 1800 ? calc_note2_sd(st->parameter[2] - 1800) * 1000 : st->parameter[2];
	dly->dtime[3] = dly->dtime[0]; // [tap] for feedback_delay // dtime[0]と同じ
	dly->pan[0] = 0x40;
	dly->pan[1] = 0x00;
	dly->pan[2] = 0x7F;
	dly->pan[3] = 0x40; // [tap] for feedback_delay
	dly->dlevel[1] = calc_option_level(st->parameter[3]);
	dly->dlevel[2] = calc_option_level(st->parameter[4]);
	dly->dlevel[0] = calc_option_level(st->parameter[5]);
	dly->feedback = (double)(clip_int(st->parameter[6], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[7]);
	dly->out = st->parameter[8] ? 1 : 0; // Speaker/Phones
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[9]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[10]);
	info->wet = calc_balance_wet_sd(st->parameter[11]);
	info->dry = calc_balance_dry_sd(st->parameter[11]);
	info->level = calc_sd_level(st->parameter[12]);
}

static void do_sd_3d_delay(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_3DDelay *info = (Info_SD_3DDelay *)ef->info;
	Info3DMultiTapDelay *dly = &info->dly;
	InfoEQ2 *eq = &info->eq; 

	send_efx_buffer(ef, buf, count);
	do_3d_multi_tap_delay(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_3pitch_shifter(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_3VoicePitchShifter *info = (Info_SD_3VoicePitchShifter *)ef->info;
	InfoPitchShifter_core *ps1 = &info->ps1, *ps2 = &info->ps2, *ps3 = &info->ps3;
	double level1, level2, level3;

	ps1->ps_delay_ms = ps2->ps_delay_ms = ps3->ps_delay_ms = PS_CF_DELAY + clip_int(st->parameter[0], 0x00, 0x04) * 4; // PS_CF_DELAY + 16ms
	ps1->pitch_cent = (double)(clip_int(st->parameter[1], 0, 36) - 12) * 100 + (clip_int(st->parameter[4], 0, 100) - 50) * 2;
	ps2->pitch_cent = (double)(clip_int(st->parameter[2], 0, 36) - 12) * 100 + (clip_int(st->parameter[5], 0, 100) - 50) * 2;
	ps3->pitch_cent = (double)(clip_int(st->parameter[3], 0, 36) - 12) * 100 + (clip_int(st->parameter[6], 0, 100) - 50) * 2;
	ps1->pre_delay_ms = (double)delay_time_3_table[clip_int(st->parameter[7], 0, 126)];
	ps2->pre_delay_ms = (double)delay_time_3_table[clip_int(st->parameter[8], 0, 126)];
	ps3->pre_delay_ms = (double)delay_time_3_table[clip_int(st->parameter[9], 0, 126)];
	ps1->feedback = (double)(clip_int(st->parameter[10], 0, 98) - 49) * (2.0 * DIV_100);
	ps2->feedback = (double)(clip_int(st->parameter[11], 0, 98) - 49) * (2.0 * DIV_100);
	ps3->feedback = (double)(clip_int(st->parameter[12], 0, 98) - 49) * (2.0 * DIV_100);	
	level1 = calc_option_level(clip_int(st->parameter[16], 0, 127));
	level2 = calc_option_level(clip_int(st->parameter[17], 0, 127));
	level3 = calc_option_level(clip_int(st->parameter[18], 0, 127));
	info->pan1l = calc_pan_sd_left(st->parameter[13]) * level1;
	info->pan1r = calc_pan_sd_right(st->parameter[13]) * level1;
	info->pan2l = calc_pan_sd_left(st->parameter[14]) * level2;
	info->pan2r = calc_pan_sd_right(st->parameter[14]) * level2;
	info->pan3l = calc_pan_sd_left(st->parameter[15]) * level3;
	info->pan3r = calc_pan_sd_right(st->parameter[15]) * level3;
	info->wet = calc_balance_wet_sd(st->parameter[19]);
	info->dry = calc_balance_dry_sd(st->parameter[19]);
	info->level = calc_sd_level(st->parameter[20]);
}

static void do_sd_3pitch_shifter(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_3VoicePitchShifter *info = (Info_SD_3VoicePitchShifter *)ef->info;
	InfoPitchShifter_core *ps1 = &info->ps1, *ps2 = &info->ps2, *ps3 = &info->ps3;
	int32 i;
	DATA_T tmp1, tmp2, tmp3;
	
	if (count == MAGIC_INIT_EFFECT_INFO) {	
		init_pitch_shifter_core(&info->ps1);
		init_pitch_shifter_core(&info->ps2);
		init_pitch_shifter_core(&info->ps2);
		if(!info->ps1.init_flg || !info->ps2.init_flg || !info->ps3.init_flg)
			info->init_flg = 0;
		else
			info->init_flg = 1;
		return;
	} else if(count == MAGIC_FREE_EFFECT_INFO) {
		uninit_pitch_shifter_core(&info->ps1);	
		uninit_pitch_shifter_core(&info->ps2);	
		uninit_pitch_shifter_core(&info->ps3);	
		info->init_flg = 0;
		return;
	} else if(count < 0)
		return;
	if(!info->init_flg)
		return;
	send_efx_buffer(ef, buf, count);
	for(i = 0; i < count; i++){
		tmp1 = tmp2 = tmp3 = (ef->efx_buf[i] + ef->efx_buf[i + 1]) * DIV_MIX_LEVEL;
		do_pitch_shifter_core(&tmp1, &info->ps1);
		do_pitch_shifter_core(&tmp2, &info->ps2);
		do_pitch_shifter_core(&tmp2, &info->ps3);
		ef->efx_buf[i] = tmp1 * info->pan1l + tmp2 * info->pan2l + tmp3 * info->pan3l;
		i++;
		ef->efx_buf[i] = tmp1 * info->pan1r + tmp2 * info->pan2r + tmp3 * info->pan3r;
	}	
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_sd_lofi_compress(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_LoFi_Compress *info = (Info_SD_LoFi_Compress *)ef->info;
	InfoLoFi *lf = &info->lf;
	InfoEQ2 *eq = &info->eq; 
	
	lf->mode = CH_MIX_MONO;
	lf->level_in = otd.sdefx_CustomLFLvIn;
	lf->level_out = otd.sdefx_CustomLFLvOut;
	lf->sr_rate = 32000;
	lf->pre_fil_type = st->parameter[0] ? FILTER_LPF_BW : FILTER_NONE; // off,lpf
	lf->pre_fil_freq = 12000;
	lf->pre_fil_reso = 0.0;
	lf->bit_length = 12 - clip_int(st->parameter[1], 0, 8);	
	// postfilter1 type st->parameter[2]
	lf->post_fil_type = st->parameter[3] >= 2 ? FILTER_LPF_BW : st->parameter[3] == 1 ? FILTER_BPF12_3 : FILTER_NONE; // off,lpf
	lf->post_fil_freq = EQ_FREQb_SD(st->parameter[4]);
	lf->post_fil_reso = 0.0;		
	lf->nz_gen = 0; // noise off
	eq->mode = CH_LEFT;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[6]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[7]);
	info->wet = calc_balance_wet_sd(st->parameter[5]);
	info->dry = calc_balance_dry_sd(st->parameter[5]);
	info->panl = calc_pan_sd_left(st->parameter[8]);
	info->panr = calc_pan_sd_right(st->parameter[8]);
	info->level = calc_sd_level(st->parameter[9]);
}

static void do_sd_lofi_compress(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_LoFi_Compress *info = (Info_SD_LoFi_Compress *)ef->info;
	InfoLoFi *lf = &info->lf;
	InfoEQ2 *eq = &info->eq; 
	
	send_efx_buffer(ef, buf, count); 
	do_lofi(ef->efx_buf, count, lf);
	do_eq2_multi(ef->efx_buf, count, eq);
	effect_panning_mono_stereo(ef->efx_buf, count, info->panl, info->panr);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level); 
}

static void conv_sd_lofi_noise(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_LoFi_Noise *info = (Info_SD_LoFi_Noise *)ef->info;
	InfoLoFi *lf = &info->lf;
	InfoEQ2 *eq = &info->eq; 

	lf->mode = CH_MIX_MONO;
	lf->level_in = otd.sdefx_CustomLFLvIn;
	lf->level_out = otd.sdefx_CustomLFLvOut;
	lf->sr_rate = 32000;
	lf->bit_length = 12 - clip_int(st->parameter[0], 0, 8);	
	lf->pre_fil_type = FILTER_NONE; // off
	lf->pre_fil_freq = 0;
	lf->pre_fil_reso = 0.0;
	switch(st->parameter[1]){
	default:
	case 0: // off
		lf->post_fil_type = FILTER_NONE;
		break;
	case 1: // lpf
		lf->post_fil_type = FILTER_LPF_BW;
		break;
	case 2: // hpf
		lf->post_fil_type = FILTER_HPF_BW;
		break;

	}
	lf->post_fil_freq = EQ_FREQ_SD(st->parameter[2]);
	lf->post_fil_reso = 0.0;		
	lf->nz_gen = 1; // noise on
	lf->rdetune = st->parameter[3];
	//lf->rnz_wet = calc_option_wet(st->parameter[4]);
	//lf->rnz_dry = calc_option_dry(st->parameter[4]);
	lf->rnz_lev = calc_option_level(st->parameter[4]);
	lf->wp_sel = 1;
	lf->wp_freq = 1000;
	//lf->wp_wet = calc_option_wet(st->parameter[7]);
	//lf->wp_dry = calc_option_dry(st->parameter[7]);
	lf->wp_level = calc_option_level(st->parameter[4]);
	lf->disc_type = clip_int(st->parameter[5], 0, 3);
	lf->disc_freq = EQ_FREQb_SD(st->parameter[6]);
	//lf->discnz_wet = calc_option_wet(st->parameter[10]);
	//lf->discnz_dry = calc_option_dry(st->parameter[10]);
	lf->discnz_lev = calc_option_level(st->parameter[7]);
	lf->hum_type = 0;
	lf->hum_freq = 2400;
	//lf->hum_wet = calc_option_wet(st->parameter[13]);
	//lf->hum_dry = calc_option_dry(st->parameter[13]);
	lf->hum_level = 0.0;
	eq->mode = CH_LEFT;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[9]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[10]);
	info->wet = calc_balance_wet_sd(st->parameter[8]);
	info->dry = calc_balance_dry_sd(st->parameter[8]);
	info->panl = calc_pan_sd_left(st->parameter[11]);
	info->panr = calc_pan_sd_right(st->parameter[11]);
	info->level = calc_sd_level(st->parameter[12]);
}

static void do_sd_lofi_noise(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_LoFi_Noise *info = (Info_SD_LoFi_Noise *)ef->info;
	InfoLoFi *lf = &info->lf;
	InfoEQ2 *eq = &info->eq; 
	
	send_efx_buffer(ef, buf, count); 
	do_lofi(ef->efx_buf, count, lf);
	do_eq2_multi(ef->efx_buf, count, eq);
	effect_panning_mono_stereo(ef->efx_buf, count, info->panl, info->panr);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_sd_speaker_simulator(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_SpeakerSimulator *info = (Info_SD_SpeakerSimulator *)ef->info;
	InfoAmpSimulator *amp = &info->amp;
	
	amp->mode = CH_STEREO;
	amp->amp_sw = 0; // off
	amp->amp_type = 0;
	amp->gain1 = 0.5;
	amp->gain2 = 0.5;
	amp->eq1_gain = clip_int(st->parameter[5] - 64, -64, 64) * DIV_64 * 6.0; // db
	amp->eq2_gain = clip_int(st->parameter[6] - 64, -64, 64) * DIV_64 * 6.0; // db
	amp->eq3_gain = clip_int(st->parameter[7] - 64, -64, 64) * DIV_64 * 6.0; // db
	amp->eq4_gain = clip_int(st->parameter[8] - 64, -64, 64) * DIV_64 * 6.0; // db
	amp->bright = st->parameter[9] ? 1 : 0;	
	amp->cab_sw = 1; // on
	amp->cab_type = clip_int(st->parameter[0], 0, 15) + 1;
	amp->mic_pos = clip_int(st->parameter[1], 0, 2);
	amp->mic_level = calc_option_level(clip_int(st->parameter[2], 0, 127));
	amp->mic_direct = calc_option_level(clip_int(st->parameter[3], 0, 127));
	info->level = calc_sd_level(clip_int(st->parameter[4], 0, 127));
}

static void do_sd_speaker_simulator(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_SpeakerSimulator *info = (Info_SD_SpeakerSimulator *)ef->info;
	InfoAmpSimulator *amp = &info->amp;
		
	do_amp_simulator(buf, count, amp);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_overdrive2(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Overdrive *info = (Info_SD_Overdrive *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoDistortion *od = &info->od;
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
	
	//od->mode = CH_LEFT;
	//od->type = 0; // od
	//od->drive = clip_int(st->parameter[0], 0, 127);
	////od->tone = st->parameter[1];
	//od->amp_sw = st->parameter[3] ? 1 : 0;
	//od->amp_type = clip_int(st->parameter[4], 0, 3);
	//od->level = 1.0; 	

	od->mode = CH_LEFT;
	od->bass_od = 0; // gtr/bass
	od->od_type = 0; // od/ds
	od->drive = (double)st->parameter[0] * DIV_127;
	od->tone = 200 + 100 * st->parameter[1];
	od->level = 1.0;
	od->edge = 0.6;	
	info->amp_sw = st->parameter[9] ? 1 : 0;
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	switch(st->parameter[2]){
	default:
	case 0: // small
		amp->amp_type = 2;
		amp->cab_type = 1;
		break;
	case 1: // built in
		amp->amp_type = 4;
		amp->cab_type = 5;
		break;
	case 2: // 2 stack
		amp->amp_type = 8;
		amp->cab_type = 15;
		break;
	case 3: // 3 stack
		amp->amp_type = 9;
		amp->cab_type = 16;
		break;
	}
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->bright = 0;	
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;

	eq->mode = CH_LEFT;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[5]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[6]);
	info->panl = calc_pan_sd_left(st->parameter[2]);
	info->panr = calc_pan_sd_right(st->parameter[2]);
	info->level = calc_sd_level(clip_int(st->parameter[5], 0, 127));
}

static void do_sd_overdrive2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Overdrive *info = (Info_SD_Overdrive *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoDistortion *od = &info->od;
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
		
	effect_mix_mono(buf, count);
//	do_od_ds_multi(buf, count, od);
	do_distortion(buf, count, od);		
	if(info->amp_sw)
		do_amp_simulator(buf, count, amp);
	do_eq2_multi(buf, count, eq);
	effect_panning_mono_stereo(buf, count, info->panl, info->panr);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_distortion2(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Overdrive *info = (Info_SD_Overdrive *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoDistortion *od = &info->od;
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
	
	od->mode = CH_LEFT;
	//od->type = 1; // ds
	//od->drive = clip_int(st->parameter[0], 0, 127);
	////od->tone = st->parameter[1];
	//od->amp_sw = st->parameter[3] ? 1 : 0;
	//od->amp_type = clip_int(st->parameter[4], 0, 3);
	//od->level = 1.0; 	
	//eq->mode = CH_LEFT;
	//eq->low_freq = 400;
	//eq->low_gain = EQ_GAIN_SD(st->parameter[5]);
	//eq->high_freq = 4000;
	//eq->high_gain = EQ_GAIN_SD(st->parameter[6]);

	od->mode = CH_LEFT;
	od->bass_od = 0; // gtr/bass
	od->od_type = 1; // od/ds
	od->drive = (double)st->parameter[0] * DIV_127;
	od->tone = 200 + 100 * st->parameter[1];
	od->level = 1.0;
	od->edge = 0.6;	
	info->amp_sw = st->parameter[9] ? 1 : 0;
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	switch(st->parameter[2]){
	default:
	case 0: // small
		amp->amp_type = 2;
		amp->cab_type = 1;
		break;
	case 1: // built in
		amp->amp_type = 4;
		amp->cab_type = 5;
		break;
	case 2: // 2 stack
		amp->amp_type = 8;
		amp->cab_type = 15;
		break;
	case 3: // 3 stack
		amp->amp_type = 9;
		amp->cab_type = 16;
		break;
	}
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->bright = 0;	
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;

	info->panl = calc_pan_sd_left(st->parameter[2]);
	info->panr = calc_pan_sd_right(st->parameter[2]);
	info->level = calc_sd_level(clip_int(st->parameter[5], 0, 127));
}

static void do_sd_distortion2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Overdrive *info = (Info_SD_Overdrive *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoDistortion *od = &info->od;
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
		
	effect_mix_mono(buf, count);
//	do_od_ds_multi(buf, count, od);
	do_distortion(buf, count, od);		
	if(info->amp_sw)
		do_amp_simulator(buf, count, amp);
	do_eq2_multi(buf, count, eq);
	effect_panning_mono_stereo(buf, count, info->panl, info->panr);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_st_compressor(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Compressor *info = (Info_SD_Compressor *)ef->info;
	InfoCompressor *cmp = &info->cmp;
	InfoEQ2 *eq = &info->eq; 

	cmp->mode = CH_STEREO;
	cmp->sustain = mix_double ((double)st->parameter[0] * DIV_127, 10, 500); // 10ms-500ms
	cmp->attak = mix_double ((double)st->parameter[1] * DIV_127, 10, 500); // 10ms-500ms
	cmp->post_gain = cmp_lmt_gain_table_gs[clip_int(st->parameter[2], 0, 3)];; // dB
	cmp->pre_gain = 0.0; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 0.5; // ratio? 1/2
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[3]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[4]);
	info->level = calc_gs_level(st->parameter[5]);
}

static void do_sd_st_compressor(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Compressor *info = (Info_SD_Compressor *)ef->info;
	InfoCompressor *cmp = &info->cmp;
	InfoEQ2 *eq = &info->eq; 

	do_compressor_multi(buf, count, cmp);
	do_eq2_multi(buf, count, eq);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_st_limiter(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Limiter *info = (Info_SD_Limiter *)ef->info;
	InfoLimiter *lmt = &info->lmt;
	InfoEQ2 *eq = &info->eq; 

	lmt->mode = CH_STEREO;
	lmt->threshold = (double)clip_int(st->parameter[0], 1, 127) * DIV_127;
	lmt->release = mix_double ((double)st->parameter[1] * DIV_127, 10, 200); // 10ms-200ms
	lmt->ratio = limiter_ratio_table_gs[clip_int(st->parameter[2], 0, 3)];
	lmt->ahead = 10; // 10ms
	lmt->pre_gain = 0;
	lmt->post_gain = cmp_lmt_gain_table_gs[clip_int(st->parameter[3], 0, 3)];
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[4]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[5]);
	info->level = calc_gs_level(st->parameter[6]);
}

static void do_sd_st_limiter(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Limiter *info = (Info_SD_Limiter *)ef->info;
	InfoLimiter *lmt = &info->lmt;
	InfoEQ2 *eq = &info->eq; 
	
	do_limiter_multi(buf, count, lmt);
	do_eq2_multi(buf, count, eq);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_gate(struct mfx_effect_sd_t *st, EffectList *ef){}
static void do_sd_gate(DATA_T *buf, int32 count, EffectList *ef){}
static void conv_sd_slicer(struct mfx_effect_sd_t *st, EffectList *ef){}
static void do_sd_slicer(DATA_T *buf, int32 count, EffectList *ef){}
static void conv_sd_isolator(struct mfx_effect_sd_t *st, EffectList *ef){}
static void do_sd_isolator(DATA_T *buf, int32 count, EffectList *ef){}

static void conv_sd_3d_chorus(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_3DChorus *info = (Info_SD_3DChorus *)ef->info;
	Info3DChorus *cho = &info->cho;	
	InfoEQ2 *eq = &info->eq; 

	cho->mode = CH_MIX_STEREO;
	cho->phase = 3;
	cho->filter_type = clip_int(st->parameter[0], 0, 2);
	cho->filter_cutoff = EQ_FREQ_SD(st->parameter[1]);
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[2], 0, 125)];
	cho->rate = st->parameter[3] > 200 ? (1.0 / calc_note2_sd(st->parameter[3])) : ((double)clip_int(st->parameter[3], 1, 200) * 0.05);
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[4], 0, 127));
	cho->phase_diff = (double)2.0 * clip_int(st->parameter[5], 0, 0x5A); // 0~180
	cho->feedback = 0.0;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	cho->out = st->parameter[6] ? 1 : 0; // Speaker/Phones
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[7]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[8]);
	info->wet = calc_balance_wet_sd(st->parameter[9]);
	info->dry = calc_balance_dry_sd(st->parameter[9]);
	info->level = calc_sd_level(st->parameter[10]);
}

static void do_sd_3d_chorus(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_3DChorus *info = (Info_SD_3DChorus *)ef->info;
	Info3DChorus *cho = &info->cho;
	InfoEQ2 *eq = &info->eq; 
	
	send_efx_buffer(ef, buf, count);
	do_3d_chorus(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_3d_flanger(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_3DChorus *info = (Info_SD_3DChorus *)ef->info;
	Info3DChorus *cho = &info->cho;	
	InfoEQ2 *eq = &info->eq; 

	cho->mode = CH_MIX_STEREO;
	cho->phase = 3;
	cho->filter_type = clip_int(st->parameter[0], 0, 2);
	cho->filter_cutoff = EQ_FREQ_SD(st->parameter[1]);
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[2], 0, 125)];
	cho->rate = st->parameter[3] > 200 ? (1.0 / calc_note2_sd(st->parameter[3])) : ((double)clip_int(st->parameter[3], 1, 200) * 0.05);
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[4], 0, 127));
	cho->feedback = (double)(clip_int(st->parameter[5], 0, 98) - 49) * (2.0 * DIV_100);
	// step rate switch st->parameter[6]
	// step rate rate st->parameter[7]
	cho->phase_diff = (double)2.0 * clip_int(st->parameter[8], 0, 0x5A); // 0~180
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	cho->out = st->parameter[9] ? 1 : 0; // Speaker/Phones
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[10]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[11]);
	info->wet = calc_balance_wet_sd(st->parameter[12]);
	info->dry = calc_balance_dry_sd(st->parameter[12]);
	info->level = calc_sd_level(st->parameter[13]);
}
static void do_sd_3d_flanger(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_3DChorus *info = (Info_SD_3DChorus *)ef->info;
	Info3DChorus *cho = &info->cho;
	InfoEQ2 *eq = &info->eq; 
	
	send_efx_buffer(ef, buf, count);
	do_3d_chorus(ef->efx_buf, count, cho);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_tremolo(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Tremolo *info = (Info_SD_Tremolo *)ef->info;
	InfoTremolo *trm = &info->trm;
	InfoEQ2 *eq = &info->eq; 

	trm->mode = CH_STEREO;
	trm->type = 0; // trem
	trm->phase = 0; // deg
	trm->wave = lfo_wave_table_gs[clip_int(st->parameter[0], 0, 4)];
	trm->rate = st->parameter[1] > 200 ? (1.0 / calc_note2_sd(st->parameter[1])) : ((double)clip_int(st->parameter[1], 1, 200) * 0.05);
	trm->depth = (double)clip_int(st->parameter[2], 0, 127) * DIV_127;
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[3]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[4]);
	info->level = calc_sd_level(st->parameter[5]);
}

static void do_sd_tremolo(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Tremolo *info = (Info_SD_Tremolo *)ef->info;
	InfoTremolo *trm = &info->trm;
	InfoEQ2 *eq = &info->eq; 

	do_tremolo_autopan(buf, count, trm);
	effect_level_stereo(buf, count, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_auto_pan(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Tremolo *info = (Info_SD_Tremolo *)ef->info;
	InfoTremolo *trm = &info->trm;
	InfoEQ2 *eq = &info->eq; 

	trm->mode = CH_STEREO;
	trm->type = 1; // autopan
	trm->phase = 180; // deg
	trm->wave = lfo_wave_table_gs[clip_int(st->parameter[0], 0, 4)];
	trm->rate = st->parameter[1] > 200 ? (1.0 / calc_note2_sd(st->parameter[1])) : ((double)clip_int(st->parameter[1], 1, 200) * 0.05);
	trm->depth = (double)clip_int(st->parameter[2], 0, 127) * DIV_127;
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[3]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[4]);
	info->level = calc_sd_level(st->parameter[5]);
}

static void do_sd_auto_pan(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Tremolo *info = (Info_SD_Tremolo *)ef->info;
	InfoTremolo *trm = &info->trm;
	InfoEQ2 *eq = &info->eq; 

	do_tremolo_autopan(buf, count, trm);
	effect_level_stereo(buf, count, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_stereo_phaser2(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Phaser *info = (Info_SD_Phaser *)ef->info;
	InfoPhaser *ph = &info->ph;
	InfoEQ2 *eq = &info->eq; 

	ph->mode = CH_STEREO;
	//type st->parameter[0]
	ph->phase = st->parameter[1] ? 8 : 2;
	//polarity st->parameter[2]
	ph->rate = st->parameter[3] > 200 ? (1.0 / calc_note2_sd(st->parameter[3])) : ((double)clip_int(st->parameter[3], 1, 200) * 0.05);
	ph->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[4], 0, 127));	
	ph->manual = manual_table[clip_int(st->parameter[5], 0, 127)];
	ph->reso = (double)clip_int(st->parameter[6], 0, 127) * DIV_127 * 12.0; // 12dB
	ph->offset = 0.0;
	ph->phase_diff = 0; // deg 0~360
	//xfb st->parameter[7]
	//step rt sw st->parameter[8]
	//step rate st->parameter[9]
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[11]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[12]);
	info->wet = calc_mix_wet_sd(st->parameter[10]);
	info->dry = 1.0; //calc_mix_dry_sd(st->parameter[10]);
	info->level = calc_sd_level(st->parameter[13]);
}

static void do_sd_stereo_phaser2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Phaser *info = (Info_SD_Phaser *)ef->info;
	InfoPhaser *ph = &info->ph;
	InfoEQ2 *eq = &info->eq; 
		
	send_efx_buffer(ef, buf, count);
	do_phaser_multi(ef->efx_buf, count, ph);
	return_efx_buffer_left(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_stereo_auto_wah(struct mfx_effect_sd_t *st, EffectList *ef)
{	
	Info_SD_AutoWah *info = (Info_SD_AutoWah *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoEQ2 *eq = &info->eq; 

	aw->mode = CH_STEREO;
	aw->type = st->parameter[0] ? 1 : 0;
	aw->rate = st->parameter[1] > 200 ? (1.0 / calc_note2_sd(st->parameter[1])) : ((double)clip_int(st->parameter[1], 1, 200) * 0.05);
	aw->depth = (double)st->parameter[2] * DIV_127;
	aw->sens = calc_auto_wah_sens_gs(st->parameter[3]);	
	aw->release = 100.0; // ms
	aw->manual = calc_auto_wah_manual_gs(st->parameter[4]);
	aw->peak = calc_auto_wah_peak_gs(st->parameter[5]);
	aw->pol = st->parameter[6] ? 1 : 0;
	aw->lfo_sw = 1; // on
	aw->sens_sw = 1; // on
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[8]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[9]);
	info->level = calc_sd_level(st->parameter[10]);
}

static void do_sd_stereo_auto_wah(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_AutoWah *info = (Info_SD_AutoWah *)ef->info;
	InfoAutoWah *aw = &info->aw;
	InfoEQ2 *eq = &info->eq; 
	
	do_auto_wah_multi(buf, count, aw);
	do_eq2_multi(buf, count, eq);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_st_formant_filter(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_FormantFilter *info = (Info_SD_FormantFilter *)ef->info;
	InfoHumanizer *hm = &info->hm;
	InfoEQ2 *eq = &info->eq; 

	hm->mode = CH_STEREO;
	hm->od_sw = st->parameter[0] ? 1 : 0;
	hm->drive = 1.0 + (double)st->parameter[1] * DIV_127 * 3.0;
	hm->vowel = clip_int(st->parameter[2], 0, 4);
	//vowel2 clip_int(st->parameter[3], 0, 4);
	//flt rate st->parameter[4]
	//flt depth st->parameter[5]
	//keys sw st->parameter[6]
	//keys thres st->parameter[7]
	//flt manual st->parameter[8]
	hm->accel = 200.0; // ms 1000ms~7.8ms
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[10]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[11]);
	info->level = calc_sd_level(st->parameter[12]);
}

static void do_sd_st_formant_filter(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_FormantFilter *info = (Info_SD_FormantFilter *)ef->info;
	InfoHumanizer *hm = &info->hm;
	InfoEQ2 *eq = &info->eq; 

	do_humanizer(buf, count, hm);
	do_eq2_multi(buf, count, eq);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_multitap_delay2(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_MultiTapDelay *info = (Info_SD_MultiTapDelay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;
	
	dly->mode = CH_MIX_STEREO;
	dly->tap = 4;
	dly->dtime[0] = st->parameter[0] > 3000 ? calc_note2_sd(st->parameter[0] - 3000) * 1000 : st->parameter[0];
	dly->dtime[1] = st->parameter[0] > 3000 ? calc_note2_sd(st->parameter[0] - 3000) * 1000 : st->parameter[0];
	dly->dtime[2] = st->parameter[0] > 3000 ? calc_note2_sd(st->parameter[0] - 3000) * 1000 : st->parameter[0];
	dly->dtime[3] = st->parameter[0] > 3000 ? calc_note2_sd(st->parameter[0] - 3000) * 1000 : st->parameter[0];
	dly->dtime[4] = dly->dtime[0]; // [tap] for feedback_delay // dtime[0]と同じ
	dly->pan[0] = clip_int(st->parameter[4], 0, 127);
	dly->pan[1] = clip_int(st->parameter[5], 0, 127);
	dly->pan[2] = clip_int(st->parameter[6], 0, 127);
	dly->pan[3] = clip_int(st->parameter[7], 0, 127);
	dly->pan[4] = 0x40; // [tap] for feedback_delay
	dly->dlevel[0] = calc_option_level(st->parameter[8]);
	dly->dlevel[1] = calc_option_level(st->parameter[9]);
	dly->dlevel[2] = calc_option_level(st->parameter[10]);
	dly->dlevel[3] = calc_option_level(st->parameter[11]);
	dly->feedback = (double)(clip_int(st->parameter[12], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[13]);
	//eq
	eq->mode = CH_STEREO;	
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[14]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[15]);
	info->wet = calc_balance_wet_sd(st->parameter[16]);
	info->dry = calc_balance_dry_sd(st->parameter[16]);
	info->level = calc_sd_level(st->parameter[17]);
}

static void do_sd_multitap_delay2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_MultiTapDelay *info = (Info_SD_MultiTapDelay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;
	InfoEQ2 *eq = &info->eq;

	send_efx_buffer(ef, buf, count);
	do_multi_tap_delay(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);	
}

static void conv_sd_reverse_delay2(struct mfx_effect_sd_t *st, EffectList *ef){}
static void do_sd_reverse_delay2(DATA_T *buf, int32 count, EffectList *ef){}
static void conv_sd_shuffle_delay2(struct mfx_effect_sd_t *st, EffectList *ef){}
static void do_sd_shuffle_delay2(DATA_T *buf, int32 count, EffectList *ef){}

static void conv_sd_3d_delay2(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_3DDelay *info = (Info_SD_3DDelay *)ef->info;
	Info3DMultiTapDelay *dly = &info->dly;
	InfoEQ2 *eq = &info->eq; 

	dly->mode = CH_MIX_STEREO;
	dly->tap = 3;
	dly->dtime[1] = st->parameter[0] > 3000 ? calc_note2_sd(st->parameter[0] - 3000) * 1000 : st->parameter[0];
	dly->dtime[2] = st->parameter[1] > 3000 ? calc_note2_sd(st->parameter[1] - 3000) * 1000 : st->parameter[1];
	dly->dtime[0] = st->parameter[2] > 3000 ? calc_note2_sd(st->parameter[2] - 3000) * 1000 : st->parameter[2];
	dly->dtime[3] = dly->dtime[0]; // [tap] for feedback_delay // dtime[0]と同じ
	dly->pan[0] = 0x40;
	dly->pan[1] = 0x00;
	dly->pan[2] = 0x7F;
	dly->pan[3] = 0x40; // [tap] for feedback_delay // pan[0]と同じ
	dly->dlevel[1] = calc_option_level(st->parameter[3]);
	dly->dlevel[2] = calc_option_level(st->parameter[4]);
	dly->dlevel[0] = calc_option_level(st->parameter[5]);
	dly->feedback = (double)(clip_int(st->parameter[6], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[7]);
	dly->out = st->parameter[8] ? 1 : 0; // Speaker/Phones
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[9]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[10]);
	info->wet = calc_balance_wet_sd(st->parameter[11]);
	info->dry = calc_balance_dry_sd(st->parameter[11]);
	info->level = calc_sd_level(st->parameter[12]);
}

static void do_sd_3d_delay2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_3DDelay *info = (Info_SD_3DDelay *)ef->info;
	Info3DMultiTapDelay *dly = &info->dly;
	InfoEQ2 *eq = &info->eq; 

	send_efx_buffer(ef, buf, count);
	do_3d_multi_tap_delay(ef->efx_buf, count, dly);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
	do_eq2_multi(buf, count, eq);
}

static void conv_sd_rotary2(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Rotary *info = (Info_SD_Rotary *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoEQ2 *eq = &info->eq; 

	rt->mode = CH_MIX_STEREO;
	rt->low_slow = st->parameter[0] > 200 ? (1.0 / calc_note2_sd(st->parameter[0])) : ((double)clip_int(st->parameter[0], 1, 200) * 0.05);
	rt->low_fast = st->parameter[1] > 200 ? (1.0 / calc_note2_sd(st->parameter[1])) : ((double)clip_int(st->parameter[1], 1, 200) * 0.05);
	rt->low_accl = 5;
	//low tup st->parameter[2]
	//low tdown st->parameter[3]
	rt->low_level = calc_option_level(st->parameter[4]);
	rt->hi_slow = st->parameter[5] > 200 ? (1.0 / calc_note2_sd(st->parameter[5])) : ((double)clip_int(st->parameter[5], 1, 200) * 0.05);
	rt->hi_fast = st->parameter[6] > 200 ? (1.0 / calc_note2_sd(st->parameter[6])) : ((double)clip_int(st->parameter[6], 1, 200) * 0.05);
	rt->hi_accl = 5;
	//hi tup st->parameter[7]
	//hi tdown st->parameter[8]
	rt->hi_level = calc_option_level(st->parameter[9]);
	rt->speed = st->parameter[10] ? 1 : 0;
	//rot break st->parameter[11]
	rt->separate = (double)st->parameter[12] * DIV_127;
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[13]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[14]);
	info->level = calc_sd_level(st->parameter[15]);
}

static void do_sd_rotary2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Rotary *info = (Info_SD_Rotary *)ef->info;
	InfoRotary *rt = &info->rt;
	InfoEQ2 *eq = &info->eq; 

	do_rotary_multi(buf, count, rt);
	do_eq2_multi(buf, count, eq);
	effect_level_stereo(buf, count, info->level);
}

#define SD_MULTI_EFX_LEVEL (0.5)

static void conv_sd_s_rotary_multi(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_RotaryMulti *pe= (Info_SD_S_RotaryMulti *)ef->info;
//	InfoOverdrive *od = &pe->info_od;
	InfoDistortion *od = &pe->info_od;
	InfoAmpSimulator *amp = &pe->info_amp;
	InfoEQ3 *eq = &pe->info_eq;
	InfoRotary *rt = &pe->info_rt;

	// overdrive1	
	//od->mode = st->parameter[0] ? CH_LEFT : CH_NONE;
	//od->type = st->parameter[1] ? 1 : 0; // od/ds
	//od->drive = clip_int(st->parameter[2], 0, 127);
	////od->tone = clip_int(st->parameter[3], 0, 127);
	//od->level = calc_option_level(st->parameter[4]);
	//od->amp_sw = st->parameter[5] ? 1 : 0;
	//od->amp_type = clip_int(st->parameter[6], 0, 3);
	
	pe->od_sw = st->parameter[0] ? 1 : 0;
	od->mode = CH_LEFT;
	od->bass_od = 0; // gtr/bass
	od->od_type = st->parameter[1] ? 1 : 0; // od/ds
	od->drive = (double)st->parameter[2] * DIV_127;
	od->tone = 200 + 100 * st->parameter[3];
	od->level = calc_option_level(st->parameter[4]);
	od->edge = 0.6;	
	pe->amp_sw = st->parameter[5] ? 1 : 0;
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	switch(st->parameter[6]){
	default:
	case 0: // small
		amp->amp_type = 2;
		amp->cab_type = 1;
		break;
	case 1: // built in
		amp->amp_type = 4;
		amp->cab_type = 5;
		break;
	case 2: // 2 stack
		amp->amp_type = 8;
		amp->cab_type = 15;
		break;
	case 3: // 3 stack
		amp->amp_type = 9;
		amp->cab_type = 16;
		break;
	}
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->bright = 0;	
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;
	// eq
	pe->eq_sw = st->parameter[7] ? 1 : 0;
	eq->mode = CH_LEFT;
	eq->low_freq = 200;
	eq->low_gain = EQ_GAIN_SD(st->parameter[8]);
	eq->mid_freq = EQ_FREQ_SD(st->parameter[9]);
	eq->mid_width = EQ_Q_SD(st->parameter[10]);
	eq->mid_gain = EQ_GAIN_SD(st->parameter[11]);
	eq->high_freq = 5000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[12]);
	// rotary	
	pe->rt_sw = st->parameter[13] ? 1 : 0;
	rt->mode = CH_MONO_STEREO;
	rt->hi_slow = st->parameter[14] > 200 ? (1.0 / calc_note2_sd(st->parameter[14])) : ((double)clip_int(st->parameter[14], 1, 200) * 0.05);
	rt->low_slow = st->parameter[15] > 200 ? (1.0 / calc_note2_sd(st->parameter[15])) : ((double)clip_int(st->parameter[15], 1, 200) * 0.05);
	rt->hi_fast = st->parameter[16] > 200 ? (1.0 / calc_note2_sd(st->parameter[16])) : ((double)clip_int(st->parameter[16], 1, 200) * 0.05);
	rt->low_fast = st->parameter[17] > 200 ? (1.0 / calc_note2_sd(st->parameter[17])) : ((double)clip_int(st->parameter[17], 1, 200) * 0.05);
	rt->speed = st->parameter[18] ? 1 : 0;
	rt->hi_accl = (double)clip_int(st->parameter[19], 0, 15) * DIV_15;
	rt->low_accl = (double)clip_int(st->parameter[20], 0, 15) * DIV_15;
	rt->hi_level = calc_option_level(st->parameter[21]);
	rt->low_level = calc_option_level(st->parameter[22]);
	rt->separate = (double)st->parameter[23] * DIV_127;
	// mix
	pe->panl = calc_pan_sd_left(st->parameter[24]);
	pe->panr = calc_pan_sd_right(st->parameter[24]);
	pe->level = calc_sd_level(st->parameter[25]) * SD_MULTI_EFX_LEVEL; // for multi efx
}

static void do_sd_s_rotary_multi(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_RotaryMulti *pe= (Info_SD_S_RotaryMulti *)ef->info;
	
	if(count <= 0){
	//	do_od_ds_multi(buf, count, &pe->info_od);	
		do_distortion(buf, count, &pe->info_od);	
		do_amp_simulator(buf, count, &pe->info_amp);	
		do_eq3_multi(buf, count, &pe->info_eq);	
		do_rotary_multi(buf, count, &pe->info_rt);
		return;
	}
	effect_mix_mono(buf, count);	
//	do_od_ds_multi(buf, count, &pe->info_od);		
	if(pe->od_sw)
		do_distortion(buf, count, &pe->info_od);		
	if(pe->amp_sw)
		do_amp_simulator(buf, count, &pe->info_amp);		
	if(pe->eq_sw)
		do_eq3_multi(buf, count, &pe->info_eq);		
	if(pe->rt_sw)
		do_rotary_multi(buf, count, &pe->info_rt);
	effect_panning_mono_stereo(buf, count, pe->panl, pe->panr);
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_s_keyboard_multi(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_KeyboardMulti *pe= (Info_SD_S_KeyboardMulti *)ef->info;
	InfoRingModulator *rm = &pe->info_rm;
	InfoEQ3 *eq = &pe->info_eq;
	InfoPitchShifter *ps = &pe->info_ps;
	InfoPhaser *ph = &pe->info_ph;
	InfoDelayLR *dly = &pe->info_dly;

	// ring modulator
	pe->rm_sw = st->parameter[0] ? 1 : 0;
	rm->mode = CH_STEREO;
	rm->freq = (double)freq_table[clip_int(st->parameter[1], 0, 127)] * DIV_1000;
	rm->lfo_sw = 0; // lfo off
	pe->rm_wet = calc_balance_wet_sd(st->parameter[2]);
	pe->rm_dry = calc_balance_dry_sd(st->parameter[2]);
	// eq
	pe->eq_sw = st->parameter[3] ? 1 : 0;
	eq->mode = CH_STEREO;
	eq->low_freq = 200;
	eq->low_gain = EQ_GAIN_SD(st->parameter[4]);
	eq->mid_freq = EQ_FREQ_SD(st->parameter[5]);
	eq->mid_width = EQ_Q_SD(st->parameter[6]);
	eq->mid_gain = EQ_GAIN_SD(st->parameter[7]);
	eq->high_freq = 5000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[8]);
	// pitch shifter
	pe->ps_sw = st->parameter[9] ? 1 : 0;
	ps->mode = CH_MIX_MONO;
	ps->psl.ps_delay_ms = PS_CF_DELAY + clip_int(st->parameter[10], 0x00, 0x04) * 4; // PS_CF_DELAY + 16ms
	ps->psl.pitch_cent = (double)(clip_int(st->parameter[11], 0, 36) - 12) * 100 + (clip_int(st->parameter[12], 0, 100) - 50) * 2;
	ps->psl.pre_delay_ms = delay_time_3_table[clip_int(st->parameter[13], 0, 126)];
	ps->psl.feedback = (double)(clip_int(st->parameter[14], 0, 98) - 49) * (2.0 * DIV_100);
	pe->pswet = calc_balance_wet_sd(st->parameter[15]);
	pe->psdry = calc_balance_dry_sd(st->parameter[15]);
	// phaser
	pe->ph_sw = st->parameter[16] ? 1 : 0;
	ph->mode = CH_MIX_MONO;
	ph->phase = st->parameter[17] ? 8 : 2;
	ph->manual = (double)manual_table[clip_int(st->parameter[18], 0, 127)];
	ph->rate = st->parameter[19] > 200 ? (1.0 / calc_note2_sd(st->parameter[19])) : ((double)clip_int(st->parameter[19], 1, 200) * 0.05);
	ph->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[20], 0, 127));
	ph->feedback = 1.0;
	ph->offset = 0.0;
	ph->phase_diff = 0; // deg 0~360
	ph->reso = (double)clip_int(st->parameter[21], 0, 127) * DIV_127 * 12.0; // 12dB
	pe->ph_wet = calc_mix_wet_sd(st->parameter[22]);
	pe->ph_dry = 1.0; //calc_mix_dry_sd(st->parameter[22]);
	// delay
	pe->dly_sw = st->parameter[23] ? 1 : 0;
	dly->mode = CH_MIX_STEREO;
	dly->ldelay = dly->fdelay1 = st->parameter[24] > 3000 ? calc_note2_sd(st->parameter[24] - 3000) * 1000 : st->parameter[24];
	dly->rdelay = dly->fdelay2 = st->parameter[25] > 3000 ? calc_note2_sd(st->parameter[25] - 3000) * 1000 : st->parameter[25];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[26], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[27]);
	pe->dly_wet = calc_balance_wet_sd(st->parameter[28]);
	pe->dly_dry = calc_balance_dry_sd(st->parameter[28]);
	// mix
	pe->level = calc_sd_level(st->parameter[29]) * SD_MULTI_EFX_LEVEL; // for multi efx
}

static void do_sd_s_keyboard_multi(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_KeyboardMulti *pe= (Info_SD_S_KeyboardMulti *)ef->info;
	
	if(count < 0){
		do_ring_modulator_multi(ef->efx_buf, count, &pe->info_rm);
		do_eq3_multi(buf, count, &pe->info_eq);
		do_pitch_shifter_multi(ef->efx_buf, count, &pe->info_ps);
		do_phaser_multi(ef->efx_buf, count, &pe->info_ph);
		do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
		return;
	}
	if(pe->rm_sw){
		send_efx_buffer(ef, buf, count);
		do_ring_modulator_multi(ef->efx_buf, count, &pe->info_rm);
		return_efx_buffer(ef, buf, count, pe->rm_wet, pe->rm_dry, 1.0);
	}
	if(pe->eq_sw)
		do_eq3_multi(buf, count, &pe->info_eq);	
	if(pe->ps_sw){
		send_efx_buffer(ef, buf, count); 
		effect_mix_mono(ef->efx_buf, count);
		do_pitch_shifter_multi(ef->efx_buf, count, &pe->info_ps);
		return_efx_buffer(ef, buf, count, pe->pswet, pe->psdry, 1.0);
	}
	if(pe->ph_sw){
		send_efx_buffer(ef, buf, count);
		do_phaser_multi(ef->efx_buf, count, &pe->info_ph);
		return_efx_buffer(ef, buf, count, pe->ph_wet, pe->ph_dry, 1.0);
	}
	if(pe->dly_sw){
		send_efx_buffer(ef, buf, count);
		do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
		return_efx_buffer(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	}
	effect_level_stereo(buf, count, pe->level);
}

static void conv_sd_s_rhodes_multi(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_RhodesMulti *pe= (Info_SD_S_RhodesMulti *)ef->info;
	InfoEnhancer *eh = &pe->info_eh;
	InfoPhaser *ph = &pe->info_ph;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoTremolo *trm = &pe->info_trm;

	// Enhancer
	pe->eh_sw = st->parameter[0] ? 1 : 0;
	eh->mode = CH_STEREO;
	eh->hpf_cutoff = 3200;
	eh->sens = (double)clip_int(st->parameter[1], 0, 127) * DIV_127;	
	pe->eh_wet = (double)clip_int(st->parameter[2], 0, 127) * DIV_127;	
	pe->eh_dry = 1.0;
	// Phaser
	pe->ph_sw = st->parameter[3] ? 1 : 0;
	ph->mode = CH_MIX_MONO;	
	ph->phase = st->parameter[4] ? 8 : 4;
	ph->manual = (double)manual_table[clip_int(st->parameter[5], 0, 127)];
	ph->rate = st->parameter[6] > 200 ? (1.0 / calc_note2_sd(st->parameter[6])) : ((double)clip_int(st->parameter[6], 1, 200) * 0.05);
	ph->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[7], 0, 127));
	ph->feedback = 1.0;
	ph->offset = 0.5;
	ph->phase_diff = 0; // deg 0~360
	ph->reso = (double)clip_int(st->parameter[8], 0, 127) * DIV_127 * 12.0; // 12dB
	pe->ph_wet = calc_mix_wet_sd(st->parameter[9]);
	pe->ph_dry = 1.0; //calc_mix_dry_sd(st->parameter[9]);
	// chorus flanger	
	pe->cf_sw = st->parameter[10] ? 1 : 0;
	cho->mode = CH_MIX_STEREO;
	cho->phase = 3;
	cho->pdelay_ms = (double)pre_delay_time_table[clip_int(st->parameter[12], 0, 125)];
	cho->rate = st->parameter[13] > 200 ? (1.0 / calc_note2_sd(st->parameter[13])) : ((double)clip_int(st->parameter[13], 1, 200) * 0.05);
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[14]);
	if(st->parameter[11])
		cho->feedback = (double)(clip_int(st->parameter[15], 0, 98) - 49) * (2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	cho->filter_type = clip_int(st->parameter[16], 0, 2);
	cho->filter_cutoff = EQ_FREQ_SD(st->parameter[17]);
	pe->cho_wet = calc_balance_wet_sd(st->parameter[18]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[18]);
	// Tremolo AutoPan	
	pe->trm_sw = st->parameter[19] ? 1 : 0;
	trm->mode = CH_STEREO;
	trm->type = st->parameter[20] ? 1 : 0;
	trm->phase = st->parameter[20] ? 180 : 0; // deg
	trm->wave = lfo_wave_table_gs[clip_int(st->parameter[21], 0, 4)];
	trm->rate = st->parameter[22] > 200 ? (1.0 / calc_note2_sd(st->parameter[22])) : ((double)clip_int(st->parameter[22], 1, 200) * 0.05);
	trm->depth = (double)clip_int(st->parameter[23], 0, 127) * DIV_127;
	// mix
	pe->level = calc_sd_level(st->parameter[24]) * SD_MULTI_EFX_LEVEL; // for multi efx
}

static void do_sd_s_rhodes_multi(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_RhodesMulti *pe= (Info_SD_S_RhodesMulti *)ef->info;
	
	if(count < 0){
		do_enhancer_multi(ef->efx_buf, count, &pe->info_eh);
		do_phaser_multi(ef->efx_buf, count, &pe->info_ph);
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		do_tremolo_autopan(buf, count, &pe->info_trm);
		return;
	}
	if(pe->eh_sw){
		send_efx_buffer(ef, buf, count);
		do_enhancer_multi(ef->efx_buf, count, &pe->info_eh);
		return_efx_buffer(ef, buf, count, pe->eh_wet, pe->eh_dry, 1.0);
	}
	if(pe->ph_sw){
		send_efx_buffer(ef, buf, count);
		do_phaser_multi(ef->efx_buf, count, &pe->info_ph);
		return_efx_buffer(ef, buf, count, pe->ph_wet, pe->ph_dry, 1.0);	
	}
	if(pe->cf_sw){
		send_efx_buffer(ef, buf, count);
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		return_efx_buffer(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	}
	if(pe->trm_sw)
		do_tremolo_autopan(buf, count, &pe->info_trm);
	effect_level_stereo(buf, count, pe->level);	
}

// JD_Multi
static void sd_jd_effect_odds(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_JD_Multi *pe= (Info_SD_S_JD_Multi *)ef->info;
	
	if(pe->od_sw)
		do_od_ds_multi(buf, count, &pe->info_od);
}

static void sd_jd_effect_phaser(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_JD_Multi *pe= (Info_SD_S_JD_Multi *)ef->info;

	if(pe->ph_sw){
		send_efx_buffer(ef, buf, count);
		do_phaser_multi(ef->efx_buf, count, &pe->info_ph);
		return_efx_buffer_left(ef, buf, count, pe->ph_wet, pe->ph_dry, 1.0);	
	}
}

static void sd_jd_effect_spectrum(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_JD_Multi *pe= (Info_SD_S_JD_Multi *)ef->info;
	
	if(pe->eq_sw)
		do_spectrum(buf, count, &pe->info_eq);
}

static void sd_jd_effect_enhancer(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_JD_Multi *pe= (Info_SD_S_JD_Multi *)ef->info;
	
	if(pe->eh_sw){
		send_efx_buffer(ef, buf, count);
		do_enhancer_multi(ef->efx_buf, count, &pe->info_eh);
		return_efx_buffer_left(ef, buf, count, pe->eh_wet, pe->eh_dry, 1.0);
	}
}

static void conv_sd_s_jd_multi(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_JD_Multi *pe= (Info_SD_S_JD_Multi *)ef->info;
	InfoOverdrive *od = &pe->info_od;
	InfoPhaser *ph = &pe->info_ph;
	InfoSpectrum *eq = &pe->info_eq;
	InfoEnhancer *eh = &pe->info_eh;
	double tmp;

	//seuence
	//st->parameter[0] 
	pe->efx1 = sd_jd_effect_odds;
	pe->efx2 = sd_jd_effect_phaser;
	pe->efx3 = sd_jd_effect_spectrum;
	pe->efx4 = sd_jd_effect_enhancer;
	// od distortion
	pe->od_sw = st->parameter[0] ? 1 : 0;
	od->mode = CH_LEFT;	
	od->type = st->parameter[1] >= 3 ? 1 : 0; // od/ds
	od->drive = clip_int((int)((double)st->parameter[3] * 1.27), 0, 127);
	od->amp_type = 1;
	od->amp_sw = 1;
	od->level = (double)clip_int(st->parameter[4], 0, 100) * DIV_100;
	// Phaser
	pe->ph_sw = st->parameter[5] ? 1 : 0;
	ph->mode = CH_LEFT;	
	ph->phase = 4;
	tmp = clip_int(st->parameter[6], 0, 99);
	ph->manual = (tmp + 1) * 50 * (1.0 + tmp * DIV_100 * 3.0); // 50 ~ 15000
	ph->rate = (double)clip_int(st->parameter[7], 1, 100) * 0.1;
	ph->depth_cent = calc_chorus_depth_gs(clip_int((int)((double)st->parameter[8] * 1.27), 0, 127));
	ph->feedback = 1.0;
	ph->offset = 0.5;
	ph->phase_diff = 0; // deg 0~360
	ph->reso = (double)clip_int(st->parameter[9], 0, 100) * DIV_100 * 12.0; // 12dB
	pe->ph_wet = calc_balance_wet_sd(st->parameter[10]);
	pe->ph_dry = 1.0; //calc_balance_dry_sd(st->parameter[10]);	
	// spectrum
	pe->eq_sw = st->parameter[11] ? 1 : 0;
	eq->mode = CH_LEFT;
	eq->freq[0] = 250;
	eq->freq[1] = 500;
	eq->freq[2] = 1000;
	eq->freq[3] = 1250;
	eq->freq[4] = 2000;
	eq->freq[5] = 3150;
	eq->freq[6] = 4000;
	eq->freq[7] = 8000;
	eq->gain[0] = EQ_GAIN_SD(st->parameter[12]);
	eq->gain[1] = EQ_GAIN_SD(st->parameter[13]);
	eq->gain[2] = EQ_GAIN_SD(st->parameter[14]);
	eq->gain[3] = 0;
	eq->gain[4] = EQ_GAIN_SD(st->parameter[15]);
	eq->gain[5] = 0;
	eq->gain[6] = EQ_GAIN_SD(st->parameter[16]);
	eq->gain[7] = EQ_GAIN_SD(st->parameter[17]);
	eq->width = (double)EQ_Q_SD(st->parameter[18]);
	// Enhancer
	pe->eh_sw = st->parameter[19] ? 1 : 0;
	eh->mode = CH_LEFT;	
	eh->hpf_cutoff = 3200;
	eh->sens = (double)clip_int(st->parameter[20], 0, 100) * DIV_100;	
	pe->eh_wet = (double)clip_int(st->parameter[21], 0, 100) * DIV_100;	
	pe->eh_dry = 1.0;
	// mix
	pe->panl = calc_pan_sd_left(st->parameter[22]);
	pe->panr = calc_pan_sd_right(st->parameter[22]);
	pe->level = calc_sd_level(st->parameter[23]) * SD_MULTI_EFX_LEVEL; // for multi efx
}

static void do_sd_s_jd_multi(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_JD_Multi *pe= (Info_SD_S_JD_Multi *)ef->info;
	
	if(count <= 0){
		do_od_ds_multi(buf, count, &pe->info_od);
		do_phaser_multi(buf, count, &pe->info_ph);
		do_spectrum(buf, count, &pe->info_eq);
		do_enhancer_multi(buf, count, &pe->info_eh);
		return;
	}
	effect_mix_mono(buf, count);
	pe->efx1(buf, count, ef);
	pe->efx2(buf, count, ef);
	pe->efx3(buf, count, ef);
	pe->efx4(buf, count, ef);
	effect_panning_mono_stereo(buf, count, pe->panl, pe->panr);
	effect_level_stereo(buf, count, pe->level);	
}

static void conv_sd_st_lofi_compress(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_LoFi_Compress *info = (Info_SD_LoFi_Compress *)ef->info;
	InfoLoFi *lf = &info->lf;
	InfoEQ2 *eq = &info->eq; 
	
	lf->mode = CH_STEREO;
	lf->level_in = otd.sdefx_CustomLFLvIn;
	lf->level_out = otd.sdefx_CustomLFLvOut;
	lf->sr_rate = 32000;
	lf->pre_fil_type = st->parameter[0] ? FILTER_LPF_BW : FILTER_NONE; // off,lpf
	lf->pre_fil_freq = 12000;
	lf->pre_fil_reso = 0.0;
	lf->bit_length = 12 - clip_int(st->parameter[1], 0, 8);	
	// postfilter1 type st->parameter[2]
	lf->post_fil_type = st->parameter[3] >= 2 ? FILTER_LPF_BW : st->parameter[3] == 1 ? FILTER_BPF12_3 : FILTER_NONE; // off,lpf
	lf->post_fil_freq = EQ_FREQb_SD(st->parameter[4]);
	lf->post_fil_reso = 0.0;		
	lf->nz_gen = 0; // noise off
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[6]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[7]);
	info->wet = calc_balance_wet_sd(st->parameter[5]);
	info->dry = calc_balance_dry_sd(st->parameter[5]);
	info->level = calc_sd_level(st->parameter[9]);
}

static void do_sd_st_lofi_compress(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_LoFi_Compress *info = (Info_SD_LoFi_Compress *)ef->info;
	InfoLoFi *lf = &info->lf;
	InfoEQ2 *eq = &info->eq; 
	
	send_efx_buffer(ef, buf, count); 
	do_lofi(ef->efx_buf, count, lf);
	do_eq2_multi(ef->efx_buf, count, eq);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level); 
}

static void conv_sd_st_lofi_noise(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_LoFi_Noise *info = (Info_SD_LoFi_Noise *)ef->info;
	InfoLoFi *lf = &info->lf;
	InfoEQ2 *eq = &info->eq; 

	lf->mode = CH_STEREO;
	lf->level_in = otd.sdefx_CustomLFLvIn;
	lf->level_out = otd.sdefx_CustomLFLvOut;
	lf->sr_rate = 32000;
	lf->bit_length = 12 - clip_int(st->parameter[0], 0, 8);	
	lf->pre_fil_type = FILTER_NONE; // off
	lf->pre_fil_freq = 0;
	lf->pre_fil_reso = 0.0;
	switch(st->parameter[1]){
	default:
	case 0: // off
		lf->post_fil_type = FILTER_NONE;
		break;
	case 1: // lpf
		lf->post_fil_type = FILTER_LPF_BW;
		break;
	case 2: // hpf
		lf->post_fil_type = FILTER_HPF_BW;
		break;

	}
	lf->post_fil_freq = EQ_FREQ_SD(st->parameter[2]);
	lf->post_fil_reso = 0.0;		
	lf->nz_gen = 1; // noise on
	lf->rdetune = st->parameter[3];
	//lf->rnz_wet = calc_option_wet(st->parameter[4]);
	//lf->rnz_dry = calc_option_dry(st->parameter[4]);
	lf->rnz_lev = calc_option_level(st->parameter[4]);
	lf->wp_sel = 1;
	lf->wp_freq = 1000;
	//lf->wp_wet = calc_option_wet(st->parameter[7]);
	//lf->wp_dry = calc_option_dry(st->parameter[7]);
	lf->wp_level = calc_option_level(st->parameter[4]);
	lf->disc_type = clip_int(st->parameter[5], 0, 3);
	lf->disc_freq = EQ_FREQb_SD(st->parameter[6]);
	//lf->discnz_wet = calc_option_wet(st->parameter[10]);
	//lf->discnz_dry = calc_option_dry(st->parameter[10]);
	lf->discnz_lev = calc_option_level(st->parameter[7]);
	lf->hum_type = st->parameter[11] ? 1 : 0;
	lf->hum_freq = EQ_FREQb_SD(st->parameter[12]);
	//lf->hum_wet = calc_option_wet(st->parameter[13]);
	//lf->hum_dry = calc_option_dry(st->parameter[13]);
	lf->hum_level = calc_option_level(st->parameter[13]);
	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[15]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[16]);
	info->wet = calc_balance_wet_sd(st->parameter[14]);
	info->dry = calc_balance_dry_sd(st->parameter[14]);
	info->level = calc_sd_level(st->parameter[17]);
}
static void do_sd_st_lofi_noise(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_LoFi_Noise *info = (Info_SD_LoFi_Noise *)ef->info;
	InfoLoFi *lf = &info->lf;
	InfoEQ2 *eq = &info->eq; 
	
	send_efx_buffer(ef, buf, count); 
	do_lofi(ef->efx_buf, count, lf);
	do_eq2_multi(ef->efx_buf, count, eq);
	return_efx_buffer(ef, buf, count, info->wet, info->dry, info->level);
}

static void conv_sd_gt_amp_simulator(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_GuitarAmpSimulator *info = (Info_SD_GuitarAmpSimulator *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
	
	//od->mode = CH_LEFT;
	//od->type = st->parameter[0] == 0 ? 0 : st->parameter[4] == 0 ? 0 : 1; // 
	//od->drive = clip_int(sqrt(sqrt((double)st->parameter[2] * DIV_127) * sqrt((double)st->parameter[3] * DIV_64)) * 127.0, 0, 127);
	////od->tone = st->parameter[1];
	//od->amp_sw = st->parameter[10] ? 1 : 0;
	//od->amp_type = clip_int(st->parameter[12] >> 2, 0, 3);
	//od->level = 1.0; 	
	//eq->mode = CH_LEFT;
	//eq->low_freq = 200;
	//eq->low_gain = clip_int(st->parameter[5] - 64, -64, 64) * DIV_8;
	//eq->high_freq = 5000;
	//eq->high_gain = clip_int(st->parameter[7] - 64, -64, 64) * DIV_8;
	
	amp->mode = CH_LEFT;
	amp->amp_sw = st->parameter[0] ? 1 : 0;
	amp->amp_type = clip_int(st->parameter[1], 0, 13) + 1;
	amp->gain1 = (double)st->parameter[2] * DIV_127 * pow(1.2, clip_int(st->parameter[4] - 1, -1, 1));
	amp->gain2 = (double)st->parameter[3] * DIV_127;
	amp->level = 1.0;
	amp->tone = 8000;
	amp->eq1_gain = clip_int(st->parameter[5] - 64, -64, 64) * DIV_64 * 6.0; // db
	amp->eq2_gain = clip_int(st->parameter[6] - 64, -64, 64) * DIV_64 * 6.0; // db
	amp->eq3_gain = clip_int(st->parameter[7] - 64, -64, 64) * DIV_64 * 6.0; // db
	amp->eq4_gain = clip_int(st->parameter[8] - 64, -64, 64) * DIV_64 * 6.0; // db
	amp->bright = st->parameter[9] ? 1 : 0;	
	amp->cab_sw = st->parameter[10] ? 1 : 0;
	amp->cab_type = clip_int(st->parameter[11], 0, 15) + 1;
	amp->mic_pos = clip_int(st->parameter[12], 0, 2);
	amp->mic_level = calc_option_level(clip_int(st->parameter[13], 0, 127));
	amp->mic_direct = calc_option_level(clip_int(st->parameter[14], 0, 127));

	info->panl = calc_pan_sd_left(st->parameter[15]);
	info->panr = calc_pan_sd_right(st->parameter[15]);
	info->level = calc_sd_level(clip_int(st->parameter[16], 0, 127));
}

static void do_sd_gt_amp_simulator(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_GuitarAmpSimulator *info = (Info_SD_GuitarAmpSimulator *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
		
	effect_mix_mono(buf, count);
//	do_od_ds_multi(buf, count, od);
	do_amp_simulator(buf, count, amp);
	effect_panning_mono_stereo(buf, count, info->panl, info->panr);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_st_overdrive(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Overdrive *info = (Info_SD_Overdrive *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoDistortion *od = &info->od;
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
	
	//od->mode = CH_STEREO;
	//od->type = 0; // od
	//od->drive = clip_int(st->parameter[0], 0, 127);
	////od->tone = st->parameter[1];
	//od->amp_sw = st->parameter[2] ? 1 : 0;
	//od->amp_type = clip_int(st->parameter[3], 0, 3);
	//od->level = 1.0; 	

	od->mode = CH_STEREO;
	od->bass_od = 0; // gtr/bass
	od->od_type = 1; // od/ds
	od->drive = (double)st->parameter[0] * DIV_127;
	od->tone = 200 + 100 * st->parameter[1];
	od->level = 1.0;
	od->edge = 0.6;	
	info->amp_sw = st->parameter[9] ? 1 : 0;
	amp->mode = CH_STEREO;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	switch(st->parameter[2]){
	default:
	case 0: // small
		amp->amp_type = 2;
		amp->cab_type = 1;
		break;
	case 1: // built in
		amp->amp_type = 4;
		amp->cab_type = 5;
		break;
	case 2: // 2 stack
		amp->amp_type = 8;
		amp->cab_type = 15;
		break;
	case 3: // 3 stack
		amp->amp_type = 9;
		amp->cab_type = 16;
		break;
	}
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;

	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[4]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[5]);
	info->level = calc_sd_level(clip_int(st->parameter[6], 0, 127));
}

static void do_sd_st_overdrive(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Overdrive *info = (Info_SD_Overdrive *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoDistortion *od = &info->od;
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
		
//	do_od_ds_multi(buf, count, od);
	do_distortion(buf, count, od);		
	if(info->amp_sw)
		do_amp_simulator(buf, count, amp);
	do_eq2_multi(buf, count, eq);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_st_distortion(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Overdrive *info = (Info_SD_Overdrive *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoDistortion *od = &info->od;
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
	
	//od->mode = CH_STEREO;
	//od->type = 1; // ds
	//od->drive = clip_int(st->parameter[0], 0, 127);
	////od->tone = st->parameter[1];
	//od->amp_sw = st->parameter[2] ? 1 : 0;
	//od->amp_type = clip_int(st->parameter[3], 0, 3);
	//od->level = 1.0; 	

	od->mode = CH_STEREO;
	od->bass_od = 0; // gtr/bass
	od->od_type = 1; // od/ds
	od->drive = (double)st->parameter[0] * DIV_127;
	od->tone = 200 + 100 * st->parameter[1];
	od->level = 1.0;
	od->edge = 0.6;	
	info->amp_sw = st->parameter[9] ? 1 : 0;
	amp->mode = CH_STEREO;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	switch(st->parameter[2]){
	default:
	case 0: // small
		amp->amp_type = 2;
		amp->cab_type = 1;
		break;
	case 1: // built in
		amp->amp_type = 4;
		amp->cab_type = 5;
		break;
	case 2: // 2 stack
		amp->amp_type = 8;
		amp->cab_type = 15;
		break;
	case 3: // 3 stack
		amp->amp_type = 9;
		amp->cab_type = 16;
		break;
	}
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;

	eq->mode = CH_STEREO;
	eq->low_freq = 400;
	eq->low_gain = EQ_GAIN_SD(st->parameter[4]);
	eq->high_freq = 4000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[5]);
	info->level = calc_sd_level(clip_int(st->parameter[6], 0, 127));
}

static void do_sd_st_distortion(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Overdrive *info = (Info_SD_Overdrive *)ef->info;
//	InfoOverdrive *od = &info->od;
	InfoDistortion *od = &info->od;
	InfoAmpSimulator *amp = &info->amp;
	InfoEQ2 *eq = &info->eq; 
		
//	do_od_ds_multi(buf, count, od);
	do_distortion(buf, count, od);		
	if(info->amp_sw)
		do_amp_simulator(buf, count, amp);
	do_eq2_multi(buf, count, eq);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_s_gt_multi_a(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_GuitarMultiA *pe= (Info_SD_S_GuitarMultiA *)ef->info;
	InfoCompressor *cmp = &pe->info_cmp;
//	InfoOverdrive *od = &pe->info_od;
	InfoDistortion *od = &pe->info_od;
	InfoAmpSimulator *amp = &pe->info_amp;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoDelayLR *dly = &pe->info_dly;

	// compressor
	pe->cmp_sw = st->parameter[0] ? 1 : 0;
	cmp->mode = CH_LEFT;
	cmp->attak = mix_double ((double)st->parameter[1] * DIV_127, 10, 100); // 10ms-100ms
	cmp->sustain = mix_double ((double)st->parameter[2] * DIV_127, 10, 500); // 10ms-500ms
	cmp->pre_gain = 6; // dB
	cmp->post_gain = 0; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 0.5; // ratio? 1/2
	pe->level_cmp = calc_sd_level(st->parameter[3]);
	// od ds
	pe->od_sw = st->parameter[4] ? 1 : 0;
	//od->mode = CH_LEFT;
	//od->type = st->parameter[5] ? 1 : 0;
	//od->drive = clip_int(st->parameter[6], 0, 127);
	//// tone st->parameter[7]
	//od->level = calc_sd_level(st->parameter[8]);
	//od->amp_sw = st->parameter[9] ? 1 : 0;
	//od->amp_type = clip_int(st->parameter[10], 0, 3);

	od->mode = CH_LEFT;
	od->bass_od = 0; // gtr/bass
	od->od_type = st->parameter[5] ? 1 : 0; // od/ds
	od->drive = (double)st->parameter[6] * DIV_127;
	od->tone = 200 + 100 * st->parameter[7];
	od->level = calc_sd_level(st->parameter[8]);
	od->edge = 0.6;	
	pe->amp_sw = st->parameter[9] ? 1 : 0;
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	switch(st->parameter[10]){
	default:
	case 0: // small
		amp->amp_type = 2;
		amp->cab_type = 1;
		break;
	case 1: // built in
		amp->amp_type = 4;
		amp->cab_type = 5;
		break;
	case 2: // 2 stack
		amp->amp_type = 8;
		amp->cab_type = 15;
		break;
	case 3: // 3 stack
		amp->amp_type = 9;
		amp->cab_type = 16;
		break;
	}
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;
	// delay
	pe->dly_sw = st->parameter[11] ? 1 : 0;
	dly->mode = CH_LEFT;
	dly->ldelay = dly->fdelay1 = st->parameter[12] > 3000 ? calc_note2_sd(st->parameter[12] - 3000) * 1000 : st->parameter[12];
	dly->rdelay = dly->fdelay2 = st->parameter[13] > 3000 ? calc_note2_sd(st->parameter[13] - 3000) * 1000 : st->parameter[13];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[14], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[15]);
	pe->dly_wet = calc_balance_wet_sd(st->parameter[16]);
	pe->dly_dry = calc_balance_dry_sd(st->parameter[16]);
	// chorus flanger	
	pe->cf_sw = st->parameter[17] ? 1 : 0;
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->pdelay_ms = (double)pre_delay_time_table[clip_int(st->parameter[19], 0, 125)];
	cho->rate = st->parameter[20] > 200 ? (1.0 / calc_note2_sd(st->parameter[20])) : ((double)clip_int(st->parameter[20], 1, 200) * 0.05);
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[21]);
	if(st->parameter[18])
		cho->feedback = (double)(clip_int(st->parameter[22], 0, 98) - 49) * (2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	cho->filter_type = clip_int(st->parameter[23], 0, 2);
	cho->filter_cutoff = EQ_FREQ_SD(st->parameter[24]);
	pe->cho_wet = calc_balance_wet_sd(st->parameter[25]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[25]);
	// mix
	pe->panl = calc_pan_sd_left(st->parameter[26]);
	pe->panr = calc_pan_sd_right(st->parameter[26]);
	pe->level = calc_sd_level(st->parameter[27]) * SD_MULTI_EFX_LEVEL; // for multi efx
}

static void do_sd_s_gt_multi_a(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_GuitarMultiA *pe= (Info_SD_S_GuitarMultiA *)ef->info;
	
	if(count <= 0){
		do_compressor_multi(buf, count, &pe->info_cmp);
//		do_od_ds_multi(buf, count, &pe->info_od);	
		do_distortion(buf, count, &pe->info_od);	
		do_amp_simulator(buf, count, &pe->info_amp);
		do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		return;
	}
	effect_mix_mono(buf, count);
	if(pe->cmp_sw)
		do_compressor_multi(buf, count, &pe->info_cmp);	
	if(pe->od_sw)
//		do_od_ds_multi(buf, count, &pe->info_od);	
		do_distortion(buf, count, &pe->info_od);	
	if(pe->amp_sw)
		do_amp_simulator(buf, count, &pe->info_amp);	
	if(pe->dly_sw){
		send_efx_buffer(ef, buf, count);
		do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
		return_efx_buffer_left(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	}
	if(pe->cf_sw){
		send_efx_buffer(ef, buf, count);
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	}
	effect_panning_mono_stereo(buf, count, pe->panl, pe->panr);
	effect_level_stereo(buf, count, pe->level);	
}

static void conv_sd_s_gt_multi_b(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_GuitarMultiB *pe= (Info_SD_S_GuitarMultiB *)ef->info;
	InfoCompressor *cmp = &pe->info_cmp;
//	InfoOverdrive *od = &pe->info_od;
	InfoDistortion *od = &pe->info_od;
	InfoAmpSimulator *amp = &pe->info_amp;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoEQ3 *eq = &pe->info_eq;

	// compressor
	pe->cmp_sw = st->parameter[0] ? 1 : 0;
	cmp->mode = CH_LEFT;
	cmp->attak = mix_double ((double)st->parameter[1] * DIV_127, 10, 100); // 10ms-100ms
	cmp->sustain = mix_double ((double)st->parameter[2] * DIV_127, 10, 500); // 10ms-500ms
	cmp->pre_gain = 6; // dB
	cmp->post_gain = 0; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 0.5; // ratio? 1/2
	pe->level_cmp = calc_sd_level(st->parameter[3]);
	// od ds
	pe->od_sw = st->parameter[4] ? 1 : 0;
	//od->mode = CH_LEFT;
	//od->type = st->parameter[5] ? 1 : 0;
	//od->drive = clip_int(st->parameter[6], 0, 127);
	//// tone st->parameter[7]
	//od->level = calc_sd_level(st->parameter[8]);
	//od->amp_sw = st->parameter[9] ? 1 : 0;
	//od->amp_type = clip_int(st->parameter[10], 0, 3);
	
	od->mode = CH_LEFT;
	od->bass_od = 0; // gtr/bass
	od->od_type = st->parameter[5] ? 1 : 0; // od/ds
	od->drive = (double)st->parameter[6] * DIV_127;
	od->tone = 200 + 100 * st->parameter[7];
	od->level = calc_sd_level(st->parameter[8]);
	od->edge = 0.6;	
	pe->amp_sw = st->parameter[9] ? 1 : 0;
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	switch(st->parameter[10]){
	default:
	case 0: // small
		amp->amp_type = 2;
		amp->cab_type = 1;
		break;
	case 1: // built in
		amp->amp_type = 4;
		amp->cab_type = 5;
		break;
	case 2: // 2 stack
		amp->amp_type = 8;
		amp->cab_type = 15;
		break;
	case 3: // 3 stack
		amp->amp_type = 9;
		amp->cab_type = 16;
		break;
	}
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;
	// eq
	pe->eq_sw = st->parameter[11] ? 1 : 0;
	eq->mode = CH_LEFT;
	eq->low_freq = 200;
	eq->low_gain = EQ_GAIN_SD(st->parameter[12]);
	eq->mid_freq = EQ_FREQ_SD(st->parameter[13]);
	eq->mid_width = EQ_Q_SD(st->parameter[14]);
	eq->mid_gain = EQ_GAIN_SD(st->parameter[15]);
	eq->high_freq = 5000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[16]);
	// chorus flanger	
	pe->cf_sw = st->parameter[17] ? 1 : 0;
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->pdelay_ms = (double)pre_delay_time_table[clip_int(st->parameter[19], 0, 125)];
	cho->rate = st->parameter[20] > 200 ? (1.0 / calc_note2_sd(st->parameter[20])) : ((double)clip_int(st->parameter[20], 1, 200) * 0.05);
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[21]);
	if(st->parameter[18])
		cho->feedback = (double)(clip_int(st->parameter[22], 0, 98) - 49) * (2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	cho->filter_type = clip_int(st->parameter[23], 0, 2);
	cho->filter_cutoff = EQ_FREQ_SD(st->parameter[24]);
	pe->cho_wet = calc_balance_wet_sd(st->parameter[25]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[25]);
	// mix
	pe->panl = calc_pan_sd_left(st->parameter[26]);
	pe->panr = calc_pan_sd_right(st->parameter[26]);
	pe->level = calc_sd_level(st->parameter[27]) * SD_MULTI_EFX_LEVEL; // for multi efx
}

static void do_sd_s_gt_multi_b(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_GuitarMultiB *pe= (Info_SD_S_GuitarMultiB *)ef->info;
	
	if(count <= 0){
		do_compressor_multi(buf, count, &pe->info_cmp);
//		do_od_ds_multi(buf, count, &pe->info_od);	
		do_distortion(buf, count, &pe->info_od);
		do_amp_simulator(buf, count, &pe->info_amp);	
		do_eq3_multi(buf, count, &pe->info_eq);	
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		return;
	}
	effect_mix_mono(buf, count);
	if(pe->cmp_sw)
		do_compressor_multi(buf, count, &pe->info_cmp);	
	if(pe->od_sw)
//		do_od_ds_multi(buf, count, &pe->info_od);	
		do_distortion(buf, count, &pe->info_od);	
	if(pe->amp_sw)
		do_amp_simulator(buf, count, &pe->info_amp);	
	if(pe->eq_sw)
		do_eq3_multi(buf, count, &pe->info_eq);	
	if(pe->cf_sw){
		send_efx_buffer(ef, buf, count);
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	}
	effect_panning_mono_stereo(buf, count, pe->panl, pe->panr);
	effect_level_stereo(buf, count, pe->level);	
}

static void conv_sd_s_gt_multi_c(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_GuitarMultiC *pe= (Info_SD_S_GuitarMultiC *)ef->info;
	InfoAutoWah *aw = &pe->info_aw;
//	InfoOverdrive *od = &pe->info_od;
	InfoDistortion *od = &pe->info_od;
	InfoAmpSimulator *amp = &pe->info_amp;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoDelayLR *dly = &pe->info_dly;

	// od ds
	pe->od_sw = st->parameter[0] ? 1 : 0;
	//od->mode = CH_LEFT;
	//od->type = st->parameter[1] ? 1 : 0;
	//od->drive = clip_int(st->parameter[2], 0, 127);
	//// tone st->parameter[7]
	//od->level = calc_sd_level(st->parameter[4]);
	//od->amp_sw = st->parameter[12] ? 1 : 0;
	//od->amp_type = clip_int(st->parameter[13], 0, 3);
	
	od->mode = CH_LEFT;
	od->bass_od = 0; // gtr/bass
	od->od_type = st->parameter[1] ? 1 : 0; // od/ds
	od->drive = (double)st->parameter[2] * DIV_127;
	od->level = calc_sd_level(st->parameter[4]);
	od->edge = 0.6;
	od->tone = 8000;	
	pe->amp_sw = st->parameter[12] ? 1 : 0;
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	switch(st->parameter[13]){
	default:
	case 0: // small
		amp->amp_type = 2;
		amp->cab_type = 1;
		break;
	case 1: // built in
		amp->amp_type = 4;
		amp->cab_type = 5;
		break;
	case 2: // 2 stack
		amp->amp_type = 8;
		amp->cab_type = 15;
		break;
	case 3: // 3 stack
		amp->amp_type = 9;
		amp->cab_type = 16;
		break;
	}
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;
	// autowah
	pe->aw_sw = st->parameter[5] ? 1 : 0;
	aw->mode = CH_LEFT;
	aw->type = st->parameter[6] ? 1 : 0;
	aw->rate = st->parameter[7] > 200 ? (1.0 / calc_note2_sd(st->parameter[7])) : ((double)clip_int(st->parameter[7], 1, 200) * 0.05);
	aw->depth = (double)st->parameter[8] * DIV_127;
	aw->sens = calc_auto_wah_sens_gs(st->parameter[9]);	
	aw->release = 100.0; // ms
	aw->manual = calc_auto_wah_manual_gs(st->parameter[10]);
	aw->peak = calc_auto_wah_peak_gs(st->parameter[11]);
	aw->pol = 1;
	aw->lfo_sw = 1; // on
	aw->sens_sw = 1; // on
	// delay
	pe->dly_sw = st->parameter[14] ? 1 : 0;
	dly->mode = CH_LEFT;
	dly->ldelay = dly->fdelay1 = st->parameter[15] > 3000 ? calc_note2_sd(st->parameter[15] - 3000) * 1000 : st->parameter[15];
	dly->rdelay = dly->fdelay2 = st->parameter[16] > 3000 ? calc_note2_sd(st->parameter[16] - 3000) * 1000 : st->parameter[16];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[17], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[18]);
	pe->dly_wet = calc_balance_wet_sd(st->parameter[19]);
	pe->dly_dry = calc_balance_dry_sd(st->parameter[19]);
	// chorus flanger	
	pe->cf_sw = st->parameter[20] ? 1 : 0;
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->pdelay_ms = (double)pre_delay_time_table[clip_int(st->parameter[22], 0, 125)];
	cho->rate = st->parameter[23] > 200 ? (1.0 / calc_note2_sd(st->parameter[23])) : ((double)clip_int(st->parameter[23], 1, 200) * 0.05);
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[24]);
	if(st->parameter[21])
		cho->feedback = (double)(clip_int(st->parameter[25], 0, 98) - 49) * (2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	cho->filter_type = clip_int(st->parameter[26], 0, 2);
	cho->filter_cutoff = EQ_FREQ_SD(st->parameter[27]);
	pe->cho_wet = calc_balance_wet_sd(st->parameter[28]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[28]);
	// mix
	pe->panl = calc_pan_sd_left(st->parameter[29]);
	pe->panr = calc_pan_sd_right(st->parameter[29]);
	pe->level = calc_sd_level(st->parameter[30]) * SD_MULTI_EFX_LEVEL; // for multi efx
}

static void do_sd_s_gt_multi_c(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_GuitarMultiC *pe= (Info_SD_S_GuitarMultiC *)ef->info;
	
	if(count <= 0){
//		do_od_ds_multi(buf, count, &pe->info_od);	
		do_distortion(buf, count, &pe->info_od);	
		do_auto_wah_multi(buf, count, &pe->info_aw);
		do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		return;
	}
	effect_mix_mono(buf, count);
	if(pe->od_sw)
//		do_od_ds_multi(buf, count, &pe->info_od);	
		do_distortion(buf, count, &pe->info_od);		
	if(pe->aw_sw)
		do_auto_wah_multi(buf, count, &pe->info_aw);
	if(pe->amp_sw)
		do_amp_simulator(buf, count, &pe->info_amp);
	if(pe->dly_sw){
		send_efx_buffer(ef, buf, count);
		do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
		return_efx_buffer_left(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	}
	if(pe->cf_sw){
		send_efx_buffer(ef, buf, count);
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	}
	effect_panning_mono_stereo(buf, count, pe->panl, pe->panr);
	effect_level_stereo(buf, count, pe->level);	
}

static void conv_sd_s_clean_gt_multi_a(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_CleanGuitarMultiA *pe= (Info_SD_S_CleanGuitarMultiA *)ef->info;
	InfoCompressor *cmp = &pe->info_cmp;
	InfoEQ3 *eq = &pe->info_eq;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoDelayLR *dly = &pe->info_dly;

	// compressor
	pe->cmp_sw = st->parameter[0] ? 1 : 0;
	cmp->mode = CH_LEFT;
	cmp->attak = mix_double ((double)st->parameter[1] * DIV_127, 10, 100); // 10ms-100ms
	cmp->sustain = mix_double ((double)st->parameter[2] * DIV_127, 10, 500); // 10ms-500ms
	cmp->pre_gain = 6; // dB
	cmp->post_gain = 0; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 0.5; // ratio? 1/2
	pe->level_cmp = calc_sd_level(st->parameter[3]);
	// eq
	pe->eq_sw = st->parameter[4] ? 1 : 0;
	eq->mode = CH_LEFT;
	eq->low_freq = 200;
	eq->low_gain = EQ_GAIN_SD(st->parameter[5]);
	eq->mid_freq = EQ_FREQ_SD(st->parameter[6]);
	eq->mid_width = EQ_Q_SD(st->parameter[7]);
	eq->mid_gain = EQ_GAIN_SD(st->parameter[8]);
	eq->high_freq = 5000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[9]);
	// delay
	pe->dly_sw = st->parameter[10] ? 1 : 0;
	dly->mode = CH_LEFT;
	dly->ldelay = dly->fdelay1 = st->parameter[11] > 3000 ? calc_note2_sd(st->parameter[11] - 3000) * 1000 : st->parameter[11];
	dly->rdelay = dly->fdelay2 = st->parameter[12] > 3000 ? calc_note2_sd(st->parameter[12] - 3000) * 1000 : st->parameter[12];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[13], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[14]);
	pe->dly_wet = calc_balance_wet_sd(st->parameter[15]);
	pe->dly_dry = calc_balance_dry_sd(st->parameter[15]);
	// chorus flanger	
	pe->cf_sw = st->parameter[16] ? 1 : 0;
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->pdelay_ms = (double)pre_delay_time_table[clip_int(st->parameter[18], 0, 125)];
	cho->rate = st->parameter[19] > 200 ? (1.0 / calc_note2_sd(st->parameter[19])) : ((double)clip_int(st->parameter[19], 1, 200) * 0.05);
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[20]);
	if(st->parameter[17])
		cho->feedback = (double)(clip_int(st->parameter[21], 0, 98) - 49) * (2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	cho->filter_type = clip_int(st->parameter[22], 0, 2);
	cho->filter_cutoff = EQ_FREQ_SD(st->parameter[23]);
	pe->cho_wet = calc_balance_wet_sd(st->parameter[24]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[24]);
	// mix
	pe->panl = calc_pan_sd_left(st->parameter[25]);
	pe->panr = calc_pan_sd_right(st->parameter[25]);
	pe->level = calc_sd_level(st->parameter[26]) * SD_MULTI_EFX_LEVEL; // for multi efx
}

static void do_sd_s_clean_gt_multi_a(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_CleanGuitarMultiA *pe= (Info_SD_S_CleanGuitarMultiA *)ef->info;
	
	if(count <= 0){
		do_compressor_multi(buf, count, &pe->info_cmp);
		do_eq3_multi(buf, count, &pe->info_eq);	
		do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		return;
	}
	effect_mix_mono(buf, count);
	if(pe->cmp_sw)
		do_compressor_multi(buf, count, &pe->info_cmp);	
	if(pe->eq_sw)
		do_eq3_multi(buf, count, &pe->info_eq);	
	if(pe->dly_sw){
		send_efx_buffer(ef, buf, count);
		do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
		return_efx_buffer_left(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	}
	if(pe->cf_sw){
		send_efx_buffer(ef, buf, count);
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	}
	effect_panning_mono_stereo(buf, count, pe->panl, pe->panr);
	effect_level_stereo(buf, count, pe->level);	
}

static void conv_sd_s_clean_gt_multi_b(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_CleanGuitarMultiB *pe= (Info_SD_S_CleanGuitarMultiB *)ef->info;
	InfoAutoWah *aw = &pe->info_aw;
	InfoEQ3 *eq = &pe->info_eq;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoDelayLR *dly = &pe->info_dly;

	// autowah
	pe->aw_sw = st->parameter[0] ? 1 : 0;
	aw->mode = CH_LEFT;
	aw->type = st->parameter[1] ? 1 : 0;
	aw->rate = st->parameter[2] > 200 ? (1.0 / calc_note2_sd(st->parameter[2])) : ((double)clip_int(st->parameter[2], 1, 200) * 0.05);
	aw->depth = (double)st->parameter[3] * DIV_127;
	aw->sens = calc_auto_wah_sens_gs(st->parameter[4]);	
	aw->release = 100.0; // ms
	aw->manual = calc_auto_wah_manual_gs(st->parameter[5]);
	aw->peak = calc_auto_wah_peak_gs(st->parameter[6]);
	aw->pol = 1;
	aw->lfo_sw = 1; // on
	aw->sens_sw = 1; // on
	// eq
	pe->eq_sw = st->parameter[7] ? 1 : 0;
	eq->mode = CH_LEFT;
	eq->low_freq = 200;
	eq->low_gain = EQ_GAIN_SD(st->parameter[8]);
	eq->mid_freq = EQ_FREQ_SD(st->parameter[9]);
	eq->mid_width = EQ_Q_SD(st->parameter[10]);
	eq->mid_gain = EQ_GAIN_SD(st->parameter[11]);
	eq->high_freq = 5000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[12]);
	// delay
	pe->dly_sw = st->parameter[13] ? 1 : 0;
	dly->mode = CH_LEFT;
	dly->ldelay = dly->fdelay1 = st->parameter[14] > 3000 ? calc_note2_sd(st->parameter[14] - 3000) * 1000 : st->parameter[14];
	dly->rdelay = dly->fdelay2 = st->parameter[15] > 3000 ? calc_note2_sd(st->parameter[15] - 3000) * 1000 : st->parameter[15];
	dly->fb_mode = 0; // normal
	dly->phasel = 0;
	dly->phaser = 0;
	dly->feedback = (double)(clip_int(st->parameter[16], 0, 98) - 49) * (2.0 * DIV_100);
	dly->high_damp = EQ_FREQb_SD(st->parameter[17]);
	pe->dly_wet = calc_balance_wet_sd(st->parameter[18]);
	pe->dly_dry = calc_balance_dry_sd(st->parameter[18]);
	// chorus flanger	
	pe->cf_sw = st->parameter[19] ? 1 : 0;
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->pdelay_ms = (double)pre_delay_time_table[clip_int(st->parameter[21], 0, 125)];
	cho->rate = st->parameter[22] > 200 ? (1.0 / calc_note2_sd(st->parameter[22])) : ((double)clip_int(st->parameter[22], 1, 200) * 0.05);
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[23]);
	if(st->parameter[20])
		cho->feedback = (double)(clip_int(st->parameter[24], 0, 98) - 49) * (2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	cho->filter_type = clip_int(st->parameter[25], 0, 2);
	cho->filter_cutoff = EQ_FREQ_SD(st->parameter[26]);
	pe->cho_wet = calc_balance_wet_sd(st->parameter[27]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[27]);
	// mix
	pe->panl = calc_pan_sd_left(st->parameter[28]);
	pe->panr = calc_pan_sd_right(st->parameter[28]);
	pe->level = calc_sd_level(st->parameter[29]) * SD_MULTI_EFX_LEVEL; // for multi efx
}

static void do_sd_s_clean_gt_multi_b(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_CleanGuitarMultiB *pe= (Info_SD_S_CleanGuitarMultiB *)ef->info;
	
	if(count <= 0){
		do_auto_wah_multi(buf, count, &pe->info_aw);
		do_eq3_multi(buf, count, &pe->info_eq);	
		do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		return;
	}
	effect_mix_mono(buf, count);
	if(pe->aw_sw)
		do_auto_wah_multi(buf, count, &pe->info_aw);
	if(pe->eq_sw)
		do_eq3_multi(buf, count, &pe->info_eq);	
	if(pe->dly_sw){
		send_efx_buffer(ef, buf, count);
		do_delay_lr_multi(ef->efx_buf, count, &pe->info_dly);
		return_efx_buffer_left(ef, buf, count, pe->dly_wet, pe->dly_dry, 1.0);
	}
	if(pe->cf_sw){
		send_efx_buffer(ef, buf, count);
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	}
	effect_panning_mono_stereo(buf, count, pe->panl, pe->panr);
	effect_level_stereo(buf, count, pe->level);	
}

static void conv_sd_s_base_multi(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_S_BaseMulti *pe= (Info_SD_S_BaseMulti *)ef->info;
	InfoCompressor *cmp = &pe->info_cmp;
//	InfoOverdrive *od = &pe->info_od;
	InfoDistortion *od = &pe->info_od;
	InfoAmpSimulator *amp = &pe->info_amp;
	InfoStereoChorus *cho = &pe->info_cho;
	InfoEQ3 *eq = &pe->info_eq;

	// compressor
	pe->cmp_sw = st->parameter[0] ? 1 : 0;
	cmp->mode = CH_LEFT;
	cmp->attak = mix_double ((double)st->parameter[1] * DIV_127, 10, 100); // 10ms-100ms
	cmp->sustain = mix_double ((double)st->parameter[2] * DIV_127, 10, 500); // 10ms-500ms
	cmp->pre_gain = 6; // dB
	cmp->post_gain = 0; // dB
	cmp->threshold = 1.0; // threshold(~1.0)
	cmp->slope = 0.5; // ratio? 1/2
	pe->level_cmp = calc_sd_level(st->parameter[3]);
	// od ds
	pe->od_sw = st->parameter[4] ? 1 : 0;
	//od->mode = CH_LEFT;
	//od->type = st->parameter[5] ? 1 : 0;
	//od->drive = clip_int(st->parameter[6], 0, 127);
	//// tone st->parameter[]
	//od->level = calc_sd_level(st->parameter[7]);
	//od->amp_sw = st->parameter[8] ? 1 : 0;
	//od->amp_type = clip_int(st->parameter[9], 0, 3);
	od->mode = CH_LEFT;
	od->bass_od = 1; // gtr/bass
	od->od_type = st->parameter[5] ? 1 : 0; // od/ds
	od->drive = (double)st->parameter[6] * DIV_127;
	od->level = calc_sd_level(st->parameter[7]);
	od->edge = 0.6;
	od->tone = 8000;	
	pe->amp_sw = st->parameter[8] ? 1 : 0;
	amp->mode = CH_LEFT;
	amp->amp_sw = 1;
	amp->cab_sw = 1; // on
	switch(st->parameter[9]){
	default:
	case 0: // small
		amp->amp_type = 2;
		amp->cab_type = 1;
		break;
	case 1: // built in
		amp->amp_type = 4;
		amp->cab_type = 5;
		break;
	case 2: // 2 stack
		amp->amp_type = 8;
		amp->cab_type = 15;
		break;
	case 3: // 3 stack
		amp->amp_type = 9;
		amp->cab_type = 16;
		break;
	}
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHzdb
	amp->bright = 0;	
	amp->mic_pos = 0.2;
	amp->mic_level = 1.0;
	amp->mic_direct = 0.0;
	// eq
	pe->eq_sw = st->parameter[10] ? 1 : 0;
	eq->mode = CH_LEFT;
	eq->low_freq = 200;
	eq->low_gain = EQ_GAIN_SD(st->parameter[11]);
	eq->mid_freq = EQ_FREQ_SD(st->parameter[12]);
	eq->mid_width = EQ_Q_SD(st->parameter[13]);
	eq->mid_gain = EQ_GAIN_SD(st->parameter[14]);
	eq->high_freq = 5000;
	eq->high_gain = EQ_GAIN_SD(st->parameter[15]);
	// chorus flanger	
	pe->cf_sw = st->parameter[16] ? 1 : 0;
	cho->mode = CH_LEFT;
	cho->phase = 3;
	cho->pdelay_ms = (double)pre_delay_time_table[clip_int(st->parameter[18], 0, 125)];
	cho->rate = st->parameter[19] > 200 ? (1.0 / calc_note2_sd(st->parameter[19])) : ((double)clip_int(st->parameter[19], 1, 200) * 0.05);
	cho->depth_cent = calc_chorus_depth_gs(st->parameter[20]);
	if(st->parameter[17])
		cho->feedback = (double)(clip_int(st->parameter[21], 0, 98) - 49) * (2.0 * DIV_100);
	else
		cho->feedback = 0.0;
	cho->phase_diff = 90;
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
	cho->filter_type = clip_int(st->parameter[22], 0, 2);
	cho->filter_cutoff = EQ_FREQ_SD(st->parameter[23]);
	pe->cho_wet = calc_balance_wet_sd(st->parameter[24]);
	pe->cho_dry = calc_balance_dry_sd(st->parameter[24]);
	// mix
	pe->panl = calc_pan_sd_left(st->parameter[25]);
	pe->panr = calc_pan_sd_right(st->parameter[25]);
	pe->level = calc_sd_level(st->parameter[26]) * SD_MULTI_EFX_LEVEL; // for multi efx
}

static void do_sd_s_base_multi(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_S_BaseMulti *pe= (Info_SD_S_BaseMulti *)ef->info;
	
	if(count <= 0){
		do_compressor_multi(buf, count, &pe->info_cmp);
	//	do_od_ds_multi(buf, count, &pe->info_od);
		do_distortion(buf, count, &pe->info_od);	
		do_amp_simulator(buf, count, &pe->info_amp);	
		do_eq3_multi(buf, count, &pe->info_eq);	
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		return;
	}
	effect_mix_mono(buf, count);
	if(pe->cmp_sw)
		do_compressor_multi(buf, count, &pe->info_cmp);	
	if(pe->od_sw)
//		do_od_ds_multi(buf, count, &pe->info_od);	
		do_distortion(buf, count, &pe->info_od);	
	if(pe->amp_sw)
		do_amp_simulator(buf, count, &pe->info_amp);	
	if(pe->eq_sw)
		do_eq3_multi(buf, count, &pe->info_eq);	
	if(pe->cf_sw){
		send_efx_buffer(ef, buf, count);
		do_chorus_ex(ef->efx_buf, count, &pe->info_cho);
		return_efx_buffer_left(ef, buf, count, pe->cho_wet, pe->cho_dry, 1.0);
	}
	effect_panning_mono_stereo(buf, count, pe->panl, pe->panr);
	effect_level_stereo(buf, count, pe->level);	
}

static void conv_sd_isolator2(struct mfx_effect_sd_t *st, EffectList *ef){}
static void do_sd_isolator2(DATA_T *buf, int32 count, EffectList *ef){}

static void conv_sd_stereo_spectrum(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Spectrum *info = (Info_SD_Spectrum *)ef->info;
	InfoSpectrum *eq = &info->eq;

	eq->mode = CH_STEREO;
	eq->freq[0] = 250;
	eq->freq[1] = 500;
	eq->freq[2] = 1000;
	eq->freq[3] = 1250;
	eq->freq[4] = 2000;
	eq->freq[5] = 3150;
	eq->freq[6] = 4000;
	eq->freq[7] = 8000;
	eq->gain[0] = EQ_GAIN_SD(st->parameter[0]);
	eq->gain[1] = EQ_GAIN_SD(st->parameter[1]);
	eq->gain[2] = EQ_GAIN_SD(st->parameter[2]);
	eq->gain[3] = EQ_GAIN_SD(st->parameter[3]);
	eq->gain[4] = EQ_GAIN_SD(st->parameter[4]);
	eq->gain[5] = EQ_GAIN_SD(st->parameter[5]);
	eq->gain[6] = EQ_GAIN_SD(st->parameter[6]);
	eq->gain[7] = EQ_GAIN_SD(st->parameter[7]);
	eq->width = (double)EQ_Q_SD(st->parameter[8]);
	info->level = calc_sd_level(st->parameter[9]);
}

static void do_sd_stereo_spectrum(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Spectrum *info = (Info_SD_Spectrum *)ef->info;
	InfoSpectrum *eq = &info->eq;

	do_spectrum(buf, count, eq);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_3d_auto_spin(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_3DAutoSpin *info = (Info_SD_3DAutoSpin *)ef->info;	
	Info3DAuto *lc = &info->locate;
	
	lc->azimuth = (double)(clip_int(st->parameter[0], 0, 30) -15) * 12.0 * DIV_180;
	lc->speed = st->parameter[1] > 200 ? (1.0 / calc_note2_sd(st->parameter[1])) : ((double)clip_int(st->parameter[1], 1, 200) * 0.05);
	lc->clockwize = st->parameter[2] ? 1 : 0;
	lc->turn = st->parameter[3] ? 1 : 0;
	lc->out = st->parameter[4] ? 1 : 0;
	info->level = calc_sd_level(st->parameter[5]);
}

static void do_sd_3d_auto_spin(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_3DAutoSpin *info = (Info_SD_3DAutoSpin *)ef->info;	
	Info3DAuto *lc = &info->locate;

	do_3d_auto(buf, count, lc);
	effect_level_stereo(buf, count, info->level);
}

static void conv_sd_3d_manual(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_3DManual *info = (Info_SD_3DManual *)ef->info;	
	Info3DManual *lc = &info->locate;

	lc->azimuth = (double)(clip_int(st->parameter[0], 0, 30) -15) * 12.0 * DIV_180;
	lc->out = st->parameter[1] ? 1 : 0;	
	info->level = calc_sd_level(st->parameter[2]);
}

static void do_sd_3d_manual(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_3DManual *info = (Info_SD_3DManual *)ef->info;	
	Info3DManual *lc = &info->locate;

	do_3d_manual(buf, count, lc);	
	effect_level_stereo(buf, count, info->level);
}


/************************************ SD Chorus Reverb test ################************************************/

// SD Reverb
static double rev_sd_type_predelay(int character)
{
	double rt;
	switch(character) {
	case 0: rt = pre_delay_time_table[5];	break;	/* Room 1 */
	case 1: rt = pre_delay_time_table[10];	break;	/* Room 2 */
	case 2: rt = pre_delay_time_table[20];	break;	/* Stage 1 */
	case 3: rt = pre_delay_time_table[40];	break;	/* Stage 2 */
	case 4: rt = pre_delay_time_table[80];	break;	/* Hall 1 */
	case 5: rt = pre_delay_time_table[120];	break;	/* Hall 2 */
	default: rt = pre_delay_time_table[120];	break;	/* Hall 2 */
	}
	return rt;
}

static float HF_damp_freq_table_sd[6] = {4000, 5000, 6400, 8000, 10000, 12500,};

static void conv_sd_reverb1(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Rev_Reverb *info = (Info_SD_Rev_Reverb *)ef->info;
	InfoFreeverb *rvb = &info->rvb;	
	InfoReverbEX *rvb2 = &info->rvb2;	
#ifdef REV_EX2
	InfoReverbEX2 *rvb3 = &info->rvb3;
#endif 

#ifdef REV_EX2			
	if((opt_reverb_control >= 7 && opt_reverb_control < 9) || (opt_reverb_control <= -768 && opt_reverb_control > -1024)){
		info->rev_type = 2; // reverb ex2
		rvb3->mode = CH_STEREO;
		switch(clip_int(st->parameter[0], 0x00, 0x05)){
		case 0: // room1
			rvb3->height = 3.0; // m
			rvb3->width = 5.0; // m
			rvb3->depth = 7.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.65;
			rvb3->er_level = 0.50;
			rvb3->rev_level = 0.50;
			rvb3->density = 1.0;
			break;
		case 1: // room2
			rvb3->height = 4.0; // m
			rvb3->width = 8.0; // m
			rvb3->depth = 10.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.99;
			rvb3->er_level = 0.45;
			rvb3->rev_level = 0.55;
			rvb3->density = 0.75;
			break;
		case 2: // stage1
			rvb3->height = 10.0; // m
			rvb3->width = 12.0; // m
			rvb3->depth = 15.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.85;
			rvb3->er_level = 0.40;
			rvb3->rev_level = 0.60;
			rvb3->density = 0.75;
			break;
		case 3: // stage2
			rvb3->height = 12.0; // m
			rvb3->width = 13.0; // m
			rvb3->depth = 18.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.95;
			rvb3->er_level = 0.60;
			rvb3->rev_level = 0.40;
			rvb3->density = 1.0;
			break;
		case 4: // hall1
			rvb3->height = 12.0; // m
			rvb3->width = 16.0; // m
			rvb3->depth = 20.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.65;
			rvb3->er_level = 0.50;
			rvb3->rev_level = 0.50;
			rvb3->density = 1.0;
			break;
		default:
		case 5: // hall2
			rvb3->height = 16.0; // m
			rvb3->width = 20.0; // m
			rvb3->depth = 31.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.95;
			rvb3->er_level = 0.45;
			rvb3->rev_level = 0.55;
			rvb3->density = 0.75;
			break;
		}		
		rvb3->er_time_ms = rev_sd_type_predelay(st->parameter[0]);
		rvb3->rev_time_sec = reverb_time_table[clip_int(st->parameter[1], 0, 127)];
		rvb3->rev_damp_freq = EQ_FREQb_SD(st->parameter[2]);
		rvb3->er_damp_freq = EQ_FREQb_SD(st->parameter[2]);
		rvb3->rev_feedback = 0.0; // reverb_status_gs.delay_feedback
		rvb3->rev_dly_ms = 0;
		rvb3->density = 1.0;
		rvb3->level = 1.0;
	}else 
#endif
	if(otd.efx_CustomRevType){
		info->rev_type = 1; // reverb ex
		rvb2->mode = CH_STEREO;
		switch(clip_int(st->parameter[0], 0x00, 0x05)){
		case 0: // room1
			rvb2->height = 3.0; // m
			rvb2->width = 5.0; // m
			rvb2->depth = 7.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.65;
			rvb2->er_level = 0.50;
			rvb2->rev_level = 0.50;
			rvb2->density = 1.0;
			break;
		case 1: // room2
			rvb2->height = 4.0; // m
			rvb2->width = 8.0; // m
			rvb2->depth = 10.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.99;
			rvb2->er_level = 0.45;
			rvb2->rev_level = 0.55;
			rvb2->density = 0.75;
			break;
		case 2: // stage1
			rvb2->height = 10.0; // m
			rvb2->width = 12.0; // m
			rvb2->depth = 15.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.85;
			rvb2->er_level = 0.40;
			rvb2->rev_level = 0.60;
			rvb2->density = 0.75;
			break;
		case 3: // stage2
			rvb2->height = 12.0; // m
			rvb2->width = 13.0; // m
			rvb2->depth = 18.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.95;
			rvb2->er_level = 0.60;
			rvb2->rev_level = 0.40;
			rvb2->density = 1.0;
			break;
		case 4: // hall1
			rvb2->height = 12.0; // m
			rvb2->width = 16.0; // m
			rvb2->depth = 20.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.65;
			rvb2->er_level = 0.50;
			rvb2->rev_level = 0.50;
			rvb2->density = 1.0;
			break;
		default:
		case 5: // hall2
			rvb2->height = 16.0; // m
			rvb2->width = 20.0; // m
			rvb2->depth = 31.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.95;
			rvb2->er_level = 0.45;
			rvb2->rev_level = 0.55;
			rvb2->density = 0.75;
			break;
		}		
		rvb2->er_time_ms = rev_sd_type_predelay(st->parameter[0]);
		rvb2->rev_time_sec = reverb_time_table[clip_int(st->parameter[1], 0, 127)];
		rvb2->rev_damp_freq = EQ_FREQb_SD(st->parameter[2]);
		rvb2->er_damp_freq = EQ_FREQb_SD(st->parameter[2]);
		rvb2->rev_feedback = 0.0;
		rvb2->rev_dly_ms = 0;
		rvb2->density = 1.0;
		rvb2->level = 1.0;
	}else{
// freeverb
		info->rev_type = 0;
		rvb->mode = CH_STEREO;		
		rvb->er_time_ms = rev_sd_type_predelay(st->parameter[0]);
		rvb->rev_rt = ins_gs_revchar_to_rt(clip_int(st->parameter[0], 0x00, 0x05));
		rvb->rev_roomsize = ins_gs_revchar_to_roomsize(clip_int(st->parameter[0], 0x00, 0x05)); 
		rvb->rev_time_sec = reverb_time_table[clip_int(st->parameter[1], 0, 127)];
		rvb->er_damp_freq = EQ_FREQb_SD(st->parameter[2]);
		rvb->rev_damp = EQ_FREQb_SD(st->parameter[2]) / 22050.0;
		rvb->er_level = 0.35;
		rvb->rev_wet = 1.0;//ins_gs_revchar_to_level(clip_int(st->parameter[0], 0x00, 0x05));
		rvb->rev_width = initialwidth;
		rvb->rev_feedback = 0.0;
		rvb->rev_dly_ms = 0;
		rvb->rev_level = 0.65;
		rvb->rev_dif = 1.0;
	}
}

static void conv_sd_reverb2(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Rev_Reverb *info = (Info_SD_Rev_Reverb *)ef->info;
	InfoFreeverb *rvb = &info->rvb;	
	InfoReverbEX *rvb2 = &info->rvb2;	
#ifdef REV_EX2
	InfoReverbEX2 *rvb3 = &info->rvb3;
#endif 

#ifdef REV_EX2			
	if((opt_reverb_control >= 7 && opt_reverb_control < 9) || (opt_reverb_control <= -768 && opt_reverb_control > -1024)){
		info->rev_type = 2; // reverb ex2
		rvb3->mode = CH_STEREO;
		rvb3->er_time_ms = pre_delay_time_table[clip_int(st->parameter[0], 0, 127)];
		rvb3->rev_time_sec = reverb_time_table[clip_int(st->parameter[1], 0, 127)];		
		rvb3->height = 2.25 + 1.25 * clip_int(st->parameter[2], 1, 8); // m
		rvb3->width = 4.0 + 2.5 * clip_int(st->parameter[2], 1, 8); // m
		rvb3->depth = 4.0 + 2.75 * clip_int(st->parameter[2], 1, 8); // m
		// st->parameter[3] // hicut freq
		rvb3->density = 0.5 + clip_int(st->parameter[4], 0, 127) * DIV_256;
		// st->parameter[5] diffusion
		// st->parameter[6] lf damp freq
		// st->parameter[7] lf damp gain
		rvb3->rev_damp_freq = HF_damp_freq_table_sd[clip_int(st->parameter[8], 0, 5)];
		rvb3->er_damp_freq = HF_damp_freq_table_sd[clip_int(st->parameter[8], 0, 5)];
		// st->parameter[9] hf damp gain
		rvb3->rev_damp_type = FILTER_LPF6;
		rvb3->rev_damp_bal = 0.95;
		rvb3->er_level = 0.45;
		rvb3->rev_level = 0.55;
		rvb3->rev_feedback = 0.0;
		rvb3->rev_dly_ms = 0;
		rvb3->density = 1.0;
		rvb3->level = 1.0;
	}else 
#endif
	if(otd.efx_CustomRevType){
		info->rev_type = 1; // reverb ex
		rvb2->mode = CH_STEREO;
		rvb2->er_time_ms = pre_delay_time_table[clip_int(st->parameter[0], 0, 127)];
		rvb2->rev_time_sec = reverb_time_table[clip_int(st->parameter[1], 0, 127)];		
		rvb2->height = 2.25 + 1.25 * clip_int(st->parameter[2], 1, 8); // m
		rvb2->width = 4.0 + 2.5 * clip_int(st->parameter[2], 1, 8); // m
		rvb2->depth = 4.0 + 2.75 * clip_int(st->parameter[2], 1, 8); // m
		// st->parameter[3] // hicut freq
		rvb2->density = 0.5 + clip_int(st->parameter[4], 0, 127) * DIV_256;
		// st->parameter[5] diffusion
		// st->parameter[6] lf damp freq
		// st->parameter[7] lf damp gain
		rvb2->rev_damp_freq = HF_damp_freq_table_sd[clip_int(st->parameter[8], 0, 5)];
		rvb2->er_damp_freq = HF_damp_freq_table_sd[clip_int(st->parameter[8], 0, 5)];
		// st->parameter[9] hf damp gain
		rvb2->rev_damp_type = FILTER_LPF6;
		rvb2->rev_damp_bal = 0.95;
		rvb2->er_level = 0.45;
		rvb2->rev_level = 0.55;
		rvb2->rev_feedback = 0.0;
		rvb2->rev_dly_ms = 0;
		rvb2->density = 1.0;
		rvb2->level = 1.0;
	}else{
// freeverb
		info->rev_type = 0;
		rvb->mode = CH_STEREO;		
		rvb->er_time_ms = pre_delay_time_table[clip_int(st->parameter[0], 0, 127)];
		rvb->rev_time_sec = reverb_time_table[clip_int(st->parameter[1], 0, 127)];
		rvb->rev_rt = ins_gs_revchar_to_rt(clip_int(st->parameter[2] * 5.4 / 8, 0x00, 0x05));
		rvb->rev_roomsize = ins_gs_revchar_to_roomsize(clip_int(st->parameter[2] * 5.4 / 8, 0x00, 0x05)); 
		rvb->er_damp_freq = HF_damp_freq_table_sd[clip_int(st->parameter[8], 0, 5)];
		rvb->rev_damp = HF_damp_freq_table_sd[clip_int(st->parameter[8], 0, 5)] / 22050.0;
		rvb->er_level = 0.35;
		rvb->rev_wet = 1.0;//ins_gs_revchar_to_level(clip_int(type, 0x00, 0x05));
		rvb->rev_width = initialwidth;
		rvb->rev_feedback = 0.0;
		rvb->rev_dly_ms = 0;
		rvb->rev_level = 0.55;
		rvb->rev_dif = 1.0;
	}
}

static void conv_sd_gm2_reverb(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Rev_Reverb *info = (Info_SD_Rev_Reverb *)ef->info;
	InfoFreeverb *rvb = &info->rvb;	
	InfoReverbEX *rvb2 = &info->rvb2;	
#ifdef REV_EX2
	InfoReverbEX2 *rvb3 = &info->rvb3;
#endif 
	int type = (st->parameter[0] >= 3) ? (st->parameter[0] + 1) : st->parameter[0];

#ifdef REV_EX2			
	if((opt_reverb_control >= 7 && opt_reverb_control < 9) || (opt_reverb_control <= -768 && opt_reverb_control > -1024)){
		info->rev_type = 2; // reverb ex2
		rvb3->mode = CH_STEREO;
		switch(clip_int(type, 0x00, 0x05)){
		case 0: // small room1
			rvb3->height = 3.0; // m
			rvb3->width = 4.5; // m
			rvb3->depth = 6.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.65;
			rvb3->er_level = 0.50;
			rvb3->rev_level = 0.50;
			rvb3->density = 1.0;
			break;
		case 1: // medium room2
			rvb3->height = 4.0; // m
			rvb3->width = 8.0; // m
			rvb3->depth = 10.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.99;
			rvb3->er_level = 0.45;
			rvb3->rev_level = 0.55;
			rvb3->density = 0.75;
			break;
		case 2: // large room1
			rvb3->height = 4.0; // m
			rvb3->width = 13.0; // m
			rvb3->depth = 16.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.85;
			rvb3->er_level = 0.40;
			rvb3->rev_level = 0.60;
			rvb3->density = 0.75;
			break;
		case 3: // medium hall
		case 4: // medium hall
			rvb3->height = 12.0; // m
			rvb3->width = 13.0; // m
			rvb3->depth = 19.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.65;
			rvb3->er_level = 0.50;
			rvb3->rev_level = 0.50;
			rvb3->density = 1.0;
			break;
		default:
		case 5: // large hall
			rvb3->height = 15.0; // m
			rvb3->width = 20.0; // m
			rvb3->depth = 31.0; // m
			rvb3->rev_damp_type = FILTER_LPF6;
			rvb3->rev_damp_bal = 0.85;
			rvb3->er_level = 0.45;
			rvb3->rev_level = 0.55;
			rvb3->density = 0.75;
			break;
		}		
		rvb3->er_time_ms = rev_sd_type_predelay(type);
		rvb3->rev_time_sec = reverb_time_table[clip_int(st->parameter[1], 0, 127)];
		rvb3->rev_damp_freq = 8000;
		rvb3->er_damp_freq = 8000;
		rvb3->rev_feedback = 0.0; // reverb_status_gs.delay_feedback
		rvb3->rev_dly_ms = 0;
		rvb3->density = 1.0;
		rvb3->level = 1.0;
	}else 
#endif
	if(otd.efx_CustomRevType){
		info->rev_type = 1; // reverb ex
		rvb2->mode = CH_STEREO;
		switch(clip_int(type, 0x00, 0x05)){
		case 0: // room1
			rvb2->height = 3.0; // m
			rvb2->width = 4.5; // m
			rvb2->depth = 6.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.65;
			rvb2->er_level = 0.50;
			rvb2->rev_level = 0.50;
			rvb2->density = 1.0;
			break;
		case 1: // room2
			rvb2->height = 4.0; // m
			rvb2->width = 8.0; // m
			rvb2->depth = 10.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.99;
			rvb2->er_level = 0.45;
			rvb2->rev_level = 0.55;
			rvb2->density = 0.75;
			break;
		case 2: // stage1
			rvb2->height = 4.0; // m
			rvb2->width = 13.0; // m
			rvb2->depth = 16.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.85;
			rvb2->er_level = 0.40;
			rvb2->rev_level = 0.60;
			rvb2->density = 0.75;
			break;
		case 3: // medium hall
		case 4: // medium hall
			rvb2->height = 12.0; // m
			rvb2->width = 13.0; // m
			rvb2->depth = 19.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.65;
			rvb2->er_level = 0.50;
			rvb2->rev_level = 0.50;
			rvb2->density = 1.0;
			break;
		default:
		case 5: // large hall
			rvb2->height = 15.0; // m
			rvb2->width = 20.0; // m
			rvb2->depth = 31.0; // m
			rvb2->rev_damp_type = FILTER_LPF6;
			rvb2->rev_damp_bal = 0.85;
			rvb2->er_level = 0.45;
			rvb2->rev_level = 0.55;
			rvb2->density = 0.75;
			break;
		}		
		rvb2->er_time_ms = rev_sd_type_predelay(type);
		rvb2->rev_time_sec = reverb_time_table[clip_int(st->parameter[1], 0, 127)];
		rvb2->rev_damp_freq = 8000;
		rvb2->er_damp_freq = 8000;
		rvb2->er_time_ms = 1.0;
		rvb2->rev_feedback = 0.0;
		rvb2->rev_dly_ms = 0;
		rvb2->density = 1.0;
		rvb2->level = 1.0;
	}else{
// freeverb
		info->rev_type = 0;
		rvb->mode = CH_STEREO;		
		rvb->er_time_ms = rev_sd_type_predelay(type);
		rvb->rev_rt = ins_gs_revchar_to_rt(clip_int(type, 0x00, 0x05));
		rvb->rev_roomsize = ins_gs_revchar_to_roomsize(clip_int(type, 0x00, 0x05)); 
		rvb->rev_time_sec = reverb_time_table[clip_int(st->parameter[1], 0, 127)];
		rvb->er_damp_freq = 8000;
		rvb->rev_damp = 8000.0 / 22050.0;
		rvb->er_level = 0.35;
		rvb->rev_wet = 1.0;//ins_gs_revchar_to_level(clip_int(type, 0x00, 0x05));
		rvb->rev_width = initialwidth;
		rvb->rev_feedback = 0.0;
		rvb->rev_dly_ms = 0;
		rvb->rev_level = 0.65;
		rvb->rev_dif = 1.0;
	}
}

static void conv_sd_plate1(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Rev_Plate *info = (Info_SD_Rev_Plate *)ef->info;
	InfoPlateReverb *rvb = &info->rvb;		

	rvb->mode = CH_STEREO;
	rvb->er_time_ms = pre_delay_time_table[clip_int(st->parameter[0], 0, 127)];
	rvb->rev_time_sec = reverb_time_table[clip_int(st->parameter[1], 0, 127)];
	rvb->rev_diff = 0.5 * (10 + clip_int(st->parameter[2], 0, 8)) * DIV_20;
	// st->parameter[3] high cut
	// st->parameter[4] density
	// st->parameter[5] diffusion
	// st->parameter[6] lf damp freq
	// st->parameter[7] lf damp gain
	rvb->rev_damp = HF_damp_freq_table_sd[clip_int(st->parameter[8], 0, 5)] / 22050.0; // initialdamp;
	// st->parameter[9] hf damp gain
	rvb->er_level = 0.25;
	rvb->rev_level = 0.75;
	rvb->rev_feedback = 0; //0.125;
	rvb->rev_wet = 1.0;	
}

static void conv_sd_gm2_plate(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Rev_Plate *info = (Info_SD_Rev_Plate *)ef->info;
	InfoPlateReverb *rvb = &info->rvb;		

	rvb->mode = CH_STEREO;
	rvb->rev_time_sec = reverb_time_table[clip_int(st->parameter[1], 0, 127)];
	rvb->rev_diff = 0.5 * (10 + 5) * DIV_20;	
	rvb->er_time_ms = 5.0;
	rvb->rev_damp = 8000.0 / 22050.0; // initialdamp;
	rvb->er_level = 0.25;
	rvb->rev_level = 0.75;
	rvb->rev_feedback = 0; //0.125;
	rvb->rev_wet = 1.0;	
}

static void conv_sd_delay2(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Rev_Delay *info = (Info_SD_Rev_Delay *)ef->info;
	InfoDelayLR *dly = &info->dly;

	dly->mode = CH_STEREO;
	dly->fb_mode = st->parameter[0] == 7 ? 1 : 0; // type
	dly->ldelay = dly->fdelay1 = (double)delay_time_3_table[clip_int(st->parameter[1], 0, 126)];
	dly->rdelay = dly->fdelay2 = (double)delay_time_3_table[clip_int(st->parameter[1], 0, 126)];
	dly->high_damp = EQ_FREQb_SD(st->parameter[2]);
	dly->feedback = (double)clip_int(st->parameter[3], 0, 127) * DIV_127;
	dly->phasel = 0;
	dly->phaser = 0;
}

static void do_sd_reverb1(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Rev_Reverb *info = (Info_SD_Rev_Reverb *)ef->info;
	InfoFreeverb *rvb = &info->rvb;
	InfoReverbEX *rvb2 = &info->rvb2;
#ifdef REV_EX2
	InfoReverbEX2 *rvb3 = &info->rvb3;
#endif

#ifdef REV_EX2	
	if(info->rev_type == 2)
		do_reverb_ex2(buf, count, rvb3);
	else 
#endif
	if(info->rev_type)
		do_reverb_ex(buf, count, rvb2);
	else
		do_freeverb(buf, count, rvb);
}

static void do_sd_plate1(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Rev_Plate *info = (Info_SD_Rev_Plate *)ef->info;
	InfoPlateReverb *rvb = &info->rvb;

	do_plate_reverb(buf, count, rvb);
}

static void do_sd_delay2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Rev_Delay *info = (Info_SD_Rev_Delay *)ef->info;
	InfoDelayLR *dly = &info->dly;

	do_delay_lr_multi(buf, count, dly);
}

// SD Chorus
static void conv_sd_chorus1(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Cho_Chorus *info = (Info_SD_Cho_Chorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;	

	cho->mode = CH_STEREO;
	cho->phase = 3;
	cho->rate = rate1_table[clip_int(st->parameter[0], 0, 125)];
	cho->depth_cent = calc_chorus_depth_gs(clip_int(st->parameter[1], 0, 127));
	cho->feedback = (double)(clip_int(st->parameter[2], 0, 98) - 49) * (2.0 * DIV_100);
	cho->phase_diff = (double)2.0 * clip_int(st->parameter[3], 0, 0x5A); // 0~180
	cho->pdelay_ms = pre_delay_time_table[clip_int(st->parameter[4], 0, 125)];
	cho->filter_type = clip_int(st->parameter[5], 0, 2);
	cho->filter_cutoff = EQ_FREQ_SD(st->parameter[6]);
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
}

static void conv_sd_gm2_chorus(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Cho_Chorus *info = (Info_SD_Cho_Chorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;	
	
	cho->mode = CH_STEREO;
	cho->phase = 3;
	 // st->parameter[0] type
	cho->depth_type = 1; // ms gm2
	cho->rate = calc_chorus_rate_gm2(clip_int(st->parameter[1], 0, 127)); // Hz
	cho->depth_ms = calc_chorus_depth_gm2(clip_int(st->parameter[2], 0, 127)); // ms
	cho->feedback = (double)clip_int(st->parameter[3], 0, 127) * DIV_127 * 0.96901; // 0.0~1.0
	cho->send_reverb = (double)chorus_status_gs.send_reverb * DIV_127 * 0.99949;
	set_chorus_send_reverb_sd(st->parameter[4]);		
	cho->pdelay_ms = 0.0;
	cho->filter_type = 0;
	cho->filter_cutoff = 0;
	cho->phase_diff = 90.0; // 0~180
	cho->pdelay_dev = 0; // 0~20
	cho->depth_dev = 0; // -20~+20
	cho->pan_dev = 20; // 0~20
}

static void conv_sd_delay3(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Cho_Delay *info = (Info_SD_Cho_Delay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;

	dly->mode = CH_MIX_STEREO;
	dly->tap = 3;
	dly->dtime[0] = st->parameter[0] > 125 ? calc_note2_sd(st->parameter[0] - 125) * 1000 : delay_time_1_table[st->parameter[0]];
	dly->dtime[1] = st->parameter[1] > 125 ? calc_note2_sd(st->parameter[1] - 125) * 1000 : delay_time_1_table[st->parameter[1]];
	dly->dtime[2] = st->parameter[2] > 125 ? calc_note2_sd(st->parameter[2] - 125) * 1000 : delay_time_1_table[st->parameter[2]];
	dly->dtime[3] = dly->dtime[0]; // [tap] for feedback_delay // dtime[0]と同じ
	dly->pan[0] = 0x40;
	dly->pan[1] = 0x00;
	dly->pan[2] = 0x7F;
	dly->pan[3] = 0x40; // [tap] for feedback_delay // pan[0]と同じ
	dly->high_damp = EQ_FREQb_SD(st->parameter[3]);
	dly->feedback = (double)(clip_int(st->parameter[4], 0, 98) - 49) * (2.0 * DIV_100);
	dly->dlevel[1] = calc_option_level(st->parameter[5]);
	dly->dlevel[2] = calc_option_level(st->parameter[6]);
	dly->dlevel[0] = calc_option_level(st->parameter[7]);
}

static void do_sd_chorus1(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Cho_Chorus *info = (Info_SD_Cho_Chorus *)ef->info;
	InfoStereoChorus *cho = &info->cho;
	
	do_chorus_ex(buf, count, cho);
}

static void do_sd_delay3(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Cho_Delay *info = (Info_SD_Cho_Delay *)ef->info;
	InfoMultiTapDelay *dly = &info->dly;

	do_multi_tap_delay(buf, count, dly);
}

/************************************ SD MFX test ################************************************/





static void conv_sd_test1(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Test1 *info = (Info_SD_Test1 *)ef->info;
	InfoDistortion *od = &info->od;
	InfoAmpSimulator *amp = &info->amp;
	
	od->mode = CH_STEREO;
	od->od_type = 0; // od/ds
	od->drive = 1.0;
	od->level = 1.0;
	od->edge = 0.5;
	od->tone = 8000;
	
	amp->mode = CH_STEREO;
	amp->amp_type = 10;
	amp->cab_type = 16;
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz

	//info->level = calc_sd_level(st->parameter[9]);
}

static void do_sd_test1(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Test1 *info = (Info_SD_Test1 *)ef->info;

//	do_distortion(buf, count, &info->od);
	do_amp_simulator(buf, count, &info->amp);
	//effect_level_stereo(buf, count, info->level);
}

static void conv_sd_test2(struct mfx_effect_sd_t *st, EffectList *ef)
{
	Info_SD_Test2 *info = (Info_SD_Test2 *)ef->info;
	InfoDistortion *od = &info->od;
	InfoAmpSimulator *amp = &info->amp;

	od->mode = CH_LEFT;
	od->bass_od = 0; // gtr/bass
	od->od_type = 0; // od/ds
	od->drive = (double)st->parameter[0] ;
	od->level = 1.0;
	od->edge = 0.6;
	od->tone = 8000;	
	amp->mode = CH_LEFT;
	amp->amp_type = 0;
	amp->cab_type = 15;
	amp->gain1 = 1.0;
	amp->gain2 = 1.0;
	amp->level = 1.0;
	amp->tone = 7000;
	amp->eq1_gain = 0; // low 700Hz
	amp->eq2_gain = 0; // mid 2.2kHz
	amp->eq3_gain = 0; // trb 4.5kHz
	amp->eq4_gain = 0; // prs 9.3kHz
}

static void do_sd_test2(DATA_T *buf, int32 count, EffectList *ef)
{
	Info_SD_Test2 *info = (Info_SD_Test2 *)ef->info;
	InfoDistortion *od = &info->od;
	InfoAmpSimulator *amp = &info->amp;

	do_distortion(buf, count, &info->od);
	do_amp_simulator(buf, count, &info->amp);
}


/**************** GS INSERTION effect_parameter ****************/
///r
struct effect_parameter_gs_t effect_parameter_gs[] = {
{	0x00, 0x00, "None", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, -1, -1,},
{	0x01, 0x00, "Stereo-EQ", { 1, 0x45, 1, 0x34, 0x48, 0x00, 0x48, 0x38, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 127,}, 19, -1,},
{	0x01, 0x01, "Spectrum", { 0x3C, 0x41, 0x43, 0x46, 0x42, 0x3F, 0x3C, 0x3B, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7F,}, 18, 19,},
{	0x01, 0x02, "Enhancer",{ 64, 127, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x34, 0x00, 0x7F,}, 0, 1, },
{	0x01, 0x03, "Humanizer", { 48, 0x01, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F,}, 2, 19,},
{	0x01, 0x10, "Overdrive",{ 48, 1, 1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 96,}, 0, 18,},
{	0x01, 0x11, "Distrotion",{ 76, 3, 1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x38, 0x40, 84,}, 0, 18, },
{	0x01, 0x20, "Phaser", { 0x24, 0x10, 64, 16, 127, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x7F,}, 0, 1,},
{	0x01, 0x21, "Auto Wah", { 0x01, 0, 68, 62, 0x31, 72, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F,}, 2, 4,},
{	0x01, 0x22, "Rotary", { 0x06, 0x71, 0x18, 127, 0x11, 0x78, 0x58, 64, 96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x7F,}, 10, 19,},
{	0x01, 0x23, "Stereo Flanger", { 0x00, 0x00, 0x10, 0x0B, 24, 0x73, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 104,}, 3, 5,},
{	0x01, 0x24, "Step Flanger", { 0x0A, 0x05, 95, 0x53, 0x5A, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 96,}, 3, 5,},
{	0x01, 0x25, "Tremolo", { 0x01, 0x3C, 96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x7F,}, 1, 2,},
{	0x01, 0x26, "Auto Pan", { 0x01, 0x3C, 96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x7F,}, 1, 2,},
{	0x01, 0x30, "Compressor", { 70, 100, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 104,}, 18, 19,},
{	0x01, 0x31, "Limiter", { 85, 0x03, 16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F,}, 18, 19,},
{	0x01, 0x40, "Hexa Chorus",{ 0x18, 0x08, 127, 5, 66, 16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0X00, 112,}, 1, 15, },
{	0x01, 0x41, "Tremolo Chorus", { 0x10, 0x08, 40, 80, 0x3C, 96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 0x7F,}, 4, 15,},
{	0x01, 0x42, "Stereo Chorus", { 0x00, 0x00, 0x0A, 0x08, 111, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 104,}, 3, 15,},
{	0x01, 0x43, "Space D", { 0x20, 0x08, 127, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 96,}, 1, 15,},
{	0x01, 0x44, "3D Chorus", { 0x0A, 0x08, 72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 80,}, 1, 15,},
{	0x01, 0x50, "Stereo Delay", { 0x65, 0x74, 0x5E, 0x01, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74, 0x40, 0x40, 0x00, 0x7F,}, 2, 15,},
{	0x01, 0x51, "Mod Delay", { 0x5A, 0x6C, 0x5E, 0x01, 0x0C, 21, 0x5A, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 61, 0x40, 0x40, 0x00, 0x7F,}, 4, 15,},
{	0x01, 0x52, "3 Tap Delay", { 0x14, 0x00, 0x07, 0x54, 127, 127, 127, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74, 0x40, 0x40, 0x00, 0x7F,}, 3, 15,},
{	0x01, 0x53, "4 Tap Delay", { 0x3C, 0x14, 0x28, 0x00, 127, 127, 127, 127, 0x54, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 74, 0x40, 0x40, 0x00, 0x7F,}, 9, 15,},
{	0x01, 0x54, "Tm Ctrl Delay", { 0x3C, 0x50, 0x54, 0x7F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74, 0x40, 0x40, 0x00, 0x7F,}, 0, 2,},
{	0x01, 0x55, "Reverb", { 0x03, 0x70, 120, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 0x7F,}, 2, 15,},
{	0x01, 0x56, "Gate Reverb", { 0x00, 0x05, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65, 0x40, 0x3D, 0x00, 112,}, 15, 19,},
{	0x01, 0x57, "3D Delay", { 0x74, 0x6A, 0x6E, 0x54, 40, 64, 64, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74, 0x40, 0x40, 0x00, 0x7F,}, 3, 15,},
{	0x01, 0x60, "2 Pitch Shifter", { 0x47, 0x3E, 0x00, 0x7F, 0x3B, 0x42, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x40, 0x40, 0x00, 95,}, 0, 4,},
{	0x01, 0x61, "Fb P.Shifter", { 0x47, 0x40, 0x59, 0x2D, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x3A, 0x00, 0x7F,}, 0, 3,},
{	0x01, 0x70, "3D Auto", { 0x40, 0x19, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,}, 1, 3,},
{	0x01, 0x71, "3D Manual", { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,}, 1, 14,},
{	0x01, 0x72, "Lo-Fi 1",{ 2, 6, 2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 127, 0x40, 0x40, 64, 127,}, 15, 18, },
{	0x01, 0x73, "Lo-Fi 2",{ 2, 1, 0x20, 0x00, 64, 1, 127, 0x00, 0x00, 127, 0x00, 0x00, 127, 0x00, 1, 127, 0x40, 0x40, 64, 127,}, 3, 15, },
{	0x02, 0x00, "OD->Chorus", { 48, 0x40, 0x01, 0x00, 0x00, 0x0A, 0x08, 72, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 80,}, 1, 9,},
{	0x02, 0x01, "OD->Flanger", { 48, 0x40, 0x01, 0x00, 0x00, 0x10, 0x0B, 40, 0x73, 49, 0x00, 0x00, 0x00, 0x00, 0x00, 49, 0x40, 0x40, 0x00, 80,}, 1, 9,},
{	0x02, 0x02, "OD->Delay", { 48, 0x40, 0x01, 0x00, 0x00, 0x6F, 0x56, 0x7F, 0x00, 74, 0x00, 0x00, 0x00, 0x00, 0x00, 74, 0x40, 0x40, 0x00, 80,}, 1, 9,},
{	0x02, 0x03, "DS->Chorus", { 48, 0x40, 0x01, 0x00, 0x00, 0x0A, 0x08, 0x00, 72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x00, 72,}, 1, 9,},
{	0x02, 0x04, "DS->Flanger", { 48, 0x40, 0x01, 0x00, 0x00, 0x10, 0x0B, 40, 0x73, 49, 0x00, 0x00, 0x00, 0x00, 0x00, 49, 0x40, 0x40, 0x00, 72,}, 1, 9,},
{	0x02, 0x05, "DS->Delay", { 48, 0x40, 0x01, 0x00, 0x00, 0x6F, 0x56, 0x7F, 0x00, 74, 0x00, 0x00, 0x00, 0x00, 0x00, 74, 0x40, 0x40, 0x00, 72,}, 1, 9,},
{	0x02, 0x06, "EH->Chorus", { 64, 127, 0x00, 0x00, 0x00, 0x40, 0x08, 101, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 80,}, 0, 9,},
{	0x02, 0x07, "EH->Flanger", { 64, 127, 0x00, 0x00, 0x00, 0x10, 0x0B, 24, 0x56, 74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 96,}, 0, 9,},
{	0x02, 0x08, "EH->Delay", { 64, 127, 0x00, 0x00, 0x00, 0x6F, 0x56, 0x7F, 0x00, 74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 88,}, 0, 9,},
{	0x02, 0x09, "Cho->Delay", { 0x10, 0x09, 120, 0x00, 0x40, 0x6F, 0x56, 0x7F, 0x00, 74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x7F,}, 4, 9,},
{	0x02, 0x0A, "FL->Delay", { 0x10, 0x0B, 24, 0x56, 0x40, 0x6F, 0x56, 0x7F, 0x00, 74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x7F,}, 3, 9,},
{	0x02, 0x0B, "Cho->Flanger", { 0x0A, 0x08, 120, 0x00, 0x40, 0x10, 0x0B, 24, 0x56, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 112,}, 4, 9,},
{	0x03, 0x00, "Rotary Multi", { 13, 0x01, 0x40, 0x48, 0x00, 0x40, 0x40, 0x06, 0x71, 0x18, 127, 0x11, 0x78, 0x58, 64, 96, 0x00, 0x00, 0x00, 96,}, 0, 16,},
{	0x04, 0x00, "GTR Multi 1", { 100, 80, 100, 0x01, 0x00, 80, 0x00, 0x01, 0x45, 0x4A, 0x01, 0x00, 0x08, 30, 0x66, 40, 0x3C, 34, 15, 110,}, 5, 18,},
{	0x04, 0x01, "GTR Multi 2", { 70, 127, 90, 0x01, 0x00, 80, 0x02, 0x01, 0x01, 0x4C, 0x30, 0x02, 0x45, 0x36, 0x00, 0x08, 96, 0x66, 0x00, 80,}, 5, 18,},
{	0x04, 0x02, "GTR Multi 3", { 0x01, 60, 10, 0x01, 0x01, 80, 0x02, 0x01, 0x40, 0x40, 0x01, 0x00, 0x08, 0x00, 0x59, 50, 0x20, 64, 30, 88,}, 1, 5,},
{	0x04, 0x03, "Clean Gt Multi 1", { 50, 127, 75, 0x01, 0x4C, 0x00, 0x02, 0x45, 0x34, 0x00, 0x08, 40, 0x4F, 100, 0x18, 40, 0x7F, 30, 0x00, 95,}, 14, 17,},
{	0x04, 0x04, "Clean Gt Multi 2", { 0x01, 55, 40, 0x1D, 80, 0x01, 0x4C, 0x48, 0x00, 0x40, 0x40, 0x00, 0x08, 20, 0x66, 100, 0x07, 15, 80, 76,}, 1, 18,},
{	0x04, 0x05, "Base Multi", { 72, 100, 75, 0x01, 0x00, 48, 0x00, 0x00, 0x01, 0x42, 0x48, 0x01, 0x44, 0x40, 0x00, 0x06, 20, 0x66, 64, 76,}, 5, 18,},
{	0x04, 0x06, "Rhodes Multi", { 64, 64, 0x24, 0x10, 32, 16, 64, 0x00, 0x7F, 0x0A, 0x08, 64, 0x68, 127, 0x01, 0x02, 0x3C, 64, 0x01, 0x7F,}, 16, 17,},
{	0x05, 0x00, "Keyboard Multi", { 50, 30, 0x43, 0x00, 0x02, 0x45, 0x42, 0x47, 0x40, 0x00, 60, 0x24, 0x08, 90, 80, 75, 0x14, 64, 40, 96,}, 0, 1,},
{	0x11, 0x00, "Cho/Delay", { 0x0A, 0x08, 120, 0x00, 0x40, 0x6F, 0x50, 0x7F, 0x00, 61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 127, 0x7F, 127, 96,}, 4, 9,},
{	0x11, 0x01, "FL/Delay", { 0x10, 0x0B, 24, 0x68, 0x40, 0x6F, 0x50, 0x7F, 0x00, 74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 127, 0x7F, 127, 96,}, 4, 9,},
{	0x11, 0x02, "Cho/Flanger", { 0x10, 0x08, 120, 0x00, 0x40, 0x10, 0x0B, 24, 0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 127, 0x7F, 127, 88,}, 4, 9,},
{	0x11, 0x03, "OD1/OD2",{ 0x00, 48, 1, 1, 0x00, 1, 76, 3, 1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 96, 0x7F, 84, 127,}, 1, 6, },
{	0x11, 0x04, "OD/Rotary", { 0x00, 48, 1, 1, 0x00, 0x06, 0x71, 0x18, 127, 0x11, 0x78, 0x58, 64, 96, 0x00, 0x00, 96, 0x7F, 0x7F, 127,}, 1, 14,},
{	0x11, 0x05, "OD/Phaser", { 0x00, 48, 1, 1, 0x00, 0x24, 0x10, 64, 16, 127, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 96, 0x7F, 0x7F, 127,}, 1, 6,},
{	0x11, 0x06, "OD/AutoWah", { 0x00, 48, 1, 1, 0x00, 0x01, 0, 68, 62, 0x28, 72, 0x01, 0x00, 0x00, 0x00, 0x00, 96, 0x7F, 0x7F, 127,}, 1, 7,},
{	0x11, 0x07, "PH/Rotary", { 0x24, 0x10, 64, 16, 127, 0x06, 0x71, 0x18, 127, 0x11, 0x78, 0x58, 64, 96, 0x00, 0x00, 127, 0x7F, 0x7F, 127,}, 1, 14,},
{	0x11, 0x08, "PH/AutoWah", { 0x24, 0x10, 64, 16, 127, 0x01, 0x00, 68, 62, 0x28, 72, 0x01, 0x00, 0x00, 0x00, 0x00, 127, 0x7F, 0x7F, 127,}, 1, 7,},
{	-1, -1, "EOF",{  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}, -1, -1,},
};


/**************** XG EFFECT effect_parameter ****************/
///e
struct effect_parameter_xg_t effect_parameter_xg[] = {
{	0x00, 0x00, "NO EFFECT", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, 0, },
{	0x01, 0x00, "HALL 1", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 18, 10, 8, 13, 49, 0, 0, 0, 0, 40, 0, 4, 50, 8, 64, 0,}, 9, },
{	0x01, 0x01, "HALL 2", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 25, 10, 20, 6, 46, 0, 0, 0, 0, 40, 13, 3, 74, 7, 64, 0,}, 9, },
{	0x01, 0x06, "HALL M", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 18, 10, 8, 13, 49, 0, 0, 0, 0, 40, 0, 4, 50, 8, 64, 0,}, 9, },
{	0x01, 0x07, "HALL L", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 18, 10, 28, 6, 46, 0, 0, 0, 0, 40, 5, 3, 64, 8, 64, 0,}, 9, },
{	0x02, 0x00, "ROOM 1", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, {  5, 10, 16, 4, 49, 0, 0, 0, 0, 40, 5, 3, 64, 8, 64, 0,}, 9, },
{	0x02, 0x01, "ROOM 2", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 12, 10,  5, 4, 38, 0, 0, 0, 0, 40, 0, 4, 50, 8, 64, 0,}, 9, },
{	0x02, 0x02, "ROOM 3", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, {  9, 10, 47, 5, 36, 0, 0, 0, 0, 40, 0, 4, 60, 8, 64, 0,}, 9, },
{	0x02, 0x05, "ROOM S", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 11, 10,  5, 4, 38, 0, 0, 0, 0, 40, 0, 4, 50, 8, 64, 0,}, 9, },
{	0x02, 0x06, "ROOM M", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 13, 10, 16, 4, 49, 0, 0, 0, 0, 40, 5, 3, 64, 8, 64, 0,}, 9, },
{	0x02, 0x07, "ROOM L", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 15, 10, 47, 5, 36, 0, 0, 0, 0, 40, 0, 4, 60, 8, 64, 0,}, 9, },
{	0x03, 0x00, "STAGE 1", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 19, 10, 16, 7, 54, 0, 0, 0, 0, 40, 0, 3, 64, 6, 64, 0,}, 9, },
{	0x03, 0x01, "STAGE 2", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 11, 10, 16, 7, 51, 0, 0, 0, 0, 40, 2, 2, 64, 6, 64, 0,}, 9, },
{	0x04, 0x00, "PLATE",    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 25, 10, 6, 8, 49, 0, 0, 0, 0, 40, 2, 3, 64, 5, 64, 0,}, 9, },
{	0x04, 0x07, "GM PLATE", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 13, 10, 6, 8, 49, 0, 0, 0, 0, 40, 2, 3, 64, 5, 64, 0,}, 9, },
{	0x05, 0x00, "DELAY L,C,R", { 0x1A, 0x0D, 0x27, 0x27, 0, 0, 0, 0, 0, 0,},{ 0x05, 0x03, 0x08, 0x08, 74, 100, 10, 0, 0, 32, 0, 0, 28, 64, 46, 64,}, 9,},
{	0x06, 0x00, "DELAY L,R", { 0x13, 0x1D, 0x1D, 0x1D, 0, 0, 0, 0, 0, 0,},{ 0x44, 0x26, 0x28, 0x26, 87, 10, 0, 0, 0, 32, 0, 0, 28, 64, 46, 64, },9,},
{	0x07, 0x00, "ECHO", { 0x0D, 0, 0x0D, 0, 0, 0x0D, 0x0D, 0, 0, 0,},{ 0x24, 80, 0x74, 80, 10, 0x24, 0x74, 0, 0, 40, 0, 0, 28, 64, 46, 64,}, 9,},
{	0x08, 0x00, "CROSS DELAY", { 0x0D, 0x0D, 0, 0, 0, 0, 0, 0, 0, 0,},{ 0x24, 0x56, 111, 1, 10, 0, 0, 0, 0, 32, 0, 0, 28, 64, 46, 64,}, 9,},
{	0x09, 0x00, "EARLY_REF 1", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 0, 19, 5, 16, 64, 0, 46, 0, 0, 32, 5, 0, 10, 0, 0, 0,}, 9, },
{	0x09, 0x01, "EARLY_REF 2", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 2, 7, 10, 16, 64, 3, 46, 0, 0, 32, 5, 2, 10, 0, 0, 0,}, 9, },
{	0x0A, 0x00, "GATE REVERB", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 0, 15, 6, 2, 64, 0, 44, 0, 0, 32, 4, 3, 10, 0, 0, 0,}, 9, },
{	0x0B, 0x00, "REVERSE GATE", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 1, 19, 8, 3, 64, 0, 47, 0, 0, 32, 6, 3, 10, 0, 0, 0,}, 9, },
{	0x10, 0x00, "WHITE ROOM", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, {  9, 5, 11, 0, 46, 30, 50, 70,  7, 40, 34, 4, 64, 7, 64, 0,}, 9, },
{	0x11, 0x00, "TUNNEL",     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 48, 6, 19, 0, 44, 33, 52, 70, 16, 40, 20, 4, 64, 7, 64, 0,}, 9, },
{	0x12, 0x00, "CANYON",     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 59, 6, 63, 0, 45, 34, 62, 91, 13, 40, 25, 4, 64, 7, 64, 0,}, 9, },
{	0x13, 0x00, "BASEMENT",   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, {  3, 6,  3, 0, 34, 26, 29, 59, 15, 40, 32, 4, 64, 7, 64, 0,}, 9, },
{	0x14, 0x00, "KARAOKE 1", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 63,  97,  0, 48, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0,}, 9, },
{	0x14, 0x01, "KARAOKE 2", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 55, 105,  0, 50, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0,}, 9, },
{	0x14, 0x02, "KARAOKE 3", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 43, 110, 14, 53, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0,}, 9, },
{	0x15, 0x00, "TEMPO DELAY", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 10, 80, 10, 78, 64, 0, 0, 0, 0, 39, 0, 0, 28, 64, 46, 64,}, 9,},
{	0x15, 0x08, "TEMPO ECHO", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 11, 92, 10, 78, 64, 0, 0, 0, 0, 40, 0, 0, 28, 64, 46, 64,}, 9,},
{	0x16, 0x00, "TEMPO CROSS", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 8, 8, 102, 1, 10, 64, 0, 0, 0, 34, 0, 0, 28, 64, 46, 64,}, 9,},
{	0x41, 0x00, "CHORUS 1", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 6, 54, 77, 106, 0, 28, 64, 46, 64, 64, 46, 64, 10, 0, 0, 0,}, 9,},
{	0x41, 0x01, "CHORUS 2",{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 8, 63, 64, 30, 0, 28, 62, 42, 58, 64, 46, 64, 10, 0, 0, 0,}, 9,},
{	0x41, 0x02, "CHORUS 3",{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 4, 44, 64, 110, 0, 28, 64, 46, 66, 64, 46, 64, 10, 0, 0, 0,}, 9,},
{	0x41, 0x03, "GM CHORUS 1",{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 9, 10, 64, 109, 0, 28, 64, 46, 64, 64, 46, 64, 10, 0, 0, 0,}, 9,},
{	0x41, 0x04, "GM CHORUS 2", {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 28, 34, 67, 105, 0, 28, 64, 46, 64, 64, 46, 64, 10, 0, 0, 0,}, 9,},
{	0x41, 0x05, "GM CHORUS 3", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 9, 34, 69, 105, 0, 28, 64, 46, 64, 64, 46, 64, 10, 0, 0, 0,}, 9,},
{	0x41, 0x06, "GM CHORUS 4", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 26, 29, 75, 102, 0, 28, 64, 46, 64, 64, 46, 64, 10, 0, 0, 0,}, 9,},
{	0x41, 0x07, "FB CHORUS", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{	6, 43, 107, 111, 0, 28, 64, 46, 64, 64, 46, 64, 10, 0, 0, 0,}, 9,},
{	0x41, 0x08, "CHORUS 4", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 9, 32, 69, 104, 0, 28, 64, 46, 64, 64, 46, 64, 10, 0, 1, 0,}, 9,},
{	0x42, 0x00, "CELESTE 1", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 12, 32, 64, 0, 0, 28, 64, 46, 64, 127, 40, 68, 10, 0, 0, 0,}, 9,},
{	0x42, 0x01, "CELESTE 2", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 28, 18, 90, 2, 0, 28, 62, 42, 60, 84, 40, 68, 10, 0, 0, 0,}, 9,},
{	0x42, 0x02, "CELESTE 3", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 4, 63, 44, 2, 0, 28, 64, 46, 68, 127, 40, 68, 10, 0, 0,0,}, 9,},
{	0x42, 0x08, "CELESTE 4", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 8, 29, 64, 0, 0, 28, 64, 51, 66, 127, 40, 68, 10, 0, 1, 0,}, 9,},
{	0x43, 0x00, "FLANGER 1", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 14, 14, 104, 2, 0, 28, 64, 46, 64, 96, 40, 64, 10, 4, 0, 0,}, 9, },
{	0x43, 0x01, "FLANGER 2", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 32, 17, 26, 2, 0, 28, 64, 46, 60, 96, 40, 64, 10, 4, 0, 0,}, 9, },
{	0x43, 0x07, "GM FLANGER", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 3, 21, 120, 1, 0, 28, 64, 46, 64, 96, 40, 64, 10, 4, 0, 0,}, 9, },
{	0x43, 0x08, "FLANGER 3", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 4, 109, 109, 2, 0, 28, 64, 46, 64, 127, 40, 64, 10, 4, 0, 0,}, 9, },
{	0x44, 0x00, "SYMPHONIC", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 12, 25, 16, 0, 0, 28, 64, 46, 64, 127, 46, 64, 10, 0, 0, 0,}, 9,},
{	0x45, 0x00, "ROTARY SPEAKER", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 81, 35, 0, 0, 0, 24, 64, 45, 64, 127, 33, 52, 30, 0, 0, 0,}, 0, },
{	0x45, 0x01, "DS+ROTARY SPEAKER", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 6, 92, 0, 0, 0, 26, 68, 56, 52, 127, 0, 0, 0, 5, 49, 55,}, 0, },
{	0x45, 0x02, "OD+ROTARY SPEAKER", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 7, 90, 0, 0, 0, 24, 66, 56, 52, 127, 0, 0, 0, 4, 47, 45,}, 0, },
{	0x45, 0x03, "AMP+ROTARY SPEAKER", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 5, 90, 0, 0, 0, 25, 68, 56, 52, 127, 0, 0, 0, 4, 48, 45,}, 0, },
{	0x46, 0x00, "TREMOLO", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 83, 56, 0, 0, 0, 28, 64, 46, 64, 0, 40, 64, 10, 64, 0, 0,}, 0, },
{	0x47, 0x00, "AUTO PAN", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 76, 80, 32, 5, 0, 28, 64, 46, 64, 0, 40, 64, 10, 0, 0, 0,}, 0, },
{	0x48, 0x00, "PHASER 1", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 8, 111, 74, 104, 0, 28, 64, 46, 64, 64, 6, 1, 0, 0, 0, 0,}, 9, },
{	0x48, 0x08, "PHASER 2", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 8, 111, 74, 108, 0, 28, 64, 46, 64, 64, 5, 0, 4, 0, 0, 0,}, 9, },
{	0x49, 0x00, "DISTORTION", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 40, 20, 72, 53, 48, 0, 43, 74, 10, 127, 120, 0, 0, 0, 0, 0,}, 0,}, 
{	0x49, 0x01, "COMPRESSOR + DISTORTION", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 40, 20, 72, 53, 48, 0, 43, 74, 10, 127, 120, 6, 2, 100, 4, 0,}, 0,}, 
{	0x49, 0x08, "STEREO DISTORTION", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 18, 27, 71, 48, 84, 0, 32, 66, 10, 127, 105, 0, 0, 0, 0, 0,}, 0,}, 
{	0x4A, 0x00, "OVERDRIVE", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 29, 24, 68, 45, 55, 0, 41, 72, 10, 127, 104, 0, 0, 0, 0, 0,}, 0,}, 
{	0x4A, 0x08, "STEREO OVERDRIVE", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 10, 24, 69, 46, 105, 0, 41, 66, 10, 127, 104, 0, 0, 0, 0, 0,}, 0,}, 
{	0x4B, 0x00, "AMP SIMULATOR", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 39, 1, 48, 55, 0, 0, 0, 0, 0, 127, 112, 0, 0, 0, 0, 0,}, 0,}, 
{	0x4B, 0x01, "AMP SIMULATOR 2", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 39, 1, 48, 55, 0, 0, 0, 0, 0, 127, 112, 0, 0, 0, 0, 0,}, 0,}, 
{	0x4B, 0x08, "STEREO AMP SIMULATOR", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 16, 2, 46, 119, 0, 0, 0, 0, 0, 127, 106, 0, 0, 0, 0, 0,}, 0,}, 
{	0x4C, 0x00, "3-BAND EQ", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 70, 34, 60, 10, 70, 28, 46, 0, 0, 127, 0, 0, 0, 0, 0, 0,}, -1,}, 
{	0x4D, 0x00, "2-BAND EQ", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 28, 70, 46, 70, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0,}, -1,}, 
{	0x4E, 0x00, "AUTO WAH", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 70, 56, 39, 25, 0, 28, 66, 46, 64, 127, 0, 0, 0, 0, 0, 0,}, 2, },
{	0x4E, 0x01, "AUTO WAH + DISTORTION", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 40, 73, 26, 29, 0, 28, 66, 46, 64, 127, 30, 72, 74, 53, 48, 0,}, 2, },
{	0x4E, 0x02, "AUTO WAH + OVERDRIVE", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 48, 64, 32, 23, 0, 28, 66, 46, 64, 127, 29, 68, 72, 45, 55, 0,}, 2, },
{	0x50, 0x00, "PITCH_CHANGE 1", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 64, 0, 74, 54, 64, 0, 0, 0, 0, 64, 1, 127, 127, 127, 0, 0,}, 9, },
{	0x50, 0x01, "PITCH_CHANGE 2", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 65, 50, 67, 61, 87, 0, 0, 0, 0, 32, 1, 127, 127, 127, 0, 0,}, 9, },
{	0x51, 0x00, "HARMONIC ENHANCER", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},{ 44, 30, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, -1,},
{	0x52, 0x00, "TOUCH_WAH 1", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 36, 0, 30, 0, 0, 28, 66, 46, 64, 127, 0, 0, 0, 0, 0, 0,}, 1, },
{	0x52, 0x01, "TOUCH_WAH + DISTORTION", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 36, 0, 30, 0, 0, 28, 66, 46, 64, 127, 30, 0, 0, 0, 0, 0,}, 1, },
{	0x52, 0x02, "TOUCH_WAH + OVERDRIVE", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 45, 18, 28, 0, 0, 28, 66, 46, 64, 127, 29, 68, 72, 45, 55, 64,}, 1, },
{	0x52, 0x08, "TOUCH_WAH 2", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 68, 18, 60, 0, 0, 28, 66, 46, 64, 127, 0, 72, 74, 53, 57, 64,}, 1, },
{	0x53, 0x00, "COMPRESSOR", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 6, 2, 100, 4, 96, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0,}, -1, },
{	0x54, 0x00, "NOISE GATE", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 0, 11, 82, 50, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0,}, -1, },
{	0x56, 0x00, "2WAY ROTARY SPEAKER", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 10, 26, 35, 70, 0, 24, 60, 45, 54, 127, 31, 45, 0, 0, 0, 0,}, 0, },
{	0x56, 0x01, "DIST + 2WAY ROTARY SPEAKER", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 6, 28, 30, 64, 0, 24, 66, 66, 59, 127, 36, 40, 0, 3, 48, 60,}, 0, },
{	0x56, 0x02, "OVERDRIVE + 2WAY ROTARY SPEAKER", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 6, 28, 30, 63, 0, 20, 67, 56, 60, 127, 33, 40, 0, 4, 46, 50,}, 0, },
{	0x56, 0x03, "AMP SIM + 2WAY ROTARY SPEAKER", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 8, 27, 29, 64, 0, 17, 66, 58, 52, 127, 33, 40, 3, 3, 48, 62,}, 0, },
{	0x57, 0x00, "ENSEMBLE DETUNE", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 54, 0, 0, 0, 0, 0, 0, 0, 0, 64, 28, 64, 46, 64, 0, 0,}, 9, },
{	0x58, 0x00, "AMBIENCE", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 114, 0, 0, 0, 28, 64, 46, 64, 64, 0, 0, 0, 0, 0, 0, 0,}, 9, },
{	0x5D, 0x00, "TALKING MODULATOR", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 0, 15, 31, 63, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0,}, 1, },
{	0x5E, 0x00, "LO-FI",{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{	2, 60, 6, 54, 5, 10, 1, 1, 0, 127, 0, 0, 0, 0, 1, 0,}, 9, },
{	0x5F, 0x00, "DISTORTION + DELAY", { 19, 23, 29, 0, 0, 0, 0, 0, 0, 0,}, { 68, 56, 38, 74, 70, 40, 48, 72, 74, 127, 0, 0, 0, 0, 0, 0,}, 9, },
{	0x5F, 0x01, "OVERDRIVE + DELAY", { 11, 10, 19, 0, 0, 0, 0, 0, 0, 0,}, { 92, 120, 68, 78, 60, 25, 55, 68, 72, 127, 0, 0, 0, 0, 0, 0,}, 9, },
{	0x60, 0x00, "COMP + DISTORTION + DELAY", { 23, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 56, 72, 66, 40, 48, 72, 74, 0, 0, 127, 6, 2, 100, 4, 0, 0,}, 9, },
{	0x60, 0x01, "COMP + OVERDRIVE + DELAY", { 23, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 56, 72, 66, 29, 55, 68, 72, 0, 0, 127, 6, 2, 100, 4, 0, 0,}, 9, },
{	0x61, 0x00, "WAH + DISTORTION + DELAY", { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 92, 84, 64, 30, 48, 69, 72, 0, 0, 127, 40, 0, 30, 64, 0, 0,}, 9, },
{	0x61, 0x01, "WAH + OVERDRIVE + DELAY", { 11, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 92, 84, 64, 24, 55, 65, 70, 0, 0, 127, 40, 0, 30, 64, 0, 0,}, 9, },
{	0x62, 0x00, "V DISTORTION HARD", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 22, 3, 2, 5, 88, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0,}, 9, },
{	0x62, 0x01, "V DISTORTION HARD + DELAY", { 0, 0, 0, 0, 0, 19, 39, 39, 0, 0,}, { 22, 3, 2, 5, 82, 68, 8, 8, 65, 127, 46, 0, 0, 0, 0, 0,}, 9, },
{	0x62, 0x02, "V DISTORTION SOFT", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 13, 3, 2, 6, 98, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0,}, 9, },
{	0x62, 0x03, "V DISTORTION SOFT + DELAY", { 0, 0, 0, 0, 0, 19, 39, 39, 0, 0,}, { 14, 3, 2, 6, 92, 68, 8, 8, 76, 127, 44, 0, 0, 0, 0, 0,}, 9, },
{	0x63, 0x00, "DUAL ROTAR SPEAKER 1", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 15, 18, 89, 91, 54, 22, 20, 22, 52, 127, 14, 72, 34, 61, 60, 0,}, 15, },
{	0x63, 0x01, "DUAL ROTAR SPEAKER 2", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 14, 18, 91, 95, 54, 22, 22, 22, 64, 127, 34, 64, 34, 64, 6, 0,}, 15, },
{	0x64, 0x00, "DISTORTION + TEMPO DELAY", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 11, 86, 62, 8, 88, 70, 68, 64, 64, 127, 0, 0, 0, 0, 0, 0,}, 9, },
{	0x64, 0x01, "OVERDRIVE + TEMPO DELAY", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 11, 78, 64, 10, 110, 68, 70, 70, 64, 127, 0, 0, 0, 0, 0, 0,}, 9, },
{	0x65, 0x00, "COMP + DISTORTION + TEMPO DELAY", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 11, 76, 62, 10, 90, 72, 74, 70, 64, 127, 4, 4, 101, 3, 0, 0,}, 9, },
{	0x65, 0x01, "COMP + OVERDRIVE + TEMPO DELAY", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 11, 74, 62, 9, 94, 74, 74, 70, 64, 127, 8, 9, 103, 3, 0, 0,}, 9, },
{	0x66, 0x00, "WAH + DISTORTION + TEMPO DELAY", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 11, 86, 52, 10, 120, 68, 64, 70, 64, 127, 50, 0, 30, 64, 0, 0,}, 9, },
{	0x66, 0x01, "WAH + OVERDRIVE + TEMPO DELAY", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 11, 84, 58, 16, 127, 68, 65, 70, 64, 127, 64, 0, 30, 64, 0, 0,}, 9, },
{	0x67, 0x00, "V DISTORTION HARD + TEMPO DELAY", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 22, 3, 2, 5, 82, 11, 90, 72, 64, 127, 64, 0, 0, 0, 0, 0,}, 9, },
{	0x67, 0x01, "V DISTORTION SOFT + TEMPO DELAY", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 14, 3, 2, 6, 90, 11, 92, 77, 64, 127, 66, 0, 0, 0, 0, 0,}, 9, },
{	0x68, 0x00, "V-FLANGER", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 14, 14, 0, 2, 104, 20, 64, 46, 64, 127, 40, 64, 10, 4, 0, 0,}, 9, },
{	0x6B, 0x00, "TEMPO FLANGER", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 10, 14, 104, 2, 0, 28, 64, 46, 64, 96, 40, 64, 10, 4, 0, 0,}, 9, },
{	0x6C, 0x00, "TEMPO PHASER", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 15, 111, 74, 104, 0, 28, 64, 46, 64, 64, 6, 1, 0, 0, 0, 0,}, 9, },
{	0x71, 0x00, "RING MODULATOR", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 20, 64, 1, 64, 10, 0, 64, 0, 0, 127, 0, 0, 20, 64, 50, 64,}, 0, },
{	0x7F, 0x01, "3D MANUAL", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 64, 64, 40, 2, 10, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0,}, 0, },
{	0x7F, 0x02, "3D AUTO", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, { 64, 64, 40, 0, 0, 0, 0, 0, 0,127, 0, 0, 0, 0, 0, 0,}, 4, },
{	-1, -1, "EOF",{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, 0,},
};

/**************** SD MFX effect_parameter ****************/
struct effect_parameter_sd_t effect_parameter_sd[] = {
{	0x00, "None",				{   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x01, "Stereo EQ",			{   0,  22,   1,  19,   7,   0,  17,  16,   0,  16, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, 10, -1, -1, -1, -1, -1, -1, -1,},
{	0x02, "Overdrive",			{ 127,  64,   0,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0,  1, -1, -1, -1, -1, -1, -1,},
{	0x03, "Distortion",			{ 127,  64,   3,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0,  1, -1, -1, -1, -1, -1, -1,},
{	0x04, "Phaser",				{  30,  19,  64,   0, 127,  64, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0,  1, -1, -1, -1, -1, -1, -1,},
{	0x05, "Spectrum",			{  15,  15,  15,  15,  15,  15,  15,  15,   0,  64, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, 10,  9, -1, -1, -1, -1, -1, -1,},
{	0x06, "Enhancer",			{ 127,  64,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0,  1, -1, -1, -1, -1, -1, -1,},
{	0x07, "Auto Wah",			{   0,  19,  64,   0,  64, 100, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  4,  1, -1, -1, -1, -1, -1, -1,},
{	0x08, "Rotary",				{  39,  39, 121, 121,   0,  10, 127, 127, 127, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  4, 10, -1, -1, -1, -1, -1, -1,},
{	0x09, "Compressor",			{ 127,  64,  64,   0,  15,  15,  127,  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  5,  6, -1, -1, -1, -1, -1, -1,},
{	0x0A, "Limiter",			{  64,  32,   2,  64,   1,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  7,  3, -1, -1, -1, -1, -1, -1,},
{	0x0B, "Hexa-Chorus",		{   5,   9,  20,   0,  20,  50,  80,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  1,  6, -1, -1, -1, -1, -1, -1,},
{	0x0C, "Tremolo Chorus",		{   0,   9,  50,  39, 127,  90,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3,  6, -1, -1, -1, -1, -1, -1,},
{	0x0D, "Space-D",			{  10,   9,  20,  90,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  1,  6, -1, -1, -1, -1, -1, -1,},
{	0x0E, "Stereo Chorus",		{   2,   7,  10,   9,  20,  90,   0,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3,  9, -1, -1, -1, -1, -1, -1,},
{	0x0F, "Stereo Flanger",		{   2,   7,  10,   9,  50,  90,  89,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3,  6, -1, -1, -1, -1, -1, -1,},
{	0x10, "Step Flanger",		{   5,   9,  50,  89,  49,  90,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3,  4, -1, -1, -1, -1, -1, -1,},
{	0x11, "Stereo Delay",		{   0, 126, 126,   0,   0,  59,  17,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  5,  9, -1, -1, -1, -1, -1, -1,},
{	0x12, "Mod Delay",			{   0, 126, 126,  59,  17,  19,  20,  90,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  5, 10, -1, -1, -1, -1, -1, -1,},
{	0x13, "3Tap Delay",			{  10,  60, 115,  59,  17, 127, 127, 127,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3, 10, -1, -1, -1, -1, -1, -1,},
{	0x14, "4Tap Delay",			{ 115,  90,  60,  10, 127, 127, 127, 127,  59,  17,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  8, 10, -1, -1, -1, -1, -1, -1,},
{	0x15, "Tm Ctrl Delay",		{  10,  59,  10,  17,  64,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0,  1, -1, -1, -1, -1, -1, -1,},
{	0x16, "2Pitch Shifter",		{   0,  24,  24,  50,  50,   0,   0,  64,  64,  50,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -2, -3, -1, -1, -1, -1, -1, -1,},
{	0x17, "Fb Pitch Shifter",	{   0,  24,  50,   0,  59,  46,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -4,  4, -1, -1, -1, -1, -1, -1,},
{	0x18, "Reverb",				{   0,  10,  10,  17,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  2,  6, -1, -1, -1, -1, -1, -1,},
{	0x19, "Gate Reverb",		{   0,  10,  10,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  5,  6, -1, -1, -1, -1, -1, -1,},
{	0x1A, "OD->Chorus",			{  64,  64,  10,   9,  20,   0,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  1,  6, -1, -1, -1, -1, -1, -1,},
{	0x1B, "OD->Flanger",		{  64,  64,  10,   9,  40,  89,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  1,  6, -1, -1, -1, -1, -1, -1,},
{	0x1C, "OD->Delay",			{  64,  64,  10,  59,  17,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  1,  5, -1, -1, -1, -1, -1, -1,},
{	0x1D, "DS->Chorus",			{ 127,  64,  10,   9,  20,   0,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  1,  6, -1, -1, -1, -1, -1, -1,},
{	0x1E, "DS->Flanger",		{ 127,  64,  10,   9,  40,  89,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  1,  6, -1, -1, -1, -1, -1, -1,},
{	0x1F, "DS->Delay",			{ 127,  64,  10,  59,  17,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  1,  5, -1, -1, -1, -1, -1, -1,},
{	0x20, "Enhancer->Chorus",	{ 127,  64,  10,   9,  20,   0,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0,  6, -1, -1, -1, -1, -1, -1,},
{	0x21, "Enhancer->Flanger",	{ 127,  64,  10,   9,  40,  89,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0,  6, -1, -1, -1, -1, -1, -1,},
{	0x22, "Enhancer->Delay",	{ 127, 127,  64,  10,  59,  17,  50,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0,  5, -1, -1, -1, -1, -1, -1,},
{	0x23, "Chorus->Delay",		{  10,   9,  20,   0,  50,  10,  59,  17,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  4,  8, -1, -1, -1, -1, -1, -1,},
{	0x24, "Flanger->Delay",		{  10,   9,  40,  89,  50,  10,  59,  17,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3,  8, -1, -1, -1, -1, -1, -1,},
{	0x25, "Chorus->Flanger",	{  10,   9,  20,  50,  10,   9,  40,  89,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3,  8, -1, -1, -1, -1, -1, -1,},
{	0x26, "Chorus/Delay",		{  10,   9,  20,   0,  50,  10,  59,  17,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  4,  8, -1, -1, -1, -1, -1, -1,},
{	0x27, "Flanger/Delay",		{  10,   9,  40,  89,  50,  10,  59,  17,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3,  8, -1, -1, -1, -1, -1, -1,},
{	0x28, "Chorus/Flanger",		{  10,   9,  20,  50,  10,   9,  40,  89,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3,  8, -1, -1, -1, -1, -1, -1,},
{	0x29, "Stereo Phaser",		{   0,   1,   1,  10,  64,  64,  64,  69,   0,  50, 127,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  5,  3,  9, -1, -1, -1, -1, -1,},
{	0x2A, "Key Sync Flanger",	{   0,   7,   5,  10,  50,  89,   0, 200,  90,   1,  60,   0,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3,  5,  7, 14, -1, -1, -1, -1,},
{	0x2B, "Formant Filter",		{   1, 127,   0,   1,  20, 127,   1,  60,  50,  15,  15,  64, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x2C, "Ring Modulator",		{  60,   1,   1,   0,   0,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0,  3,  7, -1, -1, -1, -1, -1,},
{	0x2D, "Multi Tap Delay",	{1816,1815,1813,1810,   0,  32,  96, 127, 127, 127, 127, 127,  59,  17,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, 12, 16, -1, -1, -1, -1, -1, -1,},
{	0x2E, "Reverse Delay",		{  30, 913, 910, 913, 913,  49,  54,  17,  17,  64,   0, 127, 127,  64,  64,  50,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  5,  6, 15, -1, -1, -1, -1, -1,},
{	0x2F, "Shuffle Delay",		{1813,  67,   0, 127,  50,  59,  17,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0,  1, 10, -1, -1, -1, -1, -1,},
{	0x30, "3D Delay",			{1810,1813,1815,  64,  64,  40,  59,  17,  15,  15,  40, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  6, 11, -1, -1, -1, -1, -1, -1,},
{	0x31, "3Pitch Shifter",		{   0,  12,   0,   0,  50,  50,  50,   0,   0,   0,  49,  49,  49,  64,   0, 127, 127, 127, 127, 100, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -5, -6, -7, 10, 11, 12, -1, -1,},
{	0x32, "LoFi Compress",		{   1,   5,   1,   1,  13, 100,  15,  15,  64, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  5, -1, -1, -1, -1, -1, -1, -1,},
{	0x33, "LoFi Noise",			{   2,   1,  13,   0,  64,   0,  17,   0, 100,  15,  15,  64, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3,  8, -1, -1, -1, -1, -1, -1,},
{	0x34, "Speaker Simulator",	{   6,   1, 127,   0, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  2,  3,  4, -1, -1, -1, -1, -1,},
{	0x35, "Overdrive 2",		{ 127,  50,  64,   1,   0,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0,  2, -1, -1, -1, -1, -1, -1,},
{	0x36, "Distortion 2",		{ 127,  50,  64,   1,   3,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0,  2, -1, -1, -1, -1, -1, -1,},
{	0x37, "Stereo Compressor",	{ 127,  64,   0,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  5, -1, -1, -1, -1, -1, -1, -1,},
{	0x38, "Stereo Limiter",		{  64,  32,   2,   1,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  6, -1, -1, -1, -1, -1, -1, -1,},
{	0x39, "Gate",				{   0,  70,   1,   0, 100,   0,   0,   0, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  4, -1, -1, -1, -1, -1, -1, -1,},
{	0x3A, "Slicer",				{ 127,   0,   0,   0,   0,   0, 127,   0,   0,   0, 127,   0,   0, 127,   0,   0,  40,  50,   1,  60,   1,   0,   0, 127,   0,   0,   0,   0,   0,   0,   0,   0, }, 16, 18, 22, -1, -1, -1, -1, -1,},
{	0x3B, "Isolator",			{  60,  60,  60,   0, 127,   0, 127,   0, 127, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  2,  1,  0, -1, -1, -1, -1, -1,},
{	0x3C, "3D Chorus",			{   0,   7,  10,  10,  20,  90,   0,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3,  9, -1, -1, -1, -1, -1, -1,},
{	0x3D, "3D Flanger",			{   0,   7,   5,  10,  50,  89,   0, 200,  90,   0,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3,  4,  7, 12, -1, -1, -1, -1,},
{	0x3E, "Tremoro",			{   0,  80,  96,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  1,  2, -1, -1, -1, -1, -1, -1,},
{	0x3F, "Auto Pan",			{   0,  40,  96,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  1,  2, -1, -1, -1, -1, -1, -1,},
{	0x40, "Stereo Phaser 2",	{   0,   1,   1,  10,  64,  64,  64,  69,   0,  50, 127,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  5,  3,  9, -1, -1, -1, -1, -1,},
{	0x41, "Stereo Auto Wah",	{   1,  20,  40,  60, 100,  40,   1,  45,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3,  4,  1,  2,  7, -1, -1, -1,},
{	0x42, "St Formant Filter",	{   1, 127,   0,   1,  20, 127,   0,   1,  60,  50,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  1,  4,  5,  9,  7, -1, -1, -1,},
{	0x43, "Multi Tap Delay 2",	{3016,3015,3013,3010,   0,  32,  96, 127, 127, 127, 127, 127,  59,  17,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, 12, 16, -1, -1, -1, -1, -1, -1,},
{	0x44, "Reverse Delay 2",	{  30,1516,1513,1516,1516,  49,  54,  17,  17,  64,   0, 127, 127,  64,  64,  50,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  5,  6, 15, -1, -1, -1, -1, -1,},
{	0x45, "Shuffle Delay 2",	{3013,  67,   0, 127,  50,  59,  17,  15,  15,  50, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0,  1,  5, 10, -1, -1, -1, -1,},
{	0x46, "3D Delay 2",			{3010,3013,3015,  64,  64,  40,  59,  17,  15,  15,  40, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  6, 11, -1, -1, -1, -1, -1, -1,},
{	0x47, "Rotary 2",			{  40, 160,  64,  64, 127,  40, 160,  64,  64, 127,   0,   0,  10,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, 10, 11, 15, -1, -1, -1, -1, -1,},
{	0x48, "Rotary Multi",		{   1,   0,  64,  50,  80,   1,   0,   1,  15,   7,   0,  15,  15,   1,  40,  40, 160, 160,   0,  10,  10, 127, 127, 127,  64, 127,   0,   0,   0,   0,   0,   0, },  2, 18, 24, -1, -1, -1, -1, -1,},
{	0x49, "Keyboard Multi",		{   1,  60,  50,   1,  15,   7,   0,  15,  15,   1,   0,  31,  50,   0,  59,  50,   1,   1,  64,  10,  64,  64,  64,   1,3013,3010,  59,  17,  50, 127,   0,   0, },  1,  2, -8, 14, 18, 19, 28, -1,},
{	0x4A, "Rhodes Multi",		{   1, 127,  64,   1,   1,  64,  10,  64,  64,  64,   1,   0,  10,  10,  20,  89,   0,   7,  50,   1,   0,   0,  80,  64, 127,   0,   0,   0,   0,   0,   0,   0, },  1,  5,  6, 18, 22, 23, -1, -1,},
{	0x4B, "JD Multi",			{   0,   1,   0,  50,  50,   1,  42,  10,  50,  50,  50,   1,  15,  15,  15,  15,  15,  15,   0,   1,  50,  50,  64, 127,   0,   0,   0,   0,   0,   0,   0,   0, }, 31,  6, 10,  7,  8,  9, 21, -1,},
{	0x4C, "St LoFi Compress",	{   1,   5,   1,   1,  13, 100,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  5, -1, -1, -1, -1, -1, -1, -1,},
{	0x4D, "St LoFi Noise",		{   2,   1,  13,   0,  64,   1,  17,   0,   0,  17,   0,   0,  17,   0, 100,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  3, 14, -1, -1, -1, -1, -1, -1,},
{	0x4E, "Gtr Amp Simulator",  {   1,   2,  90, 100,   1,  64,  64,  75,   0,   0,   1,   6,   1, 127,   0,  64, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  2,  3, 16, 15, -1, -1, -1, -1,},
{	0x4F, "Stereo Overdrive",	{ 127,  50,   1,   0,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0, -1, -1, -1, -1, -1, -1, -1,},
{	0x50, "Stereo Distortion",	{ 127,  50,   1,   3,  15,  15, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0, -1, -1, -1, -1, -1, -1, -1,},
{	0x51, "Guitar Multi A",		{   1,  64, 127,  80,   1,   0,  64,  50,  80,   1,   0,   1,3013,3010,  59,  17,  50,   1,   0,  10,  10,  20,  89,   0,   7,  50,  64, 127,   0,   0,   0,   0, },  3,  6, 16, 25, -1, -1, -1, -1,},
{	0x52, "Guitar Multi B",		{   1,  64, 127,  80,   1,   0,  64,  50,  80,   1,   0,   1,  15,   7,   0,  15,  15,   1,   0,  10,  10,  20,  89,   0,   7,  50,  64, 127,  50,  64, 127,   0, },  3,  6, 25, -1, -1, -1, -1, -1,},
{	0x53, "Guitar Multi C",		{   1,   0,  64,  50,  64,   1,   0,  20,   0,  32,  32,  50,   1,   0,   1,3013,3010,  59,  17,  50,   1,   0,  10,  10,  20,  89,   0,   7,   0,   0,   0,   0, },  2, 10, 19, 28, -1, -1, -1, -1,},
{	0x54, "Clean Gtr Multi A",	{   1,  64, 127,  80,   1,  15,   7,   0,  15,  15,   1,3013,3010,  59,  17,  50,   1,   0,  10,  10,  20,  89,   0,   7,  50,  64, 127,   0,   0,   0,   0,   0, },  3, 15, 24, -1, -1, -1, -1, -1,},
{	0x55, "Clean Gtr Multi B",	{   1,   0,  20,   0,  32,  32,  50,   1,  15,   7,   0,  15,  15,   1,3013,3010,  59,  17,  50,   1,   0,  10,  10,  20,  89,   0,   7,  50,  64, 127,   0,   0, },  5, 18, 27, -1, -1, -1, -1, -1,},
{	0x56, "Base Multi",			{   1,  64, 127,  80,   1,   0,  64,  80,   1,   0,   1,  15,   7,   0,  15,  15,   1,   0,  10,  10,  20,  89,   0,   7,  50,  64, 127,   0,   0,   0,   0,   0, },  3,  6, 24, -1, -1, -1, -1, -1,},
{	0x57, "Isolator 2",			{  60,  60,  60,   0, 127,   0, 127,   0,   1,   0,  80,   0,   0,   0, 127, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  2,  1,  0, -1, -1, -1, -1, -1,},
{	0x58, "Stereo Spectrum",	{  15,  15,  15,  15,  15,  15,  15,  15,   0, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  9, -1, -1, -1, -1, -1, -1, -1,},
{	0x59, "3D Auto Spin",		{  15,  26,   1,   1,   0, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  1,  3, -1, -1, -1, -1, -1, -1,},
{	0x5A, "3D Manual",			{  15,   0, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },  0, -1, -1, -1, -1, -1, -1, -1,},
// SD Chorus
{	0x60, "Chorus",				{   7,   5,   0,  45, 112,   0,  10,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x61, "Delay",				{  20,   0,   7,  18,  84, 127, 127, 127,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x62, "GM2 Chorus1",		{   0,   3,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x63, "GM2 Chorus2",		{   1,   9,  19,   5,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x64, "GM2 Chorus3",		{   2,   3,  19,   8,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x65, "GM2 Chorus4",		{   3,   9,  16,  16,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x66, "GM2 Fb.Chorus",		{   4,   2,  24,  64,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x67, "GM2 Flanger",		{   5,   1,   5, 112,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
// SD Reverb
{	0x68, "Reverb Room1",		{   0,  80,  17,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x69, "Reverb Room2",		{   1,  56,  16,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x6A, "Reverb Stage1",		{   2,  64,  15,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x6B, "Reverb Stage2",		{   3,  78,  14,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x6C, "Reverb Hall1",		{   4,  72,  13,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x6D, "Reverb Hall2",		{   5,  64,  12,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x6E, "Reverb Delay",		{   6,  32,  16,  40,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x6F, "Reverb PanDelay",	{   7,  64,  12,  32,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x70, "SRV Room",			{  10,  75,   1,  20,  60,  10,   0,  64,   5,  64,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x71, "SRV Hall",			{  70,  90,   7,  20,  90,  90,   1,  64,   3,  64,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x72, "SRV Plate",			{   5,  75,   6,  20, 110,  50,   2,  64,   4,  64,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x73, "GM2 Small Room",		{   0,  44,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x74, "GM2 Medium Room",	{   1,  50,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x75, "GM2 Large Room",		{   2,  56,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x76, "GM2 Medium Hall",	{   3,  64,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x77, "GM2 Large Hall",		{   4,  64,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x78, "GM2 Plate",			{   5,  50,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
// for effect test
{	0x7E, "Test 1",				{   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
{	0x7F, "Test 2", 			{   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},

{	  -1, "EOF",				{   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, }, -1, -1, -1, -1, -1, -1, -1, -1,},
};

/**************** EFFECT effect_engine ****************/
///r
struct _EffectEngine effect_engine[] = {
{	EFFECT_NONE, "None", NULL, NULL, NULL, NULL, 0,},

{	EFFECT_GS_POST_EQ, "Post EQ", do_gs_post_eq, conv_gs_post_eq, NULL, NULL, sizeof(Info_GS_PostEQ),},
{	EFFECT_GS_STEREO_EQ, "Stereo-EQ", do_gs_stereo_eq, conv_gs_stereo_eq, NULL, NULL, sizeof(Info_GS_StereoEQ),},
{	EFFECT_GS_SPECTRUM, "Spectrum", do_gs_spectrum, conv_gs_spectrum, NULL, NULL, sizeof(Info_GS_Spectrum),},
{	EFFECT_GS_ENHANCER, "Enhancer",do_gs_enhancer, conv_gs_enhancer, NULL, NULL, sizeof(Info_GS_Enhancer),},
{	EFFECT_GS_HUMANIZER, "Humanizer", do_gs_humanizer, conv_gs_humanizer, NULL, NULL, sizeof(Info_GS_Humanizer),},
{	EFFECT_GS_OVERDRIVE1, "Overdrive", do_gs_overdrive, conv_gs_overdrive, NULL, NULL, sizeof(Info_GS_Overdrive),},
{	EFFECT_GS_DISTORTION1, "Distortion", do_gs_distortion, conv_gs_distortion, NULL, NULL, sizeof(Info_GS_Overdrive),},
{	EFFECT_GS_PHASER, "Phaser", do_gs_phaser, conv_gs_phaser, NULL, NULL, sizeof(Info_GS_Phaser),},
{	EFFECT_GS_AUTO_WAH, "Auto Wah", do_gs_auto_wah, conv_gs_auto_wah, NULL, NULL, sizeof(Info_GS_AutoWah),},
{	EFFECT_GS_ROTARY, "Rotary", do_gs_rotary, conv_gs_rotary, NULL, NULL, sizeof(Info_GS_Rotary),},
{	EFFECT_GS_STEREO_FLANGER, "Stereo Flanger", do_gs_stereo_flanger, conv_gs_stereo_flanger, NULL, NULL, sizeof(Info_GS_StereoFlanger),},
{	EFFECT_GS_STEP_FLANGER, "Step Flanger", do_gs_step_flanger, conv_gs_step_flanger, NULL, NULL, sizeof(Info_GS_StepFlanger),},
{	EFFECT_GS_TREMOLO, "Tremolo", do_gs_tremolo, conv_gs_tremolo, NULL, NULL, sizeof(Info_GS_Tremolo),},
{	EFFECT_GS_AUTO_PAN, "Auto Pan", do_gs_auto_pan, conv_gs_auto_pan, NULL, NULL, sizeof(Info_GS_Tremolo),},
{	EFFECT_GS_COMPRESSOR, "Compressor", do_gs_compressor, conv_gs_compressor, NULL, NULL, sizeof(Info_GS_Compressor),},
{	EFFECT_GS_LIMITER, "Limiter", do_gs_limiter, conv_gs_limiter, NULL, NULL, sizeof(Info_GS_Limiter),},
{	EFFECT_GS_HEXA_CHORUS, "Hexa-Chorus", do_gs_hexa_chorus, conv_gs_hexa_chorus, NULL, NULL, sizeof(Info_GS_HexaChorus),},
{	EFFECT_GS_TREMOLO_CHORUS, "Tremolo Chorus", do_gs_tremolo_chorus, conv_gs_tremolo_chorus, NULL, NULL, sizeof(Info_GS_TremoloChorus),},
{	EFFECT_GS_STEREO_CHORUS, "Stereo Chorus", do_gs_stereo_chorus, conv_gs_stereo_chorus, NULL, NULL, sizeof(Info_GS_StereoChorus),},
{	EFFECT_GS_SPACE_D, "Space D", do_gs_space_d, conv_gs_space_d, NULL, NULL, sizeof(Info_GS_SpaceD),},
{	EFFECT_GS_3D_CHORUS, "3D Chorus", do_gs_3d_chorus, conv_gs_3d_chorus, NULL, NULL, sizeof(Info_GS_3DChorus),},
{	EFFECT_GS_STEREO_DELAY, "Stereo Delay", do_gs_stereo_delay, conv_gs_stereo_delay, NULL, NULL, sizeof(Info_GS_StereoDelay),},
{	EFFECT_GS_MOD_DELAY, "Mod Delay", do_gs_mod_delay, conv_gs_mod_delay, NULL, NULL, sizeof(Info_GS_ModDelay),},
{	EFFECT_GS_3TAP_DELAY, "3 Tap Delay", do_gs_3tap_delay, conv_gs_3tap_delay, NULL, NULL, sizeof(Info_GS_3TapDelay),},
{	EFFECT_GS_4TAP_DELAY, "4 Tap Delay", do_gs_4tap_delay, conv_gs_4tap_delay, NULL, NULL, sizeof(Info_GS_4TapDelay),},
{	EFFECT_GS_TM_CTRL_DELAY, "Tm Ctrl Delay", do_gs_tm_ctrl_delay, conv_gs_tm_ctrl_delay, NULL, NULL, sizeof(Info_GS_TmCtrlDelay),},
{	EFFECT_GS_REVERB, "Reverb", do_gs_reverb, conv_gs_reverb, NULL, NULL, sizeof(Info_GS_Reverb),},
{	EFFECT_GS_GATE_REVERB, "Gate Reverb", do_gs_gate_reverb, conv_gs_gate_reverb, NULL, NULL, sizeof(Info_GS_GateReverb),},
{	EFFECT_GS_3D_DELAY, "3D Delay", do_gs_3d_delay, conv_gs_3d_delay, NULL, NULL, sizeof(Info_GS_3DDelay),},
{	EFFECT_GS_2PITCH_SHIFTER, "2 Pitch Shifter", do_gs_2pitch_shifter, conv_gs_2pitch_shifter, NULL, NULL, sizeof(Info_GS_2PitchShifter),},
{	EFFECT_GS_FB_P_SHIFTER, "Fb P.Shifter", do_gs_fb_pitch_shifter, conv_gs_fb_pitch_shifter, NULL, NULL, sizeof(Info_GS_FbPitchShifter),},
{	EFFECT_GS_3D_AUTO, "3D Auto", do_gs_3d_auto, conv_gs_3d_auto, NULL, NULL, sizeof(Info_GS_3DAuto),},
{	EFFECT_GS_3D_MANUAL, "3D Manual", do_gs_3d_manual, conv_gs_3d_manual, NULL, NULL, sizeof(Info_GS_3DManual),},
{	EFFECT_GS_LOFI1, "Lo-Fi 1", do_gs_lofi1, conv_gs_lofi1, NULL, NULL, sizeof(Info_GS_LoFi1),},
{	EFFECT_GS_LOFI2, "Lo-Fi 2", do_gs_lofi2, conv_gs_lofi2, NULL, NULL, sizeof(Info_GS_LoFi2),},
{	EFFECT_GS_S_OD_CHORUS, "OD->Chorus", do_gs_s_od_chorus, conv_gs_s_od_chorus, NULL, NULL, sizeof(Info_GS_S_OD_Chorus),},
{	EFFECT_GS_S_OD_FLANGER, "OD->Flanger", do_gs_s_od_flanger, conv_gs_s_od_flanger, NULL, NULL, sizeof(Info_GS_S_OD_Flanger),},
{	EFFECT_GS_S_OD_DELAY, "OD->Delay", do_gs_s_od_delay, conv_gs_s_od_delay, NULL, NULL, sizeof(Info_GS_S_OD_Delay),},
{	EFFECT_GS_S_DS_CHORUS, "DS->Chorus", do_gs_s_ds_chorus, conv_gs_s_ds_chorus, NULL, NULL, sizeof(Info_GS_S_DS_Chorus),},
{	EFFECT_GS_S_DS_FLANGER, "DS->Flanger", do_gs_s_ds_flanger, conv_gs_s_ds_flanger, NULL, NULL, sizeof(Info_GS_S_DS_Flanger),},
{	EFFECT_GS_S_DS_DELAY, "DS->Delay", do_gs_s_ds_delay, conv_gs_s_ds_delay, NULL, NULL, sizeof(Info_GS_S_DS_Delay),},
{	EFFECT_GS_S_EH_CHORUS, "EH->Chorus", do_gs_s_enhancer_chorus, conv_gs_s_enhancer_chorus, NULL, NULL, sizeof(Info_GS_S_EH_Chorus),},
{	EFFECT_GS_S_EH_FLANGER, "EH->Flanger", do_gs_s_enhancer_flanger, conv_gs_s_enhancer_flanger, NULL, NULL, sizeof(Info_GS_S_EH_Flanger),},
{	EFFECT_GS_S_EH_DELAY, "EH->Delay", do_gs_s_enhancer_delay, conv_gs_s_enhancer_delay, NULL, NULL, sizeof(Info_GS_S_EH_Delay),},
{	EFFECT_GS_S_CHO_DELAY, "Cho->Delay", do_gs_s_chorus_delay, conv_gs_s_chorus_delay, NULL, NULL, sizeof(Info_GS_S_Cho_Delay),},
{	EFFECT_GS_S_FL_DELAY, "FL->Delay", do_gs_s_flanger_delay, conv_gs_s_flanger_delay, NULL, NULL, sizeof(Info_GS_S_FL_Delay),},
{	EFFECT_GS_S_CHO_FLANGER, "Cho->Flanger", do_gs_s_chorus_flanger, conv_gs_s_chorus_flanger, NULL, NULL, sizeof(Info_GS_S_Cho_Flanger),},
{	EFFECT_GS_S_ROTARY_MULTI, "Rotary Multi", do_gs_s_rotary_multi, conv_gs_s_rotary_multi, NULL, NULL, sizeof(Info_GS_S_RotaryMulti),},
{	EFFECT_GS_S_GTR_MULTI1, "GTR Multi 1", do_gs_s_gtr_multi1, conv_gs_s_gtr_multi1, NULL, NULL, sizeof(Info_GS_S_GtMulti1),},
{	EFFECT_GS_S_GTR_MULTI2, "GTR Multi 2", do_gs_s_gtr_multi2, conv_gs_s_gtr_multi2, NULL, NULL, sizeof(Info_GS_S_GtMulti2),},
{	EFFECT_GS_S_GTR_MULTI3, "GTR Multi 3", do_gs_s_gtr_multi3, conv_gs_s_gtr_multi3, NULL, NULL, sizeof(Info_GS_S_GtMulti3),},
{	EFFECT_GS_S_CLEAN_GT_MULTI1, "Clean Gt Multi 1", do_gs_s_clean_gt_multi1, conv_gs_s_clean_gt_multi1, NULL, NULL, sizeof(Info_GS_S_CleanGtMulti1),},
{	EFFECT_GS_S_CLEAN_GT_MULTI2, "Clean Gt Multi 2", do_gs_s_clean_gt_multi2, conv_gs_s_clean_gt_multi2, NULL, NULL, sizeof(Info_GS_S_CleanGtMulti2),},
{	EFFECT_GS_S_BASE_MULTI, "Base Multi", do_gs_s_base_multi, conv_gs_s_base_multi, NULL, NULL, sizeof(Info_GS_S_BaseMulti),},
{	EFFECT_GS_S_RHODES_MULTI, "Rhodes Multi", do_gs_s_rhodes_multi, conv_gs_s_rhodes_multi, NULL, NULL, sizeof(Info_GS_S_RhodesMulti),},
{	EFFECT_GS_S_KEYBOARD_MULTI, "Keyboard Multi", do_gs_s_keyboard_multi, conv_gs_s_keyboard_multi, NULL, NULL, sizeof(Info_GS_S_KeyboardMulti),},
{	EFFECT_GS_P_CHO_DELAY, "Cho/Delay", do_gs_p_chorus_delay, conv_gs_p_chorus_delay, NULL, NULL, sizeof(Info_GS_P_Cho_Delay),},
{	EFFECT_GS_P_FL_DELAY, "FL/Delay", do_gs_p_flanger_delay, conv_gs_p_flanger_delay, NULL, NULL, sizeof(Info_GS_P_FL_Delay),},
{	EFFECT_GS_P_CHO_FLANGER, "Cho/Flanger", do_gs_p_chorus_flanger, conv_gs_p_chorus_flanger, NULL, NULL, sizeof(Info_GS_P_Cho_Flanger),},
{	EFFECT_GS_P_OD1_OD2, "OD1/OD2", do_gs_p_od1_od2, conv_gs_p_od1_od2, NULL, NULL, sizeof(Info_GS_P_OD1_OD2),},
{	EFFECT_GS_P_OD_ROTARY, "OD/Rotary", do_gs_p_od_rotary, conv_gs_p_od_rotary, NULL, NULL, sizeof(Info_GS_P_OD_Rotary),},
{	EFFECT_GS_P_OD_PHASER, "OD/Phaser", do_gs_p_od_phaser, conv_gs_p_od_phaser, NULL, NULL, sizeof(Info_GS_P_OD_Phaser),},
{	EFFECT_GS_P_OD_AUTOWAH, "OD/AutoWah", do_gs_p_od_auto_wah, conv_gs_p_od_auto_wah, NULL, NULL, sizeof(Info_GS_P_OD_AutoWah),},
{	EFFECT_GS_P_PH_ROTARY, "PH/Rotary", do_gs_p_phaser_rotary, conv_gs_p_phaser_rotary, NULL, NULL, sizeof(Info_GS_P_PH_Rotary),},
{	EFFECT_GS_P_PH_AUTOWAH, "PH/AutoWah", do_gs_p_phaser_auto_wah, conv_gs_p_phaser_auto_wah, NULL, NULL, sizeof(Info_GS_P_PH_AutoWah),},

{	EFFECT_XG_HALL1, "Hall 1", do_xg_reverb1, NULL, conv_xg_reverb1, NULL, sizeof(Info_XG_Reverb1),},
{	EFFECT_XG_HALL2, "Hall 2", do_xg_reverb1, NULL, conv_xg_reverb1, NULL, sizeof(Info_XG_Reverb1),},
{	EFFECT_XG_HALL_M, "Hall M", do_xg_reverb1, NULL, conv_xg_reverb1, NULL, sizeof(Info_XG_Reverb1),},
{	EFFECT_XG_HALL_L, "Hall L", do_xg_reverb1, NULL, conv_xg_reverb1, NULL, sizeof(Info_XG_Reverb1),},
{	EFFECT_XG_ROOM1, "Room 1", do_xg_reverb1, NULL, conv_xg_reverb1, NULL, sizeof(Info_XG_Reverb1),},
{	EFFECT_XG_ROOM2, "Room 2", do_xg_reverb1, NULL, conv_xg_reverb1, NULL, sizeof(Info_XG_Reverb1),},
{	EFFECT_XG_ROOM3, "Room 3", do_xg_reverb1, NULL, conv_xg_reverb1, NULL, sizeof(Info_XG_Reverb1),},
{	EFFECT_XG_ROOM_S, "Room S", do_xg_reverb1, NULL, conv_xg_reverb1, NULL, sizeof(Info_XG_Reverb1),},
{	EFFECT_XG_ROOM_M, "Room M", do_xg_reverb1, NULL, conv_xg_reverb1, NULL, sizeof(Info_XG_Reverb1),},
{	EFFECT_XG_ROOM_L, "Room L", do_xg_reverb1, NULL, conv_xg_reverb1, NULL, sizeof(Info_XG_Reverb1),},
{	EFFECT_XG_STAGE1, "Stage 1", do_xg_reverb1, NULL, conv_xg_reverb1, NULL, sizeof(Info_XG_Reverb1),},
{	EFFECT_XG_STAGE2, "Stage 2", do_xg_reverb1, NULL, conv_xg_reverb1, NULL, sizeof(Info_XG_Reverb1),},
{	EFFECT_XG_PLATE, "Plate", do_xg_plate, NULL, conv_xg_plate, NULL, sizeof(Info_XG_Plate),},
{	EFFECT_XG_GM_PLATE, "GM Plate", do_xg_plate, NULL, conv_xg_plate, NULL, sizeof(Info_XG_Plate),},
{	EFFECT_XG_DELAY_LCR, "Delay L,C,R", do_xg_delay_lcr, NULL, conv_xg_delay_lcr, NULL, sizeof(Info_XG_DelayLCR),},
{	EFFECT_XG_DELAY_LR, "Delay L,R", do_xg_delay_lr, NULL, conv_xg_delay_lr, NULL, sizeof(Info_XG_DelayLR),},
{	EFFECT_XG_ECHO, "Echo", do_xg_echo, NULL, conv_xg_echo, NULL, sizeof(Info_XG_Echo),},
{	EFFECT_XG_CROSS_DELAY, "Cross Delay", do_xg_cross_delay, NULL, conv_xg_cross_delay, NULL, sizeof(Info_XG_CrossDelay),},
{	EFFECT_XG_EARLY_REF1, "Early Ref 1", do_xg_early_ref1, NULL, conv_xg_early_ref1, NULL, sizeof(Info_XG_EarlyRef1),},
{	EFFECT_XG_EARLY_REF2, "Early Ref 2", do_xg_early_ref2, NULL, conv_xg_early_ref2, NULL, sizeof(Info_XG_EarlyRef2),},
{	EFFECT_XG_GATE_REVERB, "Gate Reverb", do_xg_gate_reverb, NULL, conv_xg_gate_reverb, NULL, sizeof(Info_XG_GateReverb),},
{	EFFECT_XG_REVERSE_GATE, "Reverse Gate", do_xg_gate_reverb, NULL, conv_xg_gate_reverb, NULL, sizeof(Info_XG_GateReverb),},
{	EFFECT_XG_WHITE_ROOM, "White Room", do_xg_reverb2, NULL, conv_xg_reverb2, NULL, sizeof(Info_XG_Reverb2),},
{	EFFECT_XG_TUNNEL, "Tunnel", do_xg_reverb2, NULL, conv_xg_reverb2, NULL, sizeof(Info_XG_Reverb2),},
{	EFFECT_XG_CANYON, "Canyon", do_xg_reverb2, NULL, conv_xg_reverb2, NULL, sizeof(Info_XG_Reverb2),},
{	EFFECT_XG_BASEMENT, "Basement", do_xg_reverb2, NULL, conv_xg_reverb2, NULL, sizeof(Info_XG_Reverb2),},
{	EFFECT_XG_KARAOKE1, "Karaoke 1", do_xg_karaoke, NULL, conv_xg_karaoke, NULL, sizeof(Info_XG_Karaoke),},
{	EFFECT_XG_KARAOKE2, "Karaoke 2", do_xg_karaoke, NULL, conv_xg_karaoke, NULL, sizeof(Info_XG_Karaoke),},
{	EFFECT_XG_KARAOKE3, "Karaoke 3", do_xg_karaoke, NULL, conv_xg_karaoke, NULL, sizeof(Info_XG_Karaoke),},
{	EFFECT_XG_TEMPO_DELAY, "Tempo Delay", do_xg_tempo_delay, NULL, conv_xg_tempo_delay, NULL, sizeof(Info_XG_TempoDelay),},
{	EFFECT_XG_TEMPO_ECHO, "Tempo Echo", do_xg_tempo_echo, NULL, conv_xg_tempo_echo, NULL, sizeof(Info_XG_TempoEcho),},
{	EFFECT_XG_TEMPO_CROSS, "Tempo Cross", do_xg_tempo_cross, NULL, conv_xg_tempo_cross, NULL, sizeof(Info_XG_TempoCross),},
{	EFFECT_XG_CHORUS1, "Chorus 1", do_xg_chorus, NULL, conv_xg_chorus, NULL, sizeof(Info_XG_Chorus),},
{	EFFECT_XG_CHORUS2, "Chorus 2", do_xg_chorus, NULL, conv_xg_chorus, NULL, sizeof(Info_XG_Chorus),},
{	EFFECT_XG_CHORUS3, "Chorus 3", do_xg_chorus, NULL, conv_xg_chorus, NULL, sizeof(Info_XG_Chorus),},
{	EFFECT_XG_GM_CHORUS1, "GM Chorus 1", do_xg_chorus, NULL, conv_xg_chorus_gm, NULL, sizeof(Info_XG_Chorus),},
{	EFFECT_XG_GM_CHORUS2, "GM Chorus 2", do_xg_chorus, NULL, conv_xg_chorus_gm, NULL, sizeof(Info_XG_Chorus),},
{	EFFECT_XG_GM_CHORUS3, "GM Chorus 3", do_xg_chorus, NULL, conv_xg_chorus_gm, NULL, sizeof(Info_XG_Chorus),},
{	EFFECT_XG_GM_CHORUS4, "GM Chorus 4", do_xg_chorus, NULL, conv_xg_chorus_gm, NULL, sizeof(Info_XG_Chorus),},
{	EFFECT_XG_FB_CHORUS, "FB Chorus", do_xg_chorus, NULL, conv_xg_chorus_gm, NULL, sizeof(Info_XG_Chorus),},
{	EFFECT_XG_CHORUS4, "Chorus4", do_xg_chorus, NULL, conv_xg_chorus, NULL, sizeof(Info_XG_Chorus),},
{	EFFECT_XG_CELESTE1, "Celeste 1", do_xg_celeste, NULL, conv_xg_celeste, NULL, sizeof(Info_XG_Celeste),},
{	EFFECT_XG_CELESTE2, "Celeste 2", do_xg_celeste, NULL, conv_xg_celeste, NULL, sizeof(Info_XG_Celeste),},
{	EFFECT_XG_CELESTE3, "Celeste 3", do_xg_celeste, NULL, conv_xg_celeste, NULL, sizeof(Info_XG_Celeste),},
{	EFFECT_XG_CELESTE4, "Celeste 4", do_xg_celeste, NULL, conv_xg_celeste, NULL, sizeof(Info_XG_Celeste),},
{	EFFECT_XG_FLANGER1, "Flanger 1", do_xg_flanger, NULL, conv_xg_flanger, NULL, sizeof(Info_XG_Flanger),},
{	EFFECT_XG_FLANGER2, "Flanger 2", do_xg_flanger, NULL, conv_xg_flanger, NULL, sizeof(Info_XG_Flanger),},
{	EFFECT_XG_GM_FLANGER, "GM2 Flanger", do_xg_flanger, NULL, conv_xg_flanger_gm, NULL, sizeof(Info_XG_Flanger),},
{	EFFECT_XG_FLANGER3, "Flanger 3", do_xg_flanger, NULL, conv_xg_flanger, NULL, sizeof(Info_XG_Flanger),},
{	EFFECT_XG_SYMPHONIC, "Symphonic", do_xg_symphonic, NULL, conv_xg_symphonic, NULL, sizeof(Info_XG_Symphonic),},
{	EFFECT_XG_ROTARY_SPEAKER, "Rotary Speaker", do_xg_rotary_speaker, NULL, conv_xg_rotary_speaker, NULL, sizeof(Info_XG_RotarySpeaker),},
{	EFFECT_XG_DS_ROTARY_SPEAKER, "DS + Rotary Speaker", do_xg_ds_rotary_speaker, NULL, conv_xg_ds_rotary_speaker, NULL, sizeof(Info_XG_DS_RotarySpeaker),},
{	EFFECT_XG_OD_ROTARY_SPEAKER, "OD + Rotary Speaker", do_xg_od_rotary_speaker, NULL, conv_xg_od_rotary_speaker, NULL, sizeof(Info_XG_OD_RotarySpeaker),},
{	EFFECT_XG_AMP_ROTARY_SPEAKER, "AmpSim + Rotary Speaker", do_xg_amp_rotary_speaker, NULL, conv_xg_amp_rotary_speaker, NULL, sizeof(Info_XG_AMP_RotarySpeaker),},
{	EFFECT_XG_TREMOLO, "Tremolo", do_xg_tremolo, NULL, conv_xg_tremolo, NULL, sizeof(Info_XG_Tremolo),},
{	EFFECT_XG_AUTO_PAN, "Auto Pan", do_xg_auto_pan, NULL, conv_xg_auto_pan, NULL, sizeof(Info_XG_AutoPan),},
{	EFFECT_XG_PHASER1, "Phaser 1", do_xg_phaser1, NULL, conv_xg_phaser1, NULL, sizeof(Info_XG_Phaser1),},
{	EFFECT_XG_PHASER2, "Phaser 2", do_xg_phaser2, NULL, conv_xg_phaser2, NULL, sizeof(Info_XG_Phaser2),},
{	EFFECT_XG_DISTORTION, "Distortion", do_xg_distortion, NULL, conv_xg_distortion, NULL, sizeof(Info_XG_Distortion),},
{	EFFECT_XG_COMP_DISTORTION, "Comp + Distortion", do_xg_comp_distortion, NULL, conv_xg_comp_distortion, NULL, sizeof(Info_XG_Comp_Distortion),},
{	EFFECT_XG_STEREO_DISTORTION, "Stereo Distortion", do_xg_st_distortion, NULL, conv_xg_st_distortion, NULL, sizeof(Info_XG_StDistortion),},
{	EFFECT_XG_OVERDRIVE, "Overdrive", do_xg_overdrive, NULL, conv_xg_overdrive, NULL, sizeof(Info_XG_Overdrive),},
{	EFFECT_XG_STEREO_OVERDRIVE, "Stereo Overdrive", do_xg_st_overdrive, NULL, conv_xg_st_overdrive, NULL, sizeof(Info_XG_StOverdrive),},
{	EFFECT_XG_AMP_SIMULATOR, "Amp Simulator", do_xg_amp_simulator, NULL, conv_xg_amp_simulator, NULL, sizeof(Info_XG_AmpSimulator),},
{	EFFECT_XG_AMP_SIMULATOR2, "Amp Simulator2", do_xg_amp_simulator, NULL, conv_xg_amp_simulator, NULL, sizeof(Info_XG_AmpSimulator),},
{	EFFECT_XG_STEREO_AMP_SIMULATOR, "Stereo Amp Simulator", do_xg_st_amp_simulator, NULL, conv_xg_st_amp_simulator, NULL, sizeof(Info_XG_StAmpSimulator),},
{	EFFECT_XG_EQ3, "3-Band EQ", do_xg_eq3, NULL, conv_xg_eq3, NULL, sizeof(Info_XG_EQ3),},
{	EFFECT_XG_EQ2, "2-Band EQ", do_xg_eq2, NULL, conv_xg_eq2, NULL, sizeof(Info_XG_EQ2),},
{	EFFECT_XG_AUTO_WAH, "Auto Wah", do_xg_auto_wah, NULL, conv_xg_auto_wah, NULL, sizeof(Info_XG_AutoWah),},
{	EFFECT_XG_AUTO_WAH_DS, "Auto Wah + Distortion", do_xg_auto_wah_ds, NULL, conv_xg_auto_wah_ds, NULL, sizeof(Info_XG_AutoWah_DS),},
{	EFFECT_XG_AUTO_WAH_OD, "Auto Wah + Overdrive", do_xg_auto_wah_od, NULL, conv_xg_auto_wah_od, NULL, sizeof(Info_XG_AutoWah_OD),},
{	EFFECT_XG_PITCH_CHANGE1, "Pitch Change 1", do_xg_pitch_change1, NULL, conv_xg_pitch_change1, NULL, sizeof(Info_XG_PitchChange1),},
{	EFFECT_XG_PITCH_CHANGE2, "Pitch Change 2", do_xg_pitch_change2, NULL, conv_xg_pitch_change2, NULL, sizeof(Info_XG_PitchChange2),},
{	EFFECT_XG_TOUCH_WAH1, "Touch Wah 1", do_xg_touch_wah1, NULL, conv_xg_touch_wah1, NULL, sizeof(Info_XG_TouchWah1),},
{	EFFECT_XG_TOUCH_WAH_DS, "Touch Wah + Distortion", do_xg_touch_wah_ds, NULL, conv_xg_touch_wah_ds, NULL, sizeof(Info_XG_TouchWah_DS),},
{	EFFECT_XG_TOUCH_WAH_OD, "Touch Wah + Overdrive", do_xg_touch_wah_od, NULL, conv_xg_touch_wah_od, NULL, sizeof(Info_XG_TouchWah_OD),},
{	EFFECT_XG_TOUCH_WAH2, "Touch Wah 2", do_xg_touch_wah2, NULL, conv_xg_touch_wah2, NULL, sizeof(Info_XG_TouchWah1),},
{	EFFECT_XG_HARMONIC_ENHANCER, "Harmonic Enhancer", do_xg_harmonic_enhancer, NULL, conv_xg_harmonic_enhancer, NULL, sizeof(Info_XG_HarmonicEnhancer),},
{	EFFECT_XG_COMPRESSOR, "Compressor", do_xg_compressor, NULL, conv_xg_compressor, NULL, sizeof(Info_XG_Compressor),},
{	EFFECT_XG_NOISE_GATE, "Noise Gate", do_xg_noise_gate, NULL, conv_xg_noise_gate, NULL, sizeof(Info_XG_NoiseGate),},
{	EFFECT_XG_2WAY_ROTARY_SPEAKER, "2Way Rotary Speaker", do_xg_2way_rotary_speaker, NULL, conv_xg_2way_rotary_speaker, NULL, sizeof(Info_XG_2WayRotarySpeaker),},
{	EFFECT_XG_DS_2WAY_ROTARY_SPEAKER, "DS + 2Way Rotary Speaker", do_xg_ds_2way_rotary_speaker, NULL, conv_xg_ds_2way_rotary_speaker, NULL, sizeof(Info_XG_DS_2WayRotarySpeaker),},
{	EFFECT_XG_OD_2WAY_ROTARY_SPEAKER, "OD + 2Way Rotary Speaker", do_xg_od_2way_rotary_speaker, NULL, conv_xg_od_2way_rotary_speaker, NULL, sizeof(Info_XG_OD_2WayRotarySpeaker),},
{	EFFECT_XG_AMP_2WAY_ROTARY_SPEAKER, "AMP + 2Way Rotary Speaker", do_xg_amp_2way_rotary_speaker, NULL, conv_xg_amp_2way_rotary_speaker, NULL, sizeof(Info_XG_AMP_2WayRotarySpeaker),},
{	EFFECT_XG_ENSEMBLE_DETUNE, "Ensemble Detune", do_xg_ensemble_detune, NULL, conv_xg_ensemble_detune, NULL, sizeof(Info_XG_EnsembleDetune),},
{	EFFECT_XG_AMBIENCE, "Ambience", do_xg_ambience, NULL, conv_xg_ambience, NULL, sizeof(Info_XG_Ambience),},
{	EFFECT_XG_TALKING_MODULATOR, "Talking Modulator", do_xg_talking_modulator, NULL, conv_xg_talking_modulator, NULL, sizeof(Info_XG_TalkingModulator),},
{	EFFECT_XG_LOFI, "Lo-Fi", do_xg_lofi, NULL, conv_xg_lofi, NULL, sizeof(Info_XG_LoFi),},
{	EFFECT_XG_DS_DELAY, "Distortion + Delay", do_xg_ds_delay, NULL, conv_xg_ds_delay, NULL, sizeof(Info_XG_DS_Delay),},
{	EFFECT_XG_OD_DELAY, "Overdrive + Delay", do_xg_od_delay, NULL, conv_xg_od_delay, NULL, sizeof(Info_XG_OD_Delay),},
{	EFFECT_XG_COMP_DS_DELAY, "Comp + Distortion + Delay", do_xg_comp_ds_delay, NULL, conv_xg_comp_ds_delay, NULL, sizeof(Info_XG_Comp_DS_Delay),},
{	EFFECT_XG_COMP_OD_DELAY, "Comp + Overdrive + Delay", do_xg_comp_od_delay, NULL, conv_xg_comp_od_delay, NULL, sizeof(Info_XG_Comp_OD_Delay),},
{	EFFECT_XG_WAH_DS_DELAY, "Wah + Distortion + Delay", do_xg_wah_ds_delay, NULL, conv_xg_wah_ds_delay, NULL, sizeof(Info_XG_Wah_DS_Delay),},
{	EFFECT_XG_WAH_OD_DELAY, "Wah + Overdrive + Delay", do_xg_wah_od_delay, NULL, conv_xg_wah_od_delay, NULL, sizeof(Info_XG_Wah_OD_Delay),},
{	EFFECT_XG_V_DIST_HARD, "V Distortion Hard", do_xg_v_ds_hard, NULL, conv_xg_v_ds_hard, NULL, sizeof(Info_XG_VDistortionHard),},
{	EFFECT_XG_V_DIST_HARD_DELAY, "V Distortion Hard + Delay", do_xg_v_ds_hard_delay, NULL, conv_xg_v_ds_hard_delay, NULL, sizeof(Info_XG_VDistortionHard_Delay),},
{	EFFECT_XG_V_DIST_SOFT, "V Distortion Soft", do_xg_v_ds_soft, NULL, conv_xg_v_ds_soft, NULL, sizeof(Info_XG_VDistortionSoft),},
{	EFFECT_XG_V_DIST_SOFT_DELAY, "V Distortion Soft + Delay", do_xg_v_ds_soft_delay, NULL, conv_xg_v_ds_soft_delay, NULL, sizeof(Info_XG_VDistortionSoft_Delay),},
{	EFFECT_XG_DUAL_ROTAR_SPEAKER1, "Dual_Rotar_Speaker 1", do_xg_dual_rotar_speaker, NULL, conv_xg_dual_rotar_speaker, NULL, sizeof(Info_XG_DualRotarSpeaker),},
{	EFFECT_XG_DUAL_ROTAR_SPEAKER2, "Dual_Rotar_Speaker 2", do_xg_dual_rotar_speaker, NULL, conv_xg_dual_rotar_speaker, NULL, sizeof(Info_XG_DualRotarSpeaker),},
{	EFFECT_XG_DS_TEMPO_DELAY, "Distortion + Tempo Delay", do_xg_comp_ds_tempo_delay, NULL, conv_xg_comp_ds_tempo_delay, NULL, sizeof(Info_XG_DS_TempoDelay),},
{	EFFECT_XG_OD_TEMPO_DELAY, "Overdrive + Tempo Delay", do_xg_od_tempo_delay, NULL, conv_xg_od_tempo_delay, NULL, sizeof(Info_XG_OD_TempoDelay),},
{	EFFECT_XG_COMP_DS_TEMPO_DELAY, "Comp + Distortion + Tempo Delay", do_xg_comp_ds_tempo_delay, NULL, conv_xg_comp_ds_tempo_delay, NULL, sizeof(Info_XG_Comp_DS_TempoDelay),},
{	EFFECT_XG_COMP_OD_TEMPO_DELAY, "Comp + Overdrive + Tempo Delay", do_xg_comp_od_tempo_delay, NULL, conv_xg_comp_od_tempo_delay, NULL, sizeof(Info_XG_Comp_OD_TempoDelay),},
{	EFFECT_XG_WAH_DS_TEMPO_DELAY, "Wah + Distortion + Tempo Delay", do_xg_wah_ds_tempo_delay, NULL, conv_xg_wah_ds_tempo_delay, NULL, sizeof(Info_XG_Wah_DS_TempoDelay),},
{	EFFECT_XG_WAH_OD_TEMPO_DELAY, "Wah + Overdrive + Tempo Delay", do_xg_wah_od_tempo_delay, NULL, conv_xg_wah_od_tempo_delay, NULL, sizeof(Info_XG_Wah_OD_TempoDelay),},
{	EFFECT_XG_V_DIST_HARD_TEMPO_DELAY, "V Distortion Hard + Tempo Delay", do_xg_v_ds_hard_tempo_delay, NULL, conv_xg_v_ds_hard_tempo_delay, NULL, sizeof(Info_XG_VDistortionHard_TempoDelay),},
{	EFFECT_XG_V_DIST_SOFT_TEMPO_DELAY, "V Distortion Soft + Tempo Delay", do_xg_v_ds_soft_tempo_delay, NULL, conv_xg_v_ds_soft_tempo_delay, NULL, sizeof(Info_XG_VDistortionSoft_TempoDelay),},
{	EFFECT_XG_V_FLANGER, "V-Flanger", do_xg_v_flanger, NULL, conv_xg_v_flanger, NULL, sizeof(Info_XG_VFlanger),},
{	EFFECT_XG_TEMPO_FLANGER, "Tempo Flanger", do_xg_tempo_flanger, NULL, conv_xg_tempo_flanger, NULL, sizeof(Info_XG_TempoFlanger),},
{	EFFECT_XG_TEMPO_PHASER, "Tempo Phaser", do_xg_tempo_phaser, NULL, conv_xg_tempo_phaser, NULL, sizeof(Info_XG_TempoPhaser),},
{	EFFECT_XG_RING_MODULATOR, "Ring Modulator", do_xg_ring_modulator, NULL, conv_xg_ring_modulator, NULL, sizeof(Info_XG_RingModulator),},
{	EFFECT_XG_3D_MANUAL, "3D Manual", do_xg_3d_manual, NULL, conv_xg_3d_manual, NULL, sizeof(Info_XG_3DManual),},
{	EFFECT_XG_3D_AUTO, "3D Auto", do_xg_3d_auto, NULL, conv_xg_3d_auto, NULL, sizeof(Info_XG_3DAuto),},

// SD Chorus
{	EFFECT_SD_CHO_CHORUS, "Chorus", do_sd_chorus1, NULL, NULL, conv_sd_chorus1, sizeof(Info_SD_Cho_Chorus),},
{	EFFECT_SD_CHO_DELAY, "Chorus Delay", do_sd_delay3, NULL, NULL, conv_sd_delay3, sizeof(Info_SD_Cho_Delay),},
{	EFFECT_SD_CHO_CHORUS1, "GM2 Chorus1", do_sd_chorus1, NULL, NULL, conv_sd_gm2_chorus, sizeof(Info_SD_Cho_Chorus),},
{	EFFECT_SD_CHO_CHORUS2, "GM2 Chorus2", do_sd_chorus1, NULL, NULL, conv_sd_gm2_chorus, sizeof(Info_SD_Cho_Chorus),},
{	EFFECT_SD_CHO_CHORUS3, "GM2 Chorus3", do_sd_chorus1, NULL, NULL, conv_sd_gm2_chorus, sizeof(Info_SD_Cho_Chorus),},
{	EFFECT_SD_CHO_CHORUS4, "GM2 Chorus4", do_sd_chorus1, NULL, NULL, conv_sd_gm2_chorus, sizeof(Info_SD_Cho_Chorus),},
{	EFFECT_SD_CHO_FB_CHORUS, "GM2 Fb.Chorus", do_sd_chorus1, NULL, NULL, conv_sd_gm2_chorus, sizeof(Info_SD_Cho_Chorus),},
{	EFFECT_SD_CHO_FLANGER, "GM2 Flanger", do_sd_chorus1, NULL, NULL, conv_sd_gm2_chorus, sizeof(Info_SD_Cho_Chorus),},
// SD Reverb
{	EFFECT_SD_REV_ROOM1, "Reverb Room1", do_sd_reverb1, NULL, NULL, conv_sd_reverb1, sizeof(Info_SD_Rev_Reverb),},
{	EFFECT_SD_REV_ROOM2, "Reverb Room2", do_sd_reverb1, NULL, NULL, conv_sd_reverb1, sizeof(Info_SD_Rev_Reverb),},
{	EFFECT_SD_REV_STAGE1, "Reverb Stage1", do_sd_reverb1, NULL, NULL, conv_sd_reverb1, sizeof(Info_SD_Rev_Reverb),},
{	EFFECT_SD_REV_STAGE2, "Reverb Stage2", do_sd_reverb1, NULL, NULL, conv_sd_reverb1, sizeof(Info_SD_Rev_Reverb),},
{	EFFECT_SD_REV_HALL1, "Reverb Hall1", do_sd_reverb1, NULL, NULL, conv_sd_reverb1, sizeof(Info_SD_Rev_Reverb),},
{	EFFECT_SD_REV_HALL2, "Reverb Hall2", do_sd_reverb1, NULL, NULL, conv_sd_reverb1, sizeof(Info_SD_Rev_Reverb),},
{	EFFECT_SD_REV_DELAY, "Reverb Delay", do_sd_delay2, NULL, NULL, conv_sd_delay2, sizeof(Info_SD_Rev_Delay),},
{	EFFECT_SD_REV_PANDELAY, "Reverb Pan-Delay", do_sd_delay2, NULL, NULL, conv_sd_delay2, sizeof(Info_SD_Rev_Delay),},
{	EFFECT_SD_REV_SRV_ROOM, "SRV Room", do_sd_reverb1, NULL, NULL, conv_sd_reverb2, sizeof(Info_SD_Rev_Reverb),},
{	EFFECT_SD_REV_SRV_HALL, "SRV Hall", do_sd_reverb1, NULL, NULL, conv_sd_reverb2, sizeof(Info_SD_Rev_Reverb),},
{	EFFECT_SD_REV_SRV_PLATE, "SRV Plate", do_sd_plate1, NULL, NULL, conv_sd_plate1, sizeof(Info_SD_Rev_Plate),},
{	EFFECT_SD_REV_SMALL_ROOM, "GM2 Small Room", do_sd_reverb1, NULL, NULL, conv_sd_gm2_reverb, sizeof(Info_SD_Rev_Reverb),},
{	EFFECT_SD_REV_MEDIUM_ROOM, "GM2 Medium Room", do_sd_reverb1, NULL, NULL, conv_sd_gm2_reverb, sizeof(Info_SD_Rev_Reverb),},
{	EFFECT_SD_REV_LARGE_ROOM, "GM2 Large Room", do_sd_reverb1, NULL, NULL, conv_sd_gm2_reverb, sizeof(Info_SD_Rev_Reverb),},
{	EFFECT_SD_REV_MEDIUM_HALL, "GM2 Medium Hall", do_sd_reverb1, NULL, NULL, conv_sd_gm2_reverb, sizeof(Info_SD_Rev_Reverb),},
{	EFFECT_SD_REV_LARGE_HALL, "GM2 Large Hall", do_sd_reverb1, NULL, NULL, conv_sd_gm2_reverb, sizeof(Info_SD_Rev_Reverb),},
{	EFFECT_SD_REV_PLATE, "GM2 Plate", do_sd_plate1, NULL, NULL, conv_sd_gm2_plate, sizeof(Info_SD_Rev_Plate),},
// SD MFX
{	EFFECT_SD_STEREO_EQ, "Stereo-EQ", do_sd_stereo_eq, NULL, NULL, conv_sd_stereo_eq, sizeof(Info_SD_StereoEQ),},
{	EFFECT_SD_OVERDRIVE, "Overdrive", do_sd_overdrive, NULL, NULL, conv_sd_overdrive, sizeof(Info_SD_Overdrive),},
{	EFFECT_SD_DISTORTION, "Distortion", do_sd_distortion, NULL, NULL, conv_sd_distortion, sizeof(Info_SD_Overdrive),},
{	EFFECT_SD_PHASER, "Phaser", do_sd_phaser, NULL, NULL, conv_sd_phaser, sizeof(Info_SD_Phaser),},
{	EFFECT_SD_SPECTRUM, "Spectrum", do_sd_spectrum, NULL, NULL, conv_sd_spectrum, sizeof(Info_SD_Spectrum),},
{	EFFECT_SD_ENHANCER, "Enhancer",do_sd_enhancer, NULL, NULL, conv_sd_enhancer, sizeof(Info_SD_Enhancer),},
{	EFFECT_SD_AUTO_WAH, "Auto Wah", do_sd_auto_wah, NULL, NULL, conv_sd_auto_wah, sizeof(Info_SD_AutoWah),},
{	EFFECT_SD_ROTARY, "Rotary", do_sd_rotary, NULL, NULL, conv_sd_rotary, sizeof(Info_SD_Rotary),},
{	EFFECT_SD_COMPRESSOR, "Compressor", do_sd_compressor, NULL, NULL, conv_sd_compressor, sizeof(Info_SD_Compressor),},
{	EFFECT_SD_LIMITER, "Limiter", do_sd_limiter, NULL, NULL, conv_sd_limiter, sizeof(Info_SD_Limiter),},
{	EFFECT_SD_HEXA_CHORUS, "Hexa-Chorus", do_sd_hexa_chorus, NULL, NULL, conv_sd_hexa_chorus, sizeof(Info_SD_HexaChorus),},
{	EFFECT_SD_TREMOLO_CHORUS, "Tremolo Chorus", do_sd_tremolo_chorus, NULL, NULL, conv_sd_tremolo_chorus, sizeof(Info_SD_TremoloChorus),},
{	EFFECT_SD_SPACE_D, "Space D", do_sd_space_d, NULL, NULL, conv_sd_space_d, sizeof(Info_SD_SpaceD),},
{	EFFECT_SD_STEREO_CHORUS, "Stereo Chorus", do_sd_stereo_chorus, NULL, NULL, conv_sd_stereo_chorus, sizeof(Info_SD_StereoChorus),},
{	EFFECT_SD_STEREO_FLANGER, "Stereo Flanger", do_sd_stereo_flanger, NULL, NULL, conv_sd_stereo_flanger, sizeof(Info_SD_StereoChorus),},
{	EFFECT_SD_STEP_FLANGER, "Step Flanger", do_sd_step_flanger, NULL, NULL, conv_sd_step_flanger, sizeof(Info_SD_StepFlanger),},
{	EFFECT_SD_STEREO_DELAY, "Stereo Delay", do_sd_stereo_delay, NULL, NULL, conv_sd_stereo_delay, sizeof(Info_SD_StereoDelay),},
{	EFFECT_SD_MOD_DELAY, "Mod Delay", do_sd_mod_delay, NULL, NULL, conv_sd_mod_delay, sizeof(Info_SD_ModDelay),},
{	EFFECT_SD_3TAP_DELAY, "3 Tap Delay", do_sd_3tap_delay, NULL, NULL, conv_sd_3tap_delay, sizeof(Info_SD_3TapDelay),},
{	EFFECT_SD_4TAP_DELAY, "4 Tap Delay", do_sd_4tap_delay, NULL, NULL, conv_sd_4tap_delay, sizeof(Info_SD_4TapDelay),},
{	EFFECT_SD_TM_CTRL_DELAY, "Tm Ctrl Delay", do_sd_tm_ctrl_delay, NULL, NULL, conv_sd_tm_ctrl_delay, sizeof(Info_SD_TmCtrlDelay),},
{	EFFECT_SD_2PITCH_SHIFTER, "2 Pitch Shifter", do_sd_2pitch_shifter, NULL, NULL, conv_sd_2pitch_shifter, sizeof(Info_SD_2PitchShifter),},
{	EFFECT_SD_FB_P_SHIFTER, "Fb P.Shifter", do_sd_fb_pitch_shifter, NULL, NULL, conv_sd_fb_pitch_shifter, sizeof(Info_SD_FbPitchShifter),},
{	EFFECT_SD_REVERB, "Reverb", do_sd_reverb, NULL, NULL, conv_sd_reverb, sizeof(Info_SD_Reverb),},
{	EFFECT_SD_GATE_REVERB, "Gate Reverb", do_sd_gate_reverb, NULL, NULL, conv_sd_gate_reverb, sizeof(Info_SD_GateReverb),},
{	EFFECT_SD_S_OD_CHORUS, "OD->Chorus", do_sd_s_od_chorus, NULL, NULL, conv_sd_s_od_chorus, sizeof(Info_SD_S_OD_Chorus),},
{	EFFECT_SD_S_OD_FLANGER, "OD->Flanger", do_sd_s_od_flanger, NULL, NULL, conv_sd_s_od_flanger, sizeof(Info_SD_S_OD_Flanger),},
{	EFFECT_SD_S_OD_DELAY, "OD->Delay", do_sd_s_od_delay, NULL, NULL, conv_sd_s_od_delay, sizeof(Info_SD_S_OD_Delay),},
{	EFFECT_SD_S_DS_CHORUS, "DS->Chorus", do_sd_s_ds_chorus, NULL, NULL, conv_sd_s_ds_chorus, sizeof(Info_SD_S_DS_Chorus),},
{	EFFECT_SD_S_DS_FLANGER, "DS->Flanger", do_sd_s_ds_flanger, NULL, NULL, conv_sd_s_ds_flanger, sizeof(Info_SD_S_DS_Flanger),},
{	EFFECT_SD_S_DS_DELAY, "DS->Delay", do_sd_s_ds_delay, NULL, NULL, conv_sd_s_ds_delay, sizeof(Info_SD_S_DS_Delay),},
{	EFFECT_SD_S_EH_CHORUS, "EH->Chorus", do_sd_s_enhancer_chorus, NULL, NULL, conv_sd_s_enhancer_chorus, sizeof(Info_SD_S_EH_Chorus),},
{	EFFECT_SD_S_EH_FLANGER, "EH->Flanger", do_sd_s_enhancer_flanger, NULL, NULL, conv_sd_s_enhancer_flanger, sizeof(Info_SD_S_EH_Flanger),},
{	EFFECT_SD_S_EH_DELAY, "EH->Delay", do_sd_s_enhancer_delay, NULL, NULL, conv_sd_s_enhancer_delay, sizeof(Info_SD_S_EH_Delay),},
{	EFFECT_SD_S_CHO_DELAY, "Cho->Delay", do_sd_s_chorus_delay, NULL, NULL, conv_sd_s_chorus_delay, sizeof(Info_SD_S_Cho_Delay),},
{	EFFECT_SD_S_FL_DELAY, "FL->Delay", do_sd_s_flanger_delay, NULL, NULL, conv_sd_s_flanger_delay, sizeof(Info_SD_S_FL_Delay),},
{	EFFECT_SD_S_CHO_FLANGER, "Cho->Flanger", do_sd_s_chorus_flanger, NULL, NULL, conv_sd_s_chorus_flanger, sizeof(Info_SD_S_Cho_Flanger),},
{	EFFECT_SD_P_CHO_DELAY, "Cho/Delay", do_sd_p_chorus_delay, NULL, NULL, conv_sd_p_chorus_delay, sizeof(Info_SD_P_Cho_Delay),},
{	EFFECT_SD_P_FL_DELAY, "FL/Delay", do_sd_p_flanger_delay, NULL, NULL, conv_sd_p_flanger_delay, sizeof(Info_SD_P_FL_Delay),},
{	EFFECT_SD_P_CHO_FLANGER, "Cho/Flanger", do_sd_p_chorus_flanger, NULL, NULL, conv_sd_p_chorus_flanger, sizeof(Info_SD_P_Cho_Flanger),},
{	EFFECT_SD_STEREO_PHASER, "Stereo Phaser", do_sd_stereo_phaser, NULL, NULL, conv_sd_stereo_phaser, sizeof(Info_SD_Phaser),},
{	EFFECT_SD_KEYSYNC_FLANGER, "Keysync Flanger", do_sd_keysync_flanger, NULL, NULL, conv_sd_keysync_flanger, sizeof(Info_SD_KeysyncFlanger),},
{	EFFECT_SD_FORMANT_FILTER, "Formant Filter", do_sd_formant_filter, NULL, NULL, conv_sd_formant_filter, sizeof(Info_SD_FormantFilter),},
{	EFFECT_SD_RING_MODULATOR, "Ring Modulator", do_sd_ring_modulator, NULL, NULL, conv_sd_ring_modulator, sizeof(Info_SD_RingModulator),},
{	EFFECT_SD_MULTITAP_DELAY, "MultiTap Delay", do_sd_multitap_delay, NULL, NULL, conv_sd_multitap_delay, sizeof(Info_SD_MultiTapDelay),},
{	EFFECT_SD_REVERSE_DELAY, "Reverse Delay", do_sd_reverse_delay, NULL, NULL, conv_sd_reverse_delay, sizeof(Info_SD_ReverseDelay),},
{	EFFECT_SD_SHUFFLE_DELAY, "Shuffle Delay", do_sd_shuffle_delay, NULL, NULL, conv_sd_shuffle_delay, sizeof(Info_SD_ShuffleDelay),},
{	EFFECT_SD_3D_DELAY, "3D Delay", do_sd_3d_delay, NULL, NULL, conv_sd_3d_delay, sizeof(Info_SD_3DDelay),},
{	EFFECT_SD_3PITCH_SHIFTER, "3 Voice Pitch Shifter", do_sd_3pitch_shifter, NULL, NULL, conv_sd_3pitch_shifter, sizeof(Info_SD_3VoicePitchShifter),},
{	EFFECT_SD_LOFI_COMPRESS, "Lo-Fi Compress", do_sd_lofi_compress, NULL, NULL, conv_sd_lofi_compress, sizeof(Info_SD_LoFi_Compress),},
{	EFFECT_SD_LOFI_NOISE, "Lo-Fi Noise", do_sd_lofi_noise, NULL, NULL, conv_sd_lofi_noise, sizeof(Info_SD_LoFi_Noise),},
{	EFFECT_SD_SPEAKER_SIMULATOR, "Speaker Simulator", do_sd_speaker_simulator, NULL, NULL, conv_sd_speaker_simulator, sizeof(Info_SD_SpeakerSimulator),},
{	EFFECT_SD_OVERDRIVE2, "Overdrive 2", do_sd_overdrive2, NULL, NULL, conv_sd_overdrive2, sizeof(Info_SD_Overdrive),},
{	EFFECT_SD_DISTORTION2, "Distortion 2", do_sd_distortion2, NULL, NULL, conv_sd_distortion2, sizeof(Info_SD_Overdrive),},
{	EFFECT_SD_STEREO_COMPRESSOR, "Stereo Compressor", do_sd_st_compressor, NULL, NULL, conv_sd_st_compressor, sizeof(Info_SD_Compressor),},
{	EFFECT_SD_STEREO_LIMITER, "Stereo Limiter", do_sd_st_limiter, NULL, NULL, conv_sd_st_limiter, sizeof(Info_SD_Limiter),},
{	EFFECT_SD_GATE, "Gate", do_sd_gate, NULL, NULL, conv_sd_gate, sizeof(Info_SD_Gate),},
{	EFFECT_SD_SLICER, "Slicer", do_sd_slicer, NULL, NULL, conv_sd_slicer, sizeof(Info_SD_Slicer),},
{	EFFECT_SD_ISOLATOR, "Isolator", do_sd_isolator, NULL, NULL, conv_sd_isolator, sizeof(Info_SD_Isolator),},
{	EFFECT_SD_3D_CHORUS, "3D Chorus", do_sd_3d_chorus, NULL, NULL, conv_sd_3d_chorus, sizeof(Info_SD_3DChorus),},
{	EFFECT_SD_3D_FLANGER, "3D Flanger", do_sd_3d_flanger, NULL, NULL, conv_sd_3d_flanger, sizeof(Info_SD_3DFlanger),},
{	EFFECT_SD_TREMOLO, "Tremolo", do_sd_tremolo, NULL, NULL, conv_sd_tremolo, sizeof(Info_SD_Tremolo),},
{	EFFECT_SD_AUTO_PAN, "Auto Pan", do_sd_auto_pan, NULL, NULL, conv_sd_auto_pan, sizeof(Info_SD_Tremolo),},
{	EFFECT_SD_STEREO_PHASER2, "Stereo Phaser 2", do_sd_stereo_phaser2, NULL, NULL, conv_sd_stereo_phaser2, sizeof(Info_SD_Phaser),},
{	EFFECT_SD_STEREO_AUTO_WAH, "Stereo Auto Wah", do_sd_stereo_auto_wah, NULL, NULL, conv_sd_stereo_auto_wah, sizeof(Info_SD_AutoWah),},
{	EFFECT_SD_STEREO_FORMANT_FILTER, "Stereo Formant Filter", do_sd_st_formant_filter, NULL, NULL, conv_sd_st_formant_filter, sizeof(Info_SD_FormantFilter),},
{	EFFECT_SD_MULTITAP_DELAY2, "MultiTap Delay 2", do_sd_multitap_delay2, NULL, NULL, conv_sd_multitap_delay2, sizeof(Info_SD_MultiTapDelay),},
{	EFFECT_SD_REVERSE_DELAY2, "Reverse Delay 2", do_sd_reverse_delay2, NULL, NULL, conv_sd_reverse_delay2, sizeof(Info_SD_ReverseDelay),},
{	EFFECT_SD_SHUFFLE_DELAY2, "Shuffle Delay 2", do_sd_shuffle_delay2, NULL, NULL, conv_sd_shuffle_delay2, sizeof(Info_SD_ShuffleDelay),},
{	EFFECT_SD_3D_DELAY2, "3D Delay 2", do_sd_3d_delay2, NULL, NULL, conv_sd_3d_delay2, sizeof(Info_SD_3DDelay),},
{	EFFECT_SD_ROTARY2, "Rotary 2", do_sd_rotary2, NULL, NULL, conv_sd_rotary2, sizeof(Info_SD_Rotary),},
{	EFFECT_SD_S_ROTARY_MULTI, "Rotary Multi", do_sd_s_rotary_multi, NULL, NULL, conv_sd_s_rotary_multi, sizeof(Info_SD_S_RotaryMulti),},
{	EFFECT_SD_S_KEYBOARD_MULTI, "Keyboard Multi", do_sd_s_keyboard_multi, NULL, NULL, conv_sd_s_keyboard_multi, sizeof(Info_SD_S_KeyboardMulti),},
{	EFFECT_SD_S_RHODES_MULTI, "Rhodes Multi", do_sd_s_rhodes_multi, NULL, NULL, conv_sd_s_rhodes_multi, sizeof(Info_SD_S_RhodesMulti),},
{	EFFECT_SD_S_JD_MULTI, "JD Multi", do_sd_s_jd_multi, NULL, NULL, conv_sd_s_jd_multi, sizeof(Info_SD_S_JD_Multi),},
{	EFFECT_SD_STEREO_LOFI_COMPRESS, "Stereo Lo-Fi Compress", do_sd_st_lofi_compress, NULL, NULL, conv_sd_st_lofi_compress, sizeof(Info_SD_LoFi_Compress),},
{	EFFECT_SD_STEREO_LOFI_NOISE, "Stereo Lo-Fi Noise", do_sd_st_lofi_noise, NULL, NULL, conv_sd_st_lofi_noise, sizeof(Info_SD_LoFi_Noise),},
{	EFFECT_SD_GUITAR_AMP_SIMULATOR, "Guitar Amp Simulator", do_sd_gt_amp_simulator, NULL, NULL, conv_sd_gt_amp_simulator, sizeof(Info_SD_GuitarAmpSimulator),},
{	EFFECT_SD_STEREO_OVERDRIVE, "Stereo Overdrive", do_sd_st_overdrive, NULL, NULL, conv_sd_st_overdrive, sizeof(Info_SD_Overdrive),},
{	EFFECT_SD_STEREO_DISTORTION, "Stereo Distortion", do_sd_st_distortion, NULL, NULL, conv_sd_st_distortion, sizeof(Info_SD_Overdrive),},
{	EFFECT_SD_S_GUITAR_MULTI_A, "Guitar Multi A", do_sd_s_gt_multi_a, NULL, NULL, conv_sd_s_gt_multi_a, sizeof(Info_SD_S_GuitarMultiA),},
{	EFFECT_SD_S_GUITAR_MULTI_B, "Guitar Multi B", do_sd_s_gt_multi_b, NULL, NULL, conv_sd_s_gt_multi_b, sizeof(Info_SD_S_GuitarMultiB),},
{	EFFECT_SD_S_GUITAR_MULTI_C, "Guitar Multi C", do_sd_s_gt_multi_c, NULL, NULL, conv_sd_s_gt_multi_c, sizeof(Info_SD_S_GuitarMultiC),},
{	EFFECT_SD_S_CLEAN_GUITAR_MULTI_A, "Clean Guitar Multi A", do_sd_s_clean_gt_multi_a, NULL, NULL, conv_sd_s_clean_gt_multi_a, sizeof(Info_SD_S_CleanGuitarMultiA),},
{	EFFECT_SD_S_CLEAN_GUITAR_MULTI_B, "Clean Guitar Multi B", do_sd_s_clean_gt_multi_b, NULL, NULL, conv_sd_s_clean_gt_multi_b, sizeof(Info_SD_S_CleanGuitarMultiB),},
{	EFFECT_SD_S_BASE_MULTI, "Base Multi", do_sd_s_base_multi, NULL, NULL, conv_sd_s_base_multi, sizeof(Info_SD_S_BaseMulti),},
{	EFFECT_SD_ISOLATOR2, "Isolator 2", do_sd_isolator2, NULL, NULL, conv_sd_isolator2, sizeof(Info_SD_Isolator2),},
{	EFFECT_SD_STEREO_SPECTRUM, "Stereo Spectrum", do_sd_stereo_spectrum, NULL, NULL, conv_sd_stereo_spectrum, sizeof(Info_SD_Spectrum),},
{	EFFECT_SD_3D_AUTO_SPIN, "3D Auto Spin", do_sd_3d_auto_spin, NULL, NULL, conv_sd_3d_auto_spin, sizeof(Info_SD_3DAutoSpin),},
{	EFFECT_SD_3D_MANUAL, "3D Manual", do_sd_3d_manual, NULL, NULL, conv_sd_3d_manual, sizeof(Info_SD_3DManual),},
// for effect test
{	EFFECT_SD_TEST1, "Test 1", do_sd_test1, NULL, NULL, conv_sd_test1, sizeof(Info_SD_Test1),},
{	EFFECT_SD_TEST2, "Test 2", do_sd_test2, NULL, NULL, conv_sd_test2, sizeof(Info_SD_Test2),},

{	-1, "EOF", NULL, NULL, NULL, NULL, 0, },
};








/************************************ timidity_effect ***************************************/


/****************** noise_shaping *********************/

static int32 ns_z0[4];
static int32 ns_z1[4];
static const int32 ns9_order = 9;
static int32 ns9_histposl, ns9_histposr;
static int32 ns9_ehl[18] = {0};
static int32 ns9_ehr[18] = {0};
//static int32 ns9_ehl[18];
//static int32 ns9_ehr[18];
static uint32 ns9_r1l, ns9_r2l, ns9_r1r, ns9_r2r;
static const float ns9_coef[9] = {
	2.412f, -3.370f, 3.937f, -4.174f, 3.353f,
	-2.205f, 1.281f, -0.569f, 0.0847f
};
static int32 ns9_c[9];

int noise_sharp_type = 0;

static void init_mtrand(void)
{
	unsigned long init[4] = { 0x123, 0x234, 0x345, 0x456 };
	unsigned long length = 4;
	init_by_array(init, length);
}

/* Noise Shaping filter from
 * Kunihiko IMAI <imai@leo.ec.t.kanazawa-u.ac.jp>
 * (Modified by Masanao Izumo <mo@goice.co.jp>)
 */
static void init_ns_tap16(void)
{
	int i;

	for (i = 0; i < ns9_order; i++)
		ns9_c[i] = TIM_FSCALE(ns9_coef[i], 24);
	memset(ns9_ehl, 0, sizeof(ns9_ehl));
	memset(ns9_ehr, 0, sizeof(ns9_ehr));
	ns9_histposl = ns9_histposr = 8;
	ns9_r1l = ns9_r2l = ns9_r1r = ns9_r2r = 0;
}

static void init_ns_tap(void)
{
	memset(ns_z0, 0, sizeof(ns_z0));
	memset(ns_z1, 0, sizeof(ns_z1));
	if (play_mode->encoding & PE_16BIT)
		init_ns_tap16();
}

#if (OPT_MODE == 1) && !defined(DATA_T_DOUBLE) && !defined(DATA_T_FLOAT) /* fixed-point implementation */

#define NS_AMP_MAX	((int32) 0x0fffffff)
#define NS_AMP_MIN	((int32)-0x0fffffff)

static inline unsigned long frand(void)
{
	return genrand_int32();
}

static inline int32 my_mod(int32 x, int32 n)
{
	if (x >= n)
		x -= n;
	return x;
}

static void ns_shaping8(int32 *lp, int32 c)
{
	int32 l, i, ll;
	int32 ns_tap_0, ns_tap_1, ns_tap_2, ns_tap_3;
	
	switch (noise_sharp_type) {
	case 1:
		ns_tap_0 = 1;
		ns_tap_1 = 0;
		ns_tap_2 = 0;
		ns_tap_3 = 0;
		break;
	case 2:
		ns_tap_0 = -2;
		ns_tap_1 = 1;
		ns_tap_2 = 0;
		ns_tap_3 = 0;
		break;
	case 3:
		ns_tap_0 = 3;
		ns_tap_1 = -3;
		ns_tap_2 = 1;
		ns_tap_3 = 0;
		break;
	case 4:
		ns_tap_0 = -4;
		ns_tap_1 = 6;
		ns_tap_2 = -4;
		ns_tap_3 = 1;
		break;
	default:
		return;
	}
	if (! (play_mode->encoding & PE_MONO))
		c *= 2;
	for (i = 0; i < c; i++) {
		/* applied noise-shaping filter */
		if (lp[i] > NS_AMP_MAX)
			lp[i] = NS_AMP_MAX;
		else if (lp[i] < NS_AMP_MIN)
			lp[i] = NS_AMP_MIN;
		ll = lp[i] + ns_tap_0 * ns_z0[0] + ns_tap_1 * ns_z0[1]
				+ ns_tap_2 * ns_z0[2] + ns_tap_3 * ns_z0[3];
		l = ll >> (32 - 8 - GUARD_BITS);
		lp[i] = l << (32 - 8 - GUARD_BITS);
		ns_z0[3] = ns_z0[2], ns_z0[2] = ns_z0[1], ns_z0[1] = ns_z0[0];
		ns_z0[0] = ll - l * (1U << (32 - 8 - GUARD_BITS));
		if (play_mode->encoding & PE_MONO)
			continue;
		i++;
		if (lp[i] > NS_AMP_MAX)
			lp[i] = NS_AMP_MAX;
		else if (lp[i] < NS_AMP_MIN)
			lp[i] = NS_AMP_MIN;
		ll = lp[i] + ns_tap_0 * ns_z1[0] + ns_tap_1 * ns_z1[1]
				+ ns_tap_2 * ns_z1[2] + ns_tap_3 * ns_z1[3];
		l = ll >> (32 - 8 - GUARD_BITS);
		lp[i] = l << (32 - 8 - GUARD_BITS);
		ns_z1[3] = ns_z1[2], ns_z1[2] = ns_z1[1], ns_z1[1] = ns_z1[0];
		ns_z1[0] = ll - l * (1U << (32 - 8 - GUARD_BITS));
	}
}

static void ns_shaping16_trad(int32 *lp, int32 c)
{
	int32 l, i, ll;
	int32 ns_tap_0, ns_tap_1, ns_tap_2, ns_tap_3;
	
	ns_tap_0 = -4;
	ns_tap_1 = 6;
	ns_tap_2 = -4;
	ns_tap_3 = 1;
	for (i = 0; i < c; i++) {
		/* applied noise-shaping filter */
		if (lp[i] > NS_AMP_MAX)
			lp[i] = NS_AMP_MAX;
		else if (lp[i] < NS_AMP_MIN)
			lp[i] = NS_AMP_MIN;
		ll = lp[i] + ns_tap_0 * ns_z0[0] + ns_tap_1 * ns_z0[1]
				+ ns_tap_2 * ns_z0[2] + ns_tap_3 * ns_z0[3];
		l = ll >> (32 - 16 - GUARD_BITS);
		lp[i] = l << (32 - 16 - GUARD_BITS);
		ns_z0[3] = ns_z0[2], ns_z0[2] = ns_z0[1], ns_z0[1] = ns_z0[0];
		ns_z0[0] = ll - l * (1U << (32 - 16 - GUARD_BITS));
		if (play_mode->encoding & PE_MONO)
			continue;
		i++;
		if (lp[i] > NS_AMP_MAX)
			lp[i] = NS_AMP_MAX;
		else if (lp[i] < NS_AMP_MIN)
			lp[i] = NS_AMP_MIN;
		ll = lp[i] + ns_tap_0 * ns_z1[0] + ns_tap_1 * ns_z1[1]
				+ ns_tap_2 * ns_z1[2] + ns_tap_3 * ns_z1[3];
		l = ll >> (32 - 16 - GUARD_BITS);
		lp[i] = l << (32 - 16 - GUARD_BITS);
		ns_z1[3] = ns_z1[2], ns_z1[2] = ns_z1[1], ns_z1[1] = ns_z1[0];
		ns_z1[0] = ll - l * (1U << (32 - 16 - GUARD_BITS));
	}
}

static void do_soft_clipping1(int32 *buf, int32 count)
{
	int32 i, x;
	int32 ai = TIM_FSCALE(1.5f, 24), bi = TIM_FSCALE(0.5f, 24);
	
	for (i = 0; i < count; i++) {
		x = buf[i];
		x = (x > NS_AMP_MAX) ? NS_AMP_MAX : ((x < NS_AMP_MIN) ? NS_AMP_MIN : x);
		x = imuldiv24(x, ai) - imuldiv24(imuldiv28(imuldiv28(x, x), x), bi);
		buf[i] = x;
	}
}

static void do_soft_clipping2(int32 *buf, int32 count)
{
	int32 i, x;
	
	for (i = 0; i < count; i++) {
		x = buf[i];
		x = (x > NS_AMP_MAX) ? NS_AMP_MAX : ((x < NS_AMP_MIN) ? NS_AMP_MIN : x);
		x = signlong(x) * ((abs(x) << 1) - imuldiv28(x, x));
		buf[i] = x;
	}
}

static void ns_shaping16_9(int32 *lp, int32 c)
{
	int32 i, l, sample, output;
	
	for (i = 0; i < c; i++) {
		/* left channel */
		ns9_r2l = ns9_r1l;
		ns9_r1l = frand();
		lp[i] = (lp[i] > NS_AMP_MAX) ? NS_AMP_MAX : (lp[i] < NS_AMP_MIN) ? NS_AMP_MIN : lp[i];
#if OPT_MODE != 0
		sample = lp[i] - imuldiv24(ns9_c[8], ns9_ehl[ns9_histposl + 8])
				- imuldiv24(ns9_c[7], ns9_ehl[ns9_histposl + 7])
				- imuldiv24(ns9_c[6], ns9_ehl[ns9_histposl + 6])
				- imuldiv24(ns9_c[5], ns9_ehl[ns9_histposl + 5])
				- imuldiv24(ns9_c[4], ns9_ehl[ns9_histposl + 4])
				- imuldiv24(ns9_c[3], ns9_ehl[ns9_histposl + 3])
				- imuldiv24(ns9_c[2], ns9_ehl[ns9_histposl + 2])
				- imuldiv24(ns9_c[1], ns9_ehl[ns9_histposl + 1])
				- imuldiv24(ns9_c[0], ns9_ehl[ns9_histposl]);
#else
		sample = lp[i] - ns9_coef[8] * ns9_ehl[ns9_histposl + 8]
				- ns9_coef[7] * ns9_ehl[ns9_histposl + 7]
				- ns9_coef[6] * ns9_ehl[ns9_histposl + 6]
				- ns9_coef[5] * ns9_ehl[ns9_histposl + 5]
				- ns9_coef[4] * ns9_ehl[ns9_histposl + 4]
				- ns9_coef[3] * ns9_ehl[ns9_histposl + 3]
				- ns9_coef[2] * ns9_ehl[ns9_histposl + 2]
				- ns9_coef[1] * ns9_ehl[ns9_histposl + 1]
				- ns9_coef[0] * ns9_ehl[ns9_histposl];
#endif
		l = sample >> (32 - 16 - GUARD_BITS);
		output = l * (1U << (32 - 16 - GUARD_BITS))
				+ ((ns9_r1l - ns9_r2l) >> 30);
		ns9_histposl = my_mod((ns9_histposl + 8), ns9_order);
		ns9_ehl[ns9_histposl + 9] = ns9_ehl[ns9_histposl] = output - sample;
		lp[i] = output;
		/* right channel */
		i++;
		ns9_r2r = ns9_r1r;
		ns9_r1r = frand();
		lp[i] = (lp[i] > NS_AMP_MAX) ? NS_AMP_MAX
				: (lp[i] < NS_AMP_MIN) ? NS_AMP_MIN : lp[i];
#if OPT_MODE != 0
		sample = lp[i] - imuldiv24(ns9_c[8], ns9_ehr[ns9_histposr + 8])
				- imuldiv24(ns9_c[7], ns9_ehr[ns9_histposr + 7])
				- imuldiv24(ns9_c[6], ns9_ehr[ns9_histposr + 6])
				- imuldiv24(ns9_c[5], ns9_ehr[ns9_histposr + 5])
				- imuldiv24(ns9_c[4], ns9_ehr[ns9_histposr + 4])
				- imuldiv24(ns9_c[3], ns9_ehr[ns9_histposr + 3])
				- imuldiv24(ns9_c[2], ns9_ehr[ns9_histposr + 2])
				- imuldiv24(ns9_c[1], ns9_ehr[ns9_histposr + 1])
				- imuldiv24(ns9_c[0], ns9_ehr[ns9_histposr]);
#else
		sample = lp[i] - ns9_coef[8] * ns9_ehr[ns9_histposr + 8]
				- ns9_coef[7] * ns9_ehr[ns9_histposr + 7]
				- ns9_coef[6] * ns9_ehr[ns9_histposr + 6]
				- ns9_coef[5] * ns9_ehr[ns9_histposr + 5]
				- ns9_coef[4] * ns9_ehr[ns9_histposr + 4]
				- ns9_coef[3] * ns9_ehr[ns9_histposr + 3]
				- ns9_coef[2] * ns9_ehr[ns9_histposr + 2]
				- ns9_coef[1] * ns9_ehr[ns9_histposr + 1]
				- ns9_coef[0] * ns9_ehr[ns9_histposr];
#endif
		l = sample >> (32 - 16 - GUARD_BITS);
		output = l * (1U << (32 - 16 - GUARD_BITS))
				+ ((ns9_r1r - ns9_r2r) >> 30);
		ns9_histposr = my_mod((ns9_histposr + 8), ns9_order);
		ns9_ehr[ns9_histposr + 9] = ns9_ehr[ns9_histposr] = output - sample;
		lp[i] = output;
	}
}

static void ns_shaping16(int32 *lp, int32 c)
{
	if (! (play_mode->encoding & PE_MONO))
		c *= 2;
	switch (noise_sharp_type) {
	case 1:
		ns_shaping16_trad(lp, c);
		break;
	case 2:
		do_soft_clipping1(lp, c);
		ns_shaping16_9(lp, c);
		break;
	case 3:
		do_soft_clipping2(lp, c);
		ns_shaping16_9(lp, c);
		break;
	case 4:
		ns_shaping16_9(lp, c);
		break;
	default:
		break;
	}
}

static void ns_shaping(int32 *lp, int32 c)
{
	if (play_mode->encoding & (PE_16BIT | PE_ULAW | PE_ALAW)){
		ns_shaping16(lp, c);
	}else if (! (play_mode->encoding & (PE_16BIT | PE_24BIT | PE_32BIT | PE_F32BIT | PE_64BIT | PE_F64BIT))){
		ns_shaping8(lp, c);
	}
}

#else /* floating-point implementation */

#ifdef EFFECT_LEVEL_FLOAT // level float // not yet
#define NS_AMP_MAX	((FLOAT_T) 1.0)
#define NS_AMP_MIN	((FLOAT_T) -1.0)
#else // level int
#define NS_AMP_MAX	((int32) 0x0fffffff)
#define NS_AMP_MIN	((int32)-0x0fffffff)
#endif

static inline unsigned long frand(void)
{
	return genrand_int32();
}

static inline int32 my_mod(int32 x, int32 n)
{
	if (x >= n)
		x -= n;
	return x;
}

static void ns_shaping8(DATA_T *lp, int32 c)
{
	int32 l, i, ll;
	int32 ns_tap_0, ns_tap_1, ns_tap_2, ns_tap_3;
	
	switch (noise_sharp_type) {
	case 1:
		ns_tap_0 = 1;
		ns_tap_1 = 0;
		ns_tap_2 = 0;
		ns_tap_3 = 0;
		break;
	case 2:
		ns_tap_0 = -2;
		ns_tap_1 = 1;
		ns_tap_2 = 0;
		ns_tap_3 = 0;
		break;
	case 3:
		ns_tap_0 = 3;
		ns_tap_1 = -3;
		ns_tap_2 = 1;
		ns_tap_3 = 0;
		break;
	case 4:
		ns_tap_0 = -4;
		ns_tap_1 = 6;
		ns_tap_2 = -4;
		ns_tap_3 = 1;
		break;
	default:
		return;
	}
	for (i = 0; i < c; i++) {
		/* applied noise-shaping filter */
		if (lp[i] > NS_AMP_MAX)
			lp[i] = NS_AMP_MAX;
		else if (lp[i] < NS_AMP_MIN)
			lp[i] = NS_AMP_MIN;
		ll = lp[i] + ns_tap_0 * ns_z0[0] + ns_tap_1 * ns_z0[1]
				+ ns_tap_2 * ns_z0[2] + ns_tap_3 * ns_z0[3];
		l = ll >> (32 - 8 - GUARD_BITS);
		lp[i] = l << (32 - 8 - GUARD_BITS);
		ns_z0[3] = ns_z0[2], ns_z0[2] = ns_z0[1], ns_z0[1] = ns_z0[0];
		ns_z0[0] = ll - l * (1U << (32 - 8 - GUARD_BITS));
		if (play_mode->encoding & PE_MONO)
			continue;
		i++;
		if (lp[i] > NS_AMP_MAX)
			lp[i] = NS_AMP_MAX;
		else if (lp[i] < NS_AMP_MIN)
			lp[i] = NS_AMP_MIN;
		ll = lp[i] + ns_tap_0 * ns_z1[0] + ns_tap_1 * ns_z1[1]
				+ ns_tap_2 * ns_z1[2] + ns_tap_3 * ns_z1[3];
		l = ll >> (32 - 8 - GUARD_BITS);
		lp[i] = l << (32 - 8 - GUARD_BITS);
		ns_z1[3] = ns_z1[2], ns_z1[2] = ns_z1[1], ns_z1[1] = ns_z1[0];
		ns_z1[0] = ll - l * (1U << (32 - 8 - GUARD_BITS));
	}
}

static void ns_shaping16_trad(DATA_T *lp, int32 c)
{
	int32 l, i, ll;
	int32 ns_tap_0, ns_tap_1, ns_tap_2, ns_tap_3;
	
	ns_tap_0 = -4;
	ns_tap_1 = 6;
	ns_tap_2 = -4;
	ns_tap_3 = 1;
	for (i = 0; i < c; i++) {
		/* applied noise-shaping filter */
		if (lp[i] > NS_AMP_MAX)
			lp[i] = NS_AMP_MAX;
		else if (lp[i] < NS_AMP_MIN)
			lp[i] = NS_AMP_MIN;
		ll = lp[i] + ns_tap_0 * ns_z0[0] + ns_tap_1 * ns_z0[1]
				+ ns_tap_2 * ns_z0[2] + ns_tap_3 * ns_z0[3];
		l = ll >> (32 - 16 - GUARD_BITS);
		lp[i] = l << (32 - 16 - GUARD_BITS);
		ns_z0[3] = ns_z0[2], ns_z0[2] = ns_z0[1], ns_z0[1] = ns_z0[0];
		ns_z0[0] = ll - l * (1U << (32 - 16 - GUARD_BITS));
		if (play_mode->encoding & PE_MONO)
			continue;
		i++;
		if (lp[i] > NS_AMP_MAX)
			lp[i] = NS_AMP_MAX;
		else if (lp[i] < NS_AMP_MIN)
			lp[i] = NS_AMP_MIN;
		ll = lp[i] + ns_tap_0 * ns_z1[0] + ns_tap_1 * ns_z1[1]
				+ ns_tap_2 * ns_z1[2] + ns_tap_3 * ns_z1[3];
		l = ll >> (32 - 16 - GUARD_BITS);
		lp[i] = l << (32 - 16 - GUARD_BITS);
		ns_z1[3] = ns_z1[2], ns_z1[2] = ns_z1[1], ns_z1[1] = ns_z1[0];
		ns_z1[0] = ll - l * (1U << (32 - 16 - GUARD_BITS));
	}
}

static void do_soft_clipping1(DATA_T *buf, int32 count)
{
	int32 i;
	DATA_T x;
	FLOAT_T af = 1.5, bf = 0.5;
	
	for (i = 0; i < count; i++) {
		x = buf[i];
		x = (x > NS_AMP_MAX) ? NS_AMP_MAX : ((x < NS_AMP_MIN) ? NS_AMP_MIN : x);
		x = x * af - ((x * x * DIV_28BIT) * x * DIV_28BIT) * bf;
		buf[i] = x;
	}
}

static void do_soft_clipping2(DATA_T *buf, int32 count)
{
	int32 i, x;
	
	for (i = 0; i < count; i++) {
		x = buf[i];
		x = (x > NS_AMP_MAX) ? NS_AMP_MAX : ((x < NS_AMP_MIN) ? NS_AMP_MIN : x);
		x = x * (2.0 - x * DIV_28BIT);
		buf[i] = x;
	}
}

static void ns_shaping16_9(DATA_T *lp, int32 c)
{
	int32 i, l, sample, output;
	
	for (i = 0; i < c; i++) {
		/* left channel */
		ns9_r2l = ns9_r1l;
		ns9_r1l = frand();
		lp[i] = (lp[i] > NS_AMP_MAX) ? NS_AMP_MAX : (lp[i] < NS_AMP_MIN) ? NS_AMP_MIN : lp[i];
		sample = lp[i] - ns9_coef[8] * ns9_ehl[ns9_histposl + 8]
				- ns9_coef[7] * ns9_ehl[ns9_histposl + 7]
				- ns9_coef[6] * ns9_ehl[ns9_histposl + 6]
				- ns9_coef[5] * ns9_ehl[ns9_histposl + 5]
				- ns9_coef[4] * ns9_ehl[ns9_histposl + 4]
				- ns9_coef[3] * ns9_ehl[ns9_histposl + 3]
				- ns9_coef[2] * ns9_ehl[ns9_histposl + 2]
				- ns9_coef[1] * ns9_ehl[ns9_histposl + 1]
				- ns9_coef[0] * ns9_ehl[ns9_histposl];
		l = sample >> (32 - 16 - GUARD_BITS);
		output = l * (1U << (32 - 16 - GUARD_BITS))
				+ ((ns9_r1l - ns9_r2l) >> 30);
		ns9_histposl = my_mod((ns9_histposl + 8), ns9_order);
		ns9_ehl[ns9_histposl + 9] = ns9_ehl[ns9_histposl] = output - sample;
		lp[i] = output;
		/* right channel */
		i++;
		ns9_r2r = ns9_r1r;
		ns9_r1r = frand();
		lp[i] = (lp[i] > NS_AMP_MAX) ? NS_AMP_MAX
				: (lp[i] < NS_AMP_MIN) ? NS_AMP_MIN : lp[i];

		sample = lp[i] - ns9_coef[8] * ns9_ehr[ns9_histposr + 8]
				- ns9_coef[7] * ns9_ehr[ns9_histposr + 7]
				- ns9_coef[6] * ns9_ehr[ns9_histposr + 6]
				- ns9_coef[5] * ns9_ehr[ns9_histposr + 5]
				- ns9_coef[4] * ns9_ehr[ns9_histposr + 4]
				- ns9_coef[3] * ns9_ehr[ns9_histposr + 3]
				- ns9_coef[2] * ns9_ehr[ns9_histposr + 2]
				- ns9_coef[1] * ns9_ehr[ns9_histposr + 1]
				- ns9_coef[0] * ns9_ehr[ns9_histposr];

		l = sample >> (32 - 16 - GUARD_BITS);
		output = l * (1U << (32 - 16 - GUARD_BITS))
				+ ((ns9_r1r - ns9_r2r) >> 30);
		ns9_histposr = my_mod((ns9_histposr + 8), ns9_order);
		ns9_ehr[ns9_histposr + 9] = ns9_ehr[ns9_histposr] = output - sample;
		lp[i] = output;
	}
}

static void ns_shaping16(DATA_T *lp, int32 c)
{
	switch (noise_sharp_type) {
	case 1:
		ns_shaping16_trad(lp, c);
		break;
	case 2:
		do_soft_clipping1(lp, c);
		ns_shaping16_9(lp, c);
		break;
	case 3:
		do_soft_clipping2(lp, c);
		ns_shaping16_9(lp, c);
		break;
	case 4:
		ns_shaping16_9(lp, c);
		break;
	default:
		break;
	}
}

static void ns_shaping(DATA_T *lp, int32 c)
{
	if (play_mode->encoding & (PE_16BIT | PE_ULAW | PE_ALAW)){
		ns_shaping16(lp, c);
	}else if (! (play_mode->encoding & (PE_16BIT | PE_24BIT | PE_32BIT | PE_F32BIT | PE_64BIT | PE_F64BIT))){
		ns_shaping8(lp, c);
	}
}
#endif




/**************** limiter *********************/

#define LIMITER_AHEAD_TIME (8) // ms
#define LIMITER_ATTACK_TIME (4) // ms
#define LIMITER_HOLD_TIME (1000) // ms
#define LIMITER_RELEASE_TIME (10000) // ms
#define LIMITER_MAX_FIX (0.80)
#define LIMITER_BUFFER_SIZE (LIMITER_AHEAD_TIME * 400 * 2) // AHEAD*400*2*2 // sample rate ~400kHz , ~10ms
#define LIMITER_MAX ((1 << (MAX_BITS - GUARD_BITS - 1)) - 1)
const FLOAT_T limiter_max = (double)LIMITER_MAX * LIMITER_MAX_FIX;
const FLOAT_T limiter_max2 = (double)LIMITER_MAX * (double)LIMITER_MAX * LIMITER_MAX_FIX * LIMITER_MAX_FIX;
static DATA_T limiter_buffer[LIMITER_BUFFER_SIZE + 8]; //  + 8 SIMD float*8
static FLOAT_T master_amp, limiter_peak_tmp, limiter_peak_hold, limiter_env, limiter_att, limiter_rel, limiter_level;
static int32 buffer_size, limiter_write_cnt, limiter_read_cnt, limiter_wnd_cnt, limiter_wnd_size,
	limiter_hold_len, limiter_hold_cnt;
static int limiter_dir;

int opt_limiter = 0; // 0:OFF 1~: gain %

static void init_limiter(void){
	int32 ahead_cnt = playmode_rate_ms * LIMITER_AHEAD_TIME;
	limiter_hold_len = playmode_rate_ms * LIMITER_HOLD_TIME;
	limiter_hold_cnt = 0;
	master_amp = (double)opt_limiter * DIV_100;
	buffer_size = LIMITER_BUFFER_SIZE;
	memset(limiter_buffer, 0, sizeof(limiter_buffer));
	limiter_write_cnt = ahead_cnt * 2;
	limiter_read_cnt = 0; // read count offset
	limiter_wnd_cnt = 0;
	limiter_wnd_size = play_mode->rate / 1000;
	limiter_dir = 0;
	limiter_peak_tmp = limiter_max2; // 
	limiter_peak_hold = limiter_max;
	limiter_env = limiter_max;
	limiter_att = exp (-1.0 / (playmode_rate_ms * LIMITER_ATTACK_TIME * DIV_8)); // attack "per sample decay"
	limiter_rel = exp (-1.0 / (playmode_rate_ms * LIMITER_RELEASE_TIME * DIV_8)); // release "per sample decay"  
	limiter_level = 1.0;
}

static void do_limiter(DATA_T *lp, int32 count){
	int i;
	double tmp = 0, input, theta;

	if(play_mode->encoding & PE_MONO){ // mono
		for (i = 0; i < count; i++) {
			// compute envelope
			if(!(i & 0x7)){
				theta = limiter_peak_hold > limiter_env ? limiter_att : limiter_rel;
				limiter_env = (1.0 - theta) * limiter_peak_hold + theta * limiter_env;
				limiter_level = limiter_max / limiter_env;
			}
			/* left channel */
			// buffer copy , search peak level
			limiter_buffer[limiter_write_cnt++] = input = master_amp * lp[i];
			if((tmp = input * input) > limiter_peak_tmp) {limiter_peak_tmp = tmp;}
			// output
			lp[i] = limiter_level * limiter_buffer[limiter_read_cnt++];
			/* common */
			// count reset
			if(limiter_write_cnt >= buffer_size) {limiter_write_cnt = 0;}
			if(limiter_read_cnt >= buffer_size) {limiter_read_cnt = 0;}
			// calc gain , reset envelope
			if(++limiter_wnd_cnt >= limiter_wnd_size){ // per 1ms
				if(limiter_peak_tmp > limiter_peak_hold){
					limiter_peak_hold = sqrt(limiter_peak_tmp);
					limiter_hold_cnt = 0;
					limiter_dir = 0;
				}else if(limiter_peak_tmp < limiter_peak_hold){
					switch(limiter_dir){
					case 0:
						limiter_dir = 1;
					case 1:
						if((limiter_hold_cnt += limiter_wnd_cnt) <= limiter_hold_len)
							break;
						limiter_dir = 2;
					case 2:
						limiter_peak_hold = sqrt(limiter_peak_tmp);
						break;
					}
				}
				limiter_wnd_cnt = 0;			
				limiter_peak_tmp = limiter_max2;
			}
		}
	}else{ // stereo
		int count2 = count * 2;
		
#if (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_DOUBLE)
#if defined(FLOAT_T_DOUBLE)
		__m256d vec_in1, vec_in2, 
			vec_amp = _mm256_broadcast_sd(&master_amp), vec_level = _mm256_broadcast_sd(&limiter_level), 
			vpeakt = _mm256_broadcast_sd(&limiter_peak_tmp), vmax2 = _mm256_broadcast_sd(&limiter_max2);
#else
		__m256d vec_in1, vec_in2, 
			vec_amp = _mm256_set1_pd((double)master_amp), vec_level = _mm256_set1_pd((double)limiter_level),
			vpeakt = _mm256_set1_pd((double)limiter_peak_tmp), vmax2 = _mm256_set1_pd((float)limiter_max2);
#endif
		double peak_tmp = 0;
		for (i = 0; i < count2; i += 8) {
			// compute envelope
			theta = limiter_peak_hold > limiter_env ? limiter_att : limiter_rel;
			limiter_env = (1.0 - theta) * limiter_peak_hold + theta * limiter_env;
			limiter_level = limiter_max / limiter_env;
#if defined(FLOAT_T_DOUBLE)
			vec_level = _mm256_broadcast_sd(&limiter_level);
#else
			vec_level = _mm256_set1_pd((double)limiter_level);
#endif
			// 4*2set buffer copy , search peak level , output
			vec_in1 = _mm256_mul_pd(_mm256_load_pd(&lp[i]), vec_amp);
			vec_in2 = _mm256_mul_pd(_mm256_load_pd(&lp[i + 4]), vec_amp);
			_mm256_storeu_pd(&limiter_buffer[limiter_write_cnt], vec_in1);
			_mm256_storeu_pd(&limiter_buffer[limiter_write_cnt + 4], vec_in2);
			vec_in1 = _mm256_mul_pd(vec_in1, vec_in1);
			vec_in2 = _mm256_mul_pd(vec_in2, vec_in2);
			vpeakt = _mm256_max_pd(vec_in1, vpeakt);
			vpeakt = _mm256_max_pd(vec_in2, vpeakt);
			_mm256_store_pd(&lp[i], _mm256_mul_pd(_mm256_loadu_pd(&limiter_buffer[limiter_read_cnt]), vec_level));
			_mm256_store_pd(&lp[i + 4], _mm256_mul_pd(_mm256_loadu_pd(&limiter_buffer[limiter_read_cnt + 4]), vec_level));
			// count reset
			if((limiter_write_cnt += 8) >= buffer_size) {limiter_write_cnt = 0;}
			if((limiter_read_cnt += 8) >= buffer_size) {limiter_read_cnt = 0;}
			/* common */
			// calc gain , reset envelope
			if((limiter_wnd_cnt += 4) >= limiter_wnd_size){ // per 1ms
				vpeakt = _mm256_max_pd(vpeakt, _mm256_shuffle_pd(vpeakt, vpeakt, 0x1));
				vpeakt = _mm256_max_pd(vpeakt, _mm256_permute2f128_pd(vpeakt, vpeakt, 0x1));
				_mm_store_sd(&peak_tmp, _mm256_extractf128_pd(vpeakt, 0x0));
				if(peak_tmp > limiter_peak_hold){
					limiter_peak_hold = sqrt(peak_tmp);
					limiter_hold_cnt = 0;
					limiter_dir = 0;
				}else if(peak_tmp < limiter_peak_hold){
					switch(limiter_dir){ 
					case 0:
						limiter_dir = 1;
					case 1:
						if((limiter_hold_cnt += limiter_wnd_cnt) <= limiter_hold_len)
							break;
						limiter_dir = 2;
					case 2:
						limiter_peak_hold = sqrt(peak_tmp);
						break;
					}
				}
				limiter_wnd_cnt = 0;	
				vpeakt = vmax2;
			}
		}
		vpeakt = _mm256_max_pd(vpeakt, _mm256_shuffle_pd(vpeakt, vpeakt, 0x1));
		vpeakt = _mm256_max_pd(vpeakt, _mm256_permute2f128_pd(vpeakt, vpeakt, 0x1));
		_mm_store_sd(&limiter_peak_tmp, _mm256_extractf128_pd(vpeakt, 0x0));

#elif (USE_X86_EXT_INTRIN >= 8) && defined(DATA_T_FLOAT)
#if defined(FLOAT_T_DOUBLE)
		__m256 vec_in,
			vec_amp = _mm256_set1_ps((float)master_amp), vec_level = _mm256_set1_ps((float)limiter_level),
			vpeakt = _mm256_set1_ps((float)limiter_peak_tmp), vmax2 = _mm256_set1_ps((float)limiter_max2);
#else
		__m256 vec_in, 
			vec_amp = _mm256_broadcast_ss(&master_amp), vec_level = _mm256_broadcast_ss(&limiter_level), 
			vpeakt = _mm256_broadcast_ss(&limiter_peak_tmp), vmax2 = _mm256_broadcast_ss(&limiter_max2);
#endif
		float peak_tmp = 0;
		for (i = 0; i < count2; i += 8) {
			// compute envelope
			theta = limiter_peak_hold > limiter_env ? limiter_att : limiter_rel;
			limiter_env = (1.0 - theta) * limiter_peak_hold + theta * limiter_env;
			limiter_level = limiter_max / limiter_env;
#if defined(FLOAT_T_DOUBLE)
			vec_level = _mm256_set1_ps((float)limiter_level);
#else
			vec_level = _mm256_broadcast_ss(&limiter_level);
#endif
			// 8*1set buffer copy , search peak level , output
			vec_in = _mm256_mul_ps(_mm256_load_ps(&lp[i]), vec_amp);
			_mm256_storeu_ps(&limiter_buffer[limiter_write_cnt], vec_in);
			vec_in = _mm256_mul_ps(vec_in, vec_in);
			vpeakt = _mm256_max_ps(vec_in, vpeakt);
			_mm256_store_ps(&lp[i], _mm256_mul_ps(_mm256_loadu_ps(&limiter_buffer[limiter_read_cnt]), vec_level));
			// count reset
			if((limiter_write_cnt += 8) >= buffer_size) {limiter_write_cnt = 0;}
			if((limiter_read_cnt += 8) >= buffer_size) {limiter_read_cnt = 0;}
			/* common */
			// calc gain , reset envelope
			if((limiter_wnd_cnt += 4) >= limiter_wnd_size){ // per 1ms
				vpeakt = _mm256_max_ps(vpeakt, _mm256_shuffle_ps(vpeakt, vpeakt, 0x4e));
				vpeakt = _mm256_max_ps(vpeakt, _mm256_shuffle_ps(vpeakt, vpeakt, 0xb1));
				vpeakt = _mm256_max_ps(vpeakt, _mm256_permute2f128_ps(vpeakt, vpeakt, 0x1));
				_mm_store_ss(&peak_tmp, _mm256_extractf128_ps(vpeakt, 0x0));
				if(peak_tmp > limiter_peak_hold){
					limiter_peak_hold = sqrt(peak_tmp);
					limiter_hold_cnt = 0;
					limiter_dir = 0;
				}else if(peak_tmp < limiter_peak_hold){
					switch(limiter_dir){
					case 0: // thru 1:2:
						limiter_dir = 1;
					case 1: // thru 2:
						if((limiter_hold_cnt += limiter_wnd_cnt) <= limiter_hold_len)
							break;
						limiter_dir = 2;
					case 2:
						limiter_peak_hold = sqrt(peak_tmp);
						break;
					}
				}
				limiter_wnd_cnt = 0;	
				vpeakt = vmax2;
			}
		}
		vpeakt = _mm256_max_ps(vpeakt, _mm256_shuffle_ps(vpeakt, vpeakt, 0x4e));
		vpeakt = _mm256_max_ps(vpeakt, _mm256_shuffle_ps(vpeakt, vpeakt, 0xb1));
		vpeakt = _mm256_max_ps(vpeakt, _mm256_permute2f128_ps(vpeakt, vpeakt, 0x1));
		_mm_store_ss(&limiter_peak_tmp, _mm256_extractf128_ps(vpeakt, 0x0));

#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE)
#if defined(FLOAT_T_DOUBLE)
		__m128d vec_in1, vec_in2, 
			vec_amp = MM_LOAD1_PD(&master_amp), vec_level = MM_LOAD1_PD(&limiter_level), 
			vpeakt = MM_LOAD1_PD(&limiter_peak_tmp), vmax2 = MM_LOAD1_PD(&limiter_max2);
#else
		__m128d vec_in1, vec_in2, 
			vec_amp = _mm_set1_pd((double)master_amp), vec_level = _mm_set1_pd((double)limiter_level),
			vpeakt = _mm_set1_pd((double)limiter_peak_tmp), vmax2 = _mm_set1_pd((double)limiter_max2);
#endif
		double peak_tmp = 0;
		for (i = 0; i < count2; i += 8) {
			// compute envelope
			theta = limiter_peak_hold > limiter_env ? limiter_att : limiter_rel;
			limiter_env = (1.0 - theta) * limiter_peak_hold + theta * limiter_env;
			limiter_level = limiter_max / limiter_env;
#if defined(FLOAT_T_DOUBLE)
			vec_level = MM_LOAD1_PD(&limiter_level);
#else
			vec_level = _mm_set1_pd((double)limiter_level);
#endif
			// 2*2set buffer copy , search peak level , output
			vec_in1 = _mm_mul_pd(_mm_load_pd(&lp[i]), vec_amp);
			vec_in2 = _mm_mul_pd(_mm_load_pd(&lp[i + 2]), vec_amp);
			_mm_storeu_pd(&limiter_buffer[limiter_write_cnt], vec_in1);
			_mm_storeu_pd(&limiter_buffer[limiter_write_cnt + 2], vec_in2);
			vec_in1 = _mm_mul_pd(vec_in1, vec_in1);
			vec_in2 = _mm_mul_pd(vec_in2, vec_in2);
			vpeakt = _mm_max_pd(vec_in1, vpeakt);
			vpeakt = _mm_max_pd(vec_in2, vpeakt);
			_mm_store_pd(&lp[i], _mm_mul_pd(_mm_loadu_pd(&limiter_buffer[limiter_read_cnt]), vec_level));
			_mm_store_pd(&lp[i + 2], _mm_mul_pd(_mm_loadu_pd(&limiter_buffer[limiter_read_cnt + 2]), vec_level));
			// 2*2set buffer copy , search peak level , output
			vec_in1 = _mm_mul_pd(_mm_load_pd(&lp[i + 4]), vec_amp);
			vec_in2 = _mm_mul_pd(_mm_load_pd(&lp[i + 6]), vec_amp);
			_mm_storeu_pd(&limiter_buffer[limiter_write_cnt + 4], vec_in1);
			_mm_storeu_pd(&limiter_buffer[limiter_write_cnt + 6], vec_in2);
			vec_in1 = _mm_mul_pd(vec_in1, vec_in1);
			vec_in2 = _mm_mul_pd(vec_in2, vec_in2);
			vpeakt = _mm_max_pd(vec_in1, vpeakt);
			vpeakt = _mm_max_pd(vec_in2, vpeakt);
			_mm_store_pd(&lp[i + 4], _mm_mul_pd(_mm_loadu_pd(&limiter_buffer[limiter_read_cnt + 4]), vec_level));
			_mm_store_pd(&lp[i + 6], _mm_mul_pd(_mm_loadu_pd(&limiter_buffer[limiter_read_cnt + 6]), vec_level));
			// count reset
			if((limiter_write_cnt += 8) >= buffer_size) {limiter_write_cnt = 0;}
			if((limiter_read_cnt += 8) >= buffer_size) {limiter_read_cnt = 0;}
			/* common */
			// calc gain , reset envelope
			if((limiter_wnd_cnt += 4) >= limiter_wnd_size){ // per 1ms
				vpeakt = _mm_max_pd(vpeakt, _mm_shuffle_pd(vpeakt, vpeakt, 0x1));
				_mm_store_sd(&peak_tmp, vpeakt);
				if(peak_tmp > limiter_peak_hold){
					limiter_peak_hold = sqrt(peak_tmp);
					limiter_hold_cnt = 0;
					limiter_dir = 0;
				}else if(peak_tmp < limiter_peak_hold){
					switch(limiter_dir){
					case 0:
						limiter_dir = 1;
					case 1:
						if((limiter_hold_cnt += limiter_wnd_cnt) <= limiter_hold_len)
							break;
						limiter_dir = 2;
					case 2:
						limiter_peak_hold = sqrt(peak_tmp);
						break;
					}
				}
				limiter_wnd_cnt = 0;	
				vpeakt = vmax2;
			}
		}
		vpeakt = _mm_max_pd(vpeakt, _mm_shuffle_pd(vpeakt, vpeakt, 0x1));
		_mm_store_sd(&limiter_peak_tmp, vpeakt);
#if defined(FLOAT_T_DOUBLE)
		_mm_store_sd(&limiter_peak_tmp, vpeakt);
#else
		_mm_store_ss(&limiter_peak_tmp, _mm_cvtpd_ps(vpeakt));
#endif

#elif (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_FLOAT)
#if defined(FLOAT_T_DOUBLE)
		__m128 vec_in1, vec_in2, 
			vec_amp = _mm_set1_ps((float)master_amp), vec_level = _mm_set1_ps((float)limiter_level),
			vpeakt = _mm_set1_ps((float)limiter_peak_tmp), vmax2 = _mm_set1_ps((float)limiter_max2);
#else
		__m128 vec_in1, vec_in2, 
			vec_amp = _mm_load1_ps(&master_amp), vec_level = _mm_load1_ps(&limiter_level), 
			vpeakt = _mm_load1_ps(&limiter_peak_tmp), vmax2 = _mm_load1_ps(&limiter_max2);
#endif
		float peak_tmp = 0;
		for (i = 0; i < count2; i += 8) {
			// compute envelope
			theta = limiter_peak_hold > limiter_env ? limiter_att : limiter_rel;
			limiter_env = (1.0 - theta) * limiter_peak_hold + theta * limiter_env;
			limiter_level = limiter_max / limiter_env;
#if defined(FLOAT_T_DOUBLE)
			vec_level = _mm_set1_ps((float)limiter_level);
#else
			vec_level = _mm_load1_ps(&limiter_level);
#endif
			// 4*2set buffer copy , search peak level , output
			vec_in1 = _mm_mul_ps(_mm_load_ps(&lp[i]), vec_amp);
			vec_in2 = _mm_mul_ps(_mm_load_ps(&lp[i + 4]), vec_amp);
			_mm_storeu_ps(&limiter_buffer[limiter_write_cnt], vec_in1);
			_mm_storeu_ps(&limiter_buffer[limiter_write_cnt + 4], vec_in2);
			vec_in1 = _mm_mul_ps(vec_in1, vec_in1);
			vec_in2 = _mm_mul_ps(vec_in2, vec_in2);
			vpeakt = _mm_max_ps(vec_in1, vpeakt);
			vpeakt = _mm_max_ps(vec_in2, vpeakt);
			_mm_store_ps(&lp[i], _mm_mul_ps(_mm_loadu_ps(&limiter_buffer[limiter_read_cnt]), vec_level));
			_mm_store_ps(&lp[i + 4], _mm_mul_ps(_mm_loadu_ps(&limiter_buffer[limiter_read_cnt + 4]), vec_level));
			// count reset
			if((limiter_write_cnt += 8) >= buffer_size) {limiter_write_cnt = 0;}
			if((limiter_read_cnt += 8) >= buffer_size) {limiter_read_cnt = 0;}
			/* common */
			// calc gain , reset envelope
			if((limiter_wnd_cnt += 4) >= limiter_wnd_size){ // per 1ms
				vpeakt = _mm_max_ps(vpeakt, _mm_shuffle_ps(vpeakt, vpeakt, 0x4e));
				vpeakt = _mm_max_ps(vpeakt, _mm_shuffle_ps(vpeakt, vpeakt, 0xb1));
				_mm_store_ss(&peak_tmp, vpeakt);
				if(peak_tmp > limiter_peak_hold){
					limiter_peak_hold = sqrt(peak_tmp);
					limiter_hold_cnt = 0;
					limiter_dir = 0;
				}else if(peak_tmp < limiter_peak_hold){
					switch(limiter_dir){
					case 0:
						limiter_dir = 1;
					case 1:
						if((limiter_hold_cnt += limiter_wnd_cnt) <= limiter_hold_len)
							break;
						limiter_dir = 2;
					case 2:
						limiter_peak_hold = sqrt(peak_tmp);
						break;
					}
				}
				limiter_wnd_cnt = 0;	
				vpeakt = vmax2;
			}
		}
		vpeakt = _mm_max_ps(vpeakt, _mm_shuffle_ps(vpeakt, vpeakt, 0x4e));
		vpeakt = _mm_max_ps(vpeakt, _mm_shuffle_ps(vpeakt, vpeakt, 0xb1));
#if defined(FLOAT_T_DOUBLE)
		_mm_store_sd(&limiter_peak_tmp, _mm_cvtps_pd(vpeakt));
#else
		_mm_store_ss(&limiter_peak_tmp, vpeakt);
#endif

#else  // ! USE_X86_EXT_INTRIN
		for (i = 0; i < count2; i++) {
			// compute envelope
			if(!(i & 0x7)){
				theta = limiter_peak_hold > limiter_env ? limiter_att : limiter_rel;
				limiter_env = (1.0 - theta) * limiter_peak_hold + theta * limiter_env;
				limiter_level = limiter_max / limiter_env;
			}
			/* left channel */
			// buffer copy , search peak level
			limiter_buffer[limiter_write_cnt++] = input = master_amp * lp[i];
			if((tmp = input * input) > limiter_peak_tmp) {limiter_peak_tmp = tmp;}
			// output
			lp[i++] = limiter_level * limiter_buffer[limiter_read_cnt++];
			/* right channel */
			// buffer copy , search peak level
			limiter_buffer[limiter_write_cnt++] = input = master_amp * lp[i];
			if((tmp = input * input) > limiter_peak_tmp) {limiter_peak_tmp = tmp;}
			// output
			lp[i] = limiter_level * limiter_buffer[limiter_read_cnt++];
			// count reset
			if(limiter_write_cnt >= buffer_size) {limiter_write_cnt = 0;}
			if(limiter_read_cnt >= buffer_size) {limiter_read_cnt = 0;}
			/* common */
			// calc gain , reset envelope
			if(++limiter_wnd_cnt >= limiter_wnd_size){ // per 1ms
				if(limiter_peak_tmp > limiter_peak_hold){
					limiter_peak_hold = sqrt(limiter_peak_tmp);
					limiter_hold_cnt = 0;
					limiter_dir = 0;
				}else if(limiter_peak_tmp < limiter_peak_hold){
					switch(limiter_dir){
					case 0:
						limiter_dir = 1;
					case 1:
						if((limiter_hold_cnt += limiter_wnd_cnt) <= limiter_hold_len)
							break;
						limiter_dir = 2;
					case 2:
						limiter_peak_hold = sqrt(limiter_peak_tmp);
						break;
					}
				}
				limiter_wnd_cnt = 0;			
				limiter_peak_tmp = limiter_max2;
			}
		}
#endif // USE_X86_EXT_INTRIN
	}
}



/**************** compressor *********************/
// my_func.c erion add
const FLOAT_T div_mcomp_max = 1.0 / (FLOAT_T)((1 << (MAX_BITS - GUARD_BITS - 4)) - 1);

struct {
	int8 mode;
	double threshold;  // threshold to unity (0...1)
	double slope;      // slope to unity
	double tla;        // lookahead time to seconds
	double twnd;       // window time to seconds
	double tatt;       // attack time to seconds
	double trel;       // release time to seconds
	double att;        // attack "per sample decay"
	double rel;        // release "per sample decay"  
	int32 lhsmp;       // sample offset to lookahead wnd start
	int32 nrms;        // samples count in lookahead window
	FLOAT_T div_nrms;   // 1.0 / nrms
	FLOAT_T env;
	int32 delay1, count1, delay2, count2;
	FLOAT_T ptr1[1200]; // 3ms
	DATA_T ptr2[4000]; // 5ms
} mcmp;

static void init_mix_compressor(void)
{
	if (!(otd.timRunMode & EOWM_USE_COMPRESSOR)){
		mcmp.mode = 0;
		return;
	}
	mcmp.mode = (play_mode->encoding & PE_MONO) ? 1 : 2; // enable flag // buf channel
	mcmp.threshold = otd.compThr * 0.01; // threshold to unity (0...1)
	if(mcmp.threshold > 1.0)
		mcmp.threshold = 1.0;
	else if(mcmp.threshold < 0.0001)
		mcmp.threshold = 0.0001;
	mcmp.slope = otd.compSlope * 0.01; // slope to unity
	if(mcmp.slope > 100.0)
		mcmp.slope = 100.0;
	else if(mcmp.slope < 0)
		mcmp.slope = 0;
	mcmp.tla   = otd.compLook * 0.001; // lookahead time to seconds
	if(mcmp.tla > 0.005)
		mcmp.tla = 0.005;
	else if(mcmp.tla < 0.00001)
		mcmp.tla = 0.00001;
	mcmp.twnd  = otd.compWTime * 0.001; // window time to seconds
	if(mcmp.twnd > 0.003)
		mcmp.twnd = 0.003;
	else if(mcmp.twnd < 0.00001)
		mcmp.twnd = 0.00001;
	mcmp.tatt  = otd.compATime * 0.001; // attack time to seconds
	if(mcmp.tatt > 0.500)
		mcmp.tatt = 0.500;
	else if(mcmp.tatt < 0.00001)
		mcmp.tatt = 0.00001;
	mcmp.trel  = otd.compRTime * 0.001; // release time to seconds
	if(mcmp.trel > 5000.0)
		mcmp.trel = 5000.0;
	else if(mcmp.trel < 0.00001)
		mcmp.trel = 0.00001;
	mcmp.att = (mcmp.tatt == 0.0) ? (0.0) : exp (-1.0 / (play_mode->rate * mcmp.tatt)); // attack "per sample decay"
	mcmp.rel = (mcmp.trel == 0.0) ? (0.0) : exp (-1.0 / (play_mode->rate * mcmp.trel)); // release "per sample decay"  	
	mcmp.lhsmp = (int32)(play_mode->rate * mcmp.tla); // sample offset to lookahead wnd start	
	if(mcmp.lhsmp < 0)
		mcmp.lhsmp = 1;
	mcmp.nrms = (int32)(play_mode->rate * mcmp.twnd); // samples count in lookahead window
	if(mcmp.nrms < 2)
		mcmp.nrms = 2;
	else if(mcmp.nrms & 0x1)
		mcmp.nrms++;
	if(mcmp.mode == 2)
		mcmp.div_nrms = DIV_2 / (double)mcmp.nrms; // 1.0 / nrms / 2
	else
		mcmp.div_nrms = 1.0 / (double)mcmp.nrms; // 1.0 / nrms
	mcmp.env = 0;
	mcmp.delay1 = mcmp.nrms; // < 1ms
	mcmp.count1 = 0;
	mcmp.delay2 = mcmp.lhsmp * mcmp.mode; // < 2ms
	mcmp.count2 = 0;
	memset(mcmp.ptr1, 0, sizeof(FLOAT_T) * 1200); // 3ms sr max 384kHz 
	memset(mcmp.ptr2, 0, sizeof(DATA_T) * 4000); // stereo 5ms sr max 384kHz 
}

static void mix_compressor(DATA_T *buf, int count)
{
	FLOAT_T rms, theta=0, gain=0, summ;
	int i, j;

	switch(mcmp.mode){
	case 0: // disable
		break;
	case 1: // mono
		for (i = 0; i < count; ++i) // for each sample...
		{
			DATA_T dataL = mcmp.ptr2[mcmp.count2];
#ifdef EFFECT_LEVEL_FLOAT // level float
			FLOAT_T inL = buf[i]; // level int to float // cnv ins level
#else
			FLOAT_T inL = buf[i] * div_mcomp_max; // level int to float // cnv ins level
#endif
			mcmp.ptr2[mcmp.count2] = buf[i];
			mcmp.ptr1[mcmp.count1] = inL * inL;
			if (++mcmp.count1 >= mcmp.delay1) {mcmp.count1 -= mcmp.delay1;}
			if (++mcmp.count2 >= mcmp.delay2) {mcmp.count2 -= mcmp.delay2;}
			// now compute RMS
			summ = 0;
			// for each sample in window
			for (j = 0; j < mcmp.nrms; ++j)
				summ += mcmp.ptr1[j]; // level float
			rms = sqrt(summ * mcmp.div_nrms);   // root-mean-square
			// dynamic selection: attack or release?
			theta = rms > mcmp.env ? mcmp.att : mcmp.rel;
			// smoothing with capacitor, envelope extraction...
			// here be aware of pIV denormal numbers glitch
			mcmp.env = (1.0 - theta) * rms + theta * mcmp.env;
			// the very easy hard knee 1:N compressor
		//	gain = (mcmp.env > mcmp.threshold) ? (1.0 - (mcmp.env - mcmp.threshold))) : 1.0;
			gain = (mcmp.env > mcmp.threshold) ? (mcmp.threshold / mcmp.env) : 1.0;
			if(gain < mcmp.slope)
				gain = mcmp.slope;
			// result - two hard kneed compressed channels...
#if defined(DATA_T_DOUBLE) || defined(DATA_T_FLOAT) 
			buf[i] = dataL * gain;
#else
			buf[i] = Sample_FtoI(Sample_ItoF(dataL) * gain);
#endif
		}
		break;
	case 2: // stereo
#if (USE_X86_EXT_INTRIN >= 3) && defined(DATA_T_DOUBLE) && defined(FLOAT_T_DOUBLE) && !defined(EFFECT_LEVEL_FLOAT)
		{
			__m128d vec_in_level = _mm_set1_pd(div_mcomp_max); // cnv ins level
			__m128d vec_div_nrms = _mm_set1_pd(mcmp.div_nrms);
			for (i = 0; i < count; i += 2)
			{
				__m128d vec_tmp, vec_buf = _mm_load_pd(&buf[i]), vec_data = _mm_loadu_pd(&mcmp.ptr2[mcmp.count2]);
				_mm_storeu_pd(&mcmp.ptr2[mcmp.count2], vec_buf);
				vec_tmp = _mm_mul_pd(vec_buf, vec_in_level);
				vec_tmp = _mm_mul_pd(vec_tmp, vec_tmp);
				vec_tmp = _mm_add_pd(vec_tmp, _mm_shuffle_pd(vec_tmp, vec_tmp, 0x1));
				_mm_store_sd(&mcmp.ptr1[mcmp.count1], vec_tmp);
				if (++mcmp.count1 >= mcmp.delay1) {mcmp.count1 -= mcmp.delay1;}
				if ((mcmp.count2 += 2) >= mcmp.delay2) {mcmp.count2 -= mcmp.delay2;}
				vec_tmp = _mm_setzero_pd();
				for (j = 0; j < mcmp.nrms; j += 2)
					vec_tmp = _mm_add_pd(vec_tmp, _mm_loadu_pd(&mcmp.ptr1[j]));
				vec_tmp = _mm_add_pd(vec_tmp, _mm_shuffle_pd(vec_tmp, vec_tmp, 0x1));
				vec_tmp = _mm_mul_sd(_mm_sqrt_sd(vec_tmp, vec_tmp), vec_div_nrms);   // root-mean-square
				_mm_store_sd(&rms, vec_tmp);
				theta = rms > mcmp.env ? mcmp.att : mcmp.rel;
				mcmp.env = (1.0 - theta) * rms + theta * mcmp.env;
				gain = (mcmp.env > mcmp.threshold) ? (mcmp.threshold / mcmp.env) : 1.0;
				_mm_store_pd(&buf[i], _mm_mul_pd(vec_data, _mm_set1_pd(gain < mcmp.slope ? mcmp.slope : gain)));
			}
		}
#else // ! USE_X86_EXT_INTRIN
		for (i = 0; i < count; ++i) // for each sample...
		{
			FLOAT_T dataL = mcmp.ptr2[mcmp.count2], dataR = mcmp.ptr2[mcmp.count2 + 1];
#ifdef EFFECT_LEVEL_FLOAT // level float
			FLOAT_T inL = buf[i]; // level int to float // cnv ins level
			FLOAT_T inR = buf[i + 1]; // level int to float // cnv ins level
#else
			FLOAT_T inL = buf[i] * div_mcomp_max; // level int to float // cnv ins level
			FLOAT_T inR = buf[i + 1] * div_mcomp_max; // level int to float // cnv ins level
#endif
			mcmp.ptr2[mcmp.count2] = buf[i];
			mcmp.ptr2[++mcmp.count2] = buf[i + 1];
			mcmp.ptr1[mcmp.count1] = inL * inL + inR * inR;
			if (++mcmp.count1 >= mcmp.delay1) {mcmp.count1 -= mcmp.delay1;}
			if (++mcmp.count2 >= mcmp.delay2) {mcmp.count2 -= mcmp.delay2;}
			// now compute RMS
			summ = 0;
			// for each sample in window
			for (j = 0; j < mcmp.nrms; ++j)
				summ += mcmp.ptr1[j]; // level float
			rms = sqrt(summ * mcmp.div_nrms);   // root-mean-square
			// dynamic selection: attack or release?
			theta = rms > mcmp.env ? mcmp.att : mcmp.rel;
			// smoothing with capacitor, envelope extraction...
			// here be aware of pIV denormal numbers glitch
			mcmp.env = (1.0 - theta) * rms + theta * mcmp.env;
			// the very easy hard knee 1:N compressor
		//	gain = (mcmp.env > mcmp.threshold) ? (1.0 - (mcmp.env - mcmp.threshold))) : 1.0;
			gain = (mcmp.env > mcmp.threshold) ? (mcmp.threshold / mcmp.env) : 1.0;
			if(gain < mcmp.slope)
				gain = mcmp.slope;
			// result - two hard kneed compressed channels...
#if defined(DATA_T_DOUBLE) || defined(DATA_T_FLOAT) 
			buf[i] = dataL * gain;
			i++;
			buf[i] = dataR * gain;
#else
			buf[i] = Sample_FtoI(Sample_ItoF(dataL) * gain);
			i++;
			buf[i] = Sample_FtoI(Sample_ItoF(dataR) * gain);
#endif
		}
#endif // USE_X86_EXT_INTRIN
		break;
	}
	
}





/************************************ master_effect ***************************************/

//#define TEST_FFT

#ifdef TEST_FFT

#include "fft4g.h"
#define FFT_BIT_MAX 16
#define FFT_SIZE_MAX (1<<FFT_BIT_MAX)

int32 fft_bit = 12;
int32 fft_size = 1 << 12;
float div_fft_size = 1;
int fft_ip[FFT_SIZE_MAX];
float fft_w[FFT_SIZE_MAX];
float fft_bufL0[2][FFT_SIZE_MAX];
float fft_bufR0[2][FFT_SIZE_MAX];
float fft_bufL1[2][FFT_SIZE_MAX];
float fft_bufR1[2][FFT_SIZE_MAX];
int32 fft_count[2];
int32 fft_cycle[2];
int32 fft_rofs[2];

float fft_fcL[FFT_SIZE_MAX];
float fft_fcR[FFT_SIZE_MAX];

void init_fft(void)
{
	fft_bit = 14;
	if(fft_bit > FFT_BIT_MAX) fft_bit = FFT_BIT_MAX;
	else if(fft_bit < 4) fft_bit = 4;
	fft_size = 1 << fft_bit;
	div_fft_size = (double)1.0 / (double)fft_size;
	memset(fft_ip, 0, sizeof(fft_ip)); // fft_ip[0] = 0; initialize
	memset(fft_w, 0, sizeof(fft_w));
	memset(fft_bufL0, 0, sizeof(fft_bufL0));
	memset(fft_bufR0, 0, sizeof(fft_bufR0));
	memset(fft_bufL1, 0, sizeof(fft_bufL1));
	memset(fft_bufR1, 0, sizeof(fft_bufR1));	
	fft_count[0] = 0;
	fft_cycle[0] = 1;
	fft_count[1] = fft_size / 2;
	fft_cycle[1] = 0;
	fft_rofs[0] = 0x1 - fft_cycle[0];
	fft_rofs[1] = 0x1 - fft_cycle[1];
	
	memset(fft_fcL, 0, sizeof(fft_fcL));
	memset(fft_fcR, 0, sizeof(fft_fcR));
}

void custom_fft_dataL(float *buf)
{
	int32 i, tmp;
	float var;
	
	for(i = 0; i < fft_size; ++i){
		fft_fcL[i] = fft_fcL[i] + buf[i] * DIV_2 + fft_fcR[i] * DIV_8;
		fft_fcL[i] *= (1.0 - ((double)i * div_fft_size)) * 0.75;
		buf[i] += fft_fcL[i];
	}	
	for(i = fft_size - 1; i >= 0; --i){
		tmp = i - 4;
		if(tmp >= 0)
			fft_fcL[i] = fft_fcL[tmp];
		else
			fft_fcL[i] = 0;
	}	
}

void custom_fft_dataR(float *buf)
{
	int32 i, tmp;
	float var;
	
	for(i = 0; i < fft_size; ++i){
		fft_fcR[i] = fft_fcR[i] + buf[i] * DIV_2 + fft_fcL[i] * DIV_8;
		fft_fcR[i] *= (1.0 - ((double)i * div_fft_size)) * 0.75;
		buf[i] += fft_fcR[i];
	}
	for(i = fft_size - 1; i >= 4; --i){
		tmp = i - 4;
		if(tmp >= 0)
			fft_fcR[i] = fft_fcR[tmp];
		else
			fft_fcR[i] = 0;
	}
}

void test_fft(DATA_T *buf, int32 count)
{
	int32 i;
	double cf;
	DATA_T inout[2];

	for(i = 0; i < count; i += 2){	
		inout[0] = buf[i] * DIV_31BIT;
		inout[1] = buf[i + 1] * DIV_31BIT;
		fft_bufL0[fft_cycle[0]][fft_count[0]] = inout[0];
		fft_bufR0[fft_cycle[0]][fft_count[0]] = inout[1];
		fft_bufL1[fft_cycle[1]][fft_count[1]] = inout[0];
		fft_bufR1[fft_cycle[1]][fft_count[1]] = inout[1];
		inout[0] = 0;
		inout[1] = 0;		
		cf = (double)fft_count[0] * div_fft_size;
		if(cf >= 0.5) cf = 1.0 - cf;
		inout[0] += fft_bufL0[fft_rofs[0]][fft_count[0]] * cf;
		inout[1] += fft_bufR0[fft_rofs[0]][fft_count[0]] * cf;	
		cf = (double)fft_count[1] * div_fft_size;
		if(cf >= 0.5) cf = 1.0 - cf;
		inout[0] += fft_bufL1[fft_rofs[1]][fft_count[1]] * cf;
		inout[1] += fft_bufR1[fft_rofs[1]][fft_count[1]] * cf;	
		buf[i] = inout[0] * div_fft_size * M_32BIT; //  31bit * cf*=2.0
		buf[i + 1] = inout[1] * div_fft_size * M_32BIT; //  31bit * cf*=2.0

		if((++fft_count[0]) >= fft_size){
			rdft(fft_size, 1, &fft_bufL0[fft_cycle[0]][0], fft_ip, fft_w);
			rdft(fft_size, 1, &fft_bufR0[fft_cycle[0]][0], fft_ip, fft_w);	
			custom_fft_dataL(fft_bufL0[fft_cycle[0]]);
			custom_fft_dataR(fft_bufR0[fft_cycle[0]]);
			rdft(fft_size, -1, &fft_bufL0[fft_cycle[0]][0], fft_ip, fft_w);
			rdft(fft_size, -1, &fft_bufR0[fft_cycle[0]][0], fft_ip, fft_w);
			fft_count[0] = 0;
			fft_cycle[0] = 0x1 - fft_cycle[0];
			fft_rofs[0] = 0x1 - fft_cycle[0];
		}
		
		if((++fft_count[1]) >= fft_size){
			rdft(fft_size, 1, &fft_bufL1[fft_cycle[1]][0], fft_ip, fft_w);
			rdft(fft_size, 1, &fft_bufR1[fft_cycle[1]][0], fft_ip, fft_w);	
			custom_fft_dataL(fft_bufL1[fft_cycle[1]]);
			custom_fft_dataR(fft_bufR1[fft_cycle[1]]);
			rdft(fft_size, -1, &fft_bufL1[fft_cycle[1]][0], fft_ip, fft_w);
			rdft(fft_size, -1, &fft_bufR1[fft_cycle[1]][0], fft_ip, fft_w);
			fft_count[1] = 0;
			fft_cycle[1] = 0x1 - fft_cycle[1];
			fft_rofs[1] = 0x1 - fft_cycle[1];
		}
	}
}

#endif



#ifdef TEST_FIR_EQ
FIR_EQ test_fir_eq;
#endif

void do_effect(DATA_T *buf, int32 count)
{
	int32 i;
	int mono = play_mode->encoding & PE_MONO;
	int32 nsamples = mono ? count : count * 2;
	int rev_flg = (opt_reverb_control > 0 && !(opt_reverb_control & 0x1))
			|| (opt_reverb_control < 0 && ! (opt_reverb_control & 0x80));
	int cho_flg = opt_chorus_control < 0;
	

#ifdef TEST_FFT
	test_fft(buf, nsamples);
#endif
#ifdef TEST_FIR_EQ
	apply_fir_eq(&test_fir_eq, buf, nsamples);
#endif	
	mix_compressor(buf, nsamples); // elion add.
	/* reverb in mono */
	if (opt_reverb_control && mono)
		do_mono_reverb(buf, count);
	/* for static reverb / chorus level */
	if (rev_flg	|| cho_flg) {
		set_dry_signal(buf, nsamples);
		/* chorus sounds horrible
		 * if applied globally on top of channel chorus
		 */
#if 0
		if (cho_flg)
			set_ch_chorus(buf, nsamples, -opt_chorus_control);
#endif
		if (rev_flg){
			int reverb_level = (opt_reverb_control < 0)	? -opt_reverb_control & 0x7f : DEFAULT_REVERB_SEND_LEVEL;
			set_ch_reverb(buf, nsamples, reverb_level);
		}
		mix_dry_signal(buf, nsamples);
			/* chorus sounds horrible
			 * if applied globally on top of channel chorus
			 */
#if 0
		if (cho_flg)
			do_ch_chorus(buf, nsamples);
#endif
		if (rev_flg)
			do_ch_reverb(buf, nsamples);
	}
	/* Noise shaping filter must apply at last */
	if(noise_sharp_type)
		ns_shaping(buf, nsamples);	
	if (opt_limiter)
		do_limiter(buf, count);
///r
#ifdef VST_LOADER_ENABLE
	do_master_vst(buf, nsamples, mono);
#endif /* VST_LOADER_ENABLE */
	
}



/************************************ inialize_effect ***************************************/

#if 0
void init_effect_status(void)
{
	int i;
	memset(&reverb_status_gs, 0, sizeof(reverb_status_gs));
	memset(&chorus_status_gs, 0, sizeof(chorus_status_gs));
	memset(&delay_status_gs, 0, sizeof(delay_status_gs));
	memset(&insertion_effect_gs, 0, sizeof(insertion_effect_gs));
	memset(&reverb_status_xg, 0, sizeof(reverb_status_xg));
	memset(&chorus_status_xg, 0, sizeof(chorus_status_xg));
	memset(variation_effect_xg, 0, sizeof(variation_effect_xg));
	memset(insertion_effect_xg, 0, sizeof(insertion_effect_xg));
}
#endif

#ifdef MULTI_THREAD_COMPUTE
void init_effect_buffer_thread(void);
#endif




void init_effect(void)
{
#ifdef TEST_FFT
	init_fft();
#endif
#ifdef TEST_FIR_EQ
	init_fir_eq(&test_fir_eq);
#endif
	init_mtrand();
	init_pink_noise(&global_pink_noise_light);
	init_ns_tap();
	init_ch_reverb();
	init_ch_delay();
	init_ch_chorus();
	init_eq_gs();
///r
	init_limiter();
	init_mix_compressor();
	init_vst_effect();
#ifdef MULTI_THREAD_COMPUTE
	init_effect_buffer_thread();
#endif
}




#ifdef MULTI_THREAD_COMPUTE
#include "thread_effect.c"
#endif