
/************************************************************
**	Delta.c
**
**  Private :
**
**  History :
**     2013.05.13 M.Takigahira Build有無指定に対応
**     2013.04.26 M.Takigahira 処理精査、インデント修正、全てのloop内ifを排除
**                             処理順序の変更、センターフレームインデックスを固定値からDEL_WINに変更
**     2013.01.10 kama@SIF     新規作成(V1.0)
**
**  Description
**  -----------
**  静的特徴量から動的特徴量を求める
**  入力1　：フィルタバンク
**  出力1　：動的特徴量を追加した、フィルタバンク
**
*/

///////////////////////////////////////////////////////////////
//  Include Files
#include "build_modules.h"
//////////#include "header.h"
#include "HA_log.h"
#include "android_hark.h"

///////////////////////////////////////////////////////////////
//  Define Macros
#define	DEL_WIN 	(2)
#define	B_FACTOR 	(5.0f) // for(i=1; i<=DEL_WIN; i++){ B_FACTOR+=i*i; } ==> 1^2 + 2^2 ==> 5

#if !defined BUILD_MODULE_DELTA
///////////////////////////////////////////////////////////////
//  Dummy Functions for build empty methods.
void ClearDelta(void){ }
int	Delta(
		int num_src,
		int count,
		HA_Float input_fbank[ARY_NUM_SRC][ARY_NUM_FBANK_DELTA_POWER],
		HA_Float output_fbank[ARY_NUM_SRC][ARY_NUM_FBANK_DELTA_POWER]
		){ return 0; }
#else // #if defined BUILD_MODULE_DELTA
///////////////////////////////////////////////////////////////
//  Parameter
static int num_fbank_power = ARY_NUM_FBANK_POWER;
static HA_Float bfactor = 1.0f / (2.0f * B_FACTOR);

///////////////////////////////////////////////////////////////
//  Local Buffer
HA_Float	input[ARY_NUM_SRC][DEL_WIN*2+1][ARY_NUM_FBANK_POWER];
//HA_Float	sum[ARY_NUM_SRC][ARY_NUM_FBANK_POWER]; //TAKIGAHIRA

///////////////////////////////////////////////////////////////
//  Clear
void ClearDelta(void) /* 2013.02.22 初期化処理を追加 */
{
	bzero(input, sizeof(input));
	//bzero(sum, sizeof(sum)); //TAKIGAHIRA
}

///////////////////////////////////////////////////////////////
//  Initialize
void HAInitDelta(void)
{
	bfactor = 1.0f / (2.0f * B_FACTOR);
}

///////////////////////////////////////////////////////////////
//  SetParam
int HASetParamDelta(int *param_fbank)
{
    if(*param_fbank <= 0){
        return -1;
    }
	num_fbank_power = (*param_fbank)+1;
    return 0;
}

int HAGetParamDelta(int *param_fbank)
{
	*param_fbank = num_fbank_power-1;
	return 0;
}

///////////////////////////////////////////////////////////////
//  MAIN
int	Delta(
	int	num_src,
	int	count,
	HA_Float	input_fbank[ARY_NUM_SRC][ARY_NUM_FBANK_DELTA_POWER],
	HA_Float	output_fbank[ARY_NUM_SRC][ARY_NUM_FBANK_DELTA_POWER]
	)
{
	int	s, i, j, k;
	HA_Float sum;

	for(s=0; s<num_src; s++){
		// 過去５（DEL_WIN*2+1）フレーム分のフィルタバンクを確保
		//for(i=(DEL_WIN*2+1)-1; i>0; i--){ // i != 0 // 過去フレームのシフト
		for(i=(DEL_WIN+DEL_WIN+1)-1; i>0; i--){ // i != 0 // 過去フレームのシフト
			//for(j=0; j<num_fbank_power; j++){
			for(j=num_fbank_power-1; j>=0; j--){
				input[s][i][j] = input[s][i-1][j];
			}
		}
		//for(j=0; j<num_fbank_power; j++){ // i == 0 // 最新フレーム
		for(j=num_fbank_power-1; j>=0; j--){ // i == 0 // 最新フレーム
			input[s][0][j] = input_fbank[s][j];
		}

		//for(i=0; i<(DEL_WIN*2+1); i++){
		//	LOGI("s=%d, i=%d : input[s][i][0](%f)\n", s, i, input[s][i][0]);
		//}

		// 動的特徴量計算
		//for(j=0; j<num_fbank_power; j++){ // パワー項も含めデルタを求める
		//	sum[s][j] = 0.0f;
		//	for(i=1; i<=DEL_WIN; i++){
		//		sum[s][j] += (input[s][DEL_WIN-i][j] - input[s][DEL_WIN+i][j]) * i;
		//		//if(j==0){ LOGI("i=%d : input[s][%d, %d][j](%f, %f), sum[s][j](%f)\n", i, DEL_WIN-i, DEL_WIN+i, input[s][DEL_WIN-i][j], input[s][DEL_WIN+i][j], sum[s][j]); } // debug
		//	}
		//	sum[s][j] *= 1.0f / (2.0f * B_FACTOR); // [B_FACTOR]係数をコンパイル時計算とするため[/=]の代わりに逆数と[*=]で記述している
		//}

		// 出力（非デルタ、デルタでループを分けているが実質の連続メモリアクセスとなる）
		//j=0;
		//for(; j<num_fbank_power; j++){
		//	output_fbank[s][j] = input[s][DEL_WIN][j]; // 非デルタ項はパワー項も含め、現在値（センター）をスルー
		//}
		//for(k=0; k<num_fbank_power; k++, j++){ // k=j+(fbank_count+1)
		//	sum = 0.0f;
		//	for(i=1; i<=DEL_WIN; i++){
		//		sum += (input[s][DEL_WIN-i][k] - input[s][DEL_WIN+i][k]) * i;
		//		//if(k==0){ LOGI("i=%d : input[s][%d, %d][k](%f, %f), sum[s][k](%f)\n", i, DEL_WIN-i, DEL_WIN+i, input[s][DEL_WIN-i][k], input[s][DEL_WIN+i][k], sum[s][k]); } // debug
		//	}
		//	output_fbank[s][j] = sum * bfactor; // B_FACTOR計算を初期化へ移動
		//	//output_fbank[s][j] = sum[s][k]; // B_FACTOR計算を動的特徴量計算へ移動
		//	//if(j==0){ LOGI("%f\n", output_fbank[s][j]); } // debug
		//}
		j=num_fbank_power+num_fbank_power-1; k=num_fbank_power-1;
		for(; k>=0; k--, j--){
			sum = 0.0f;
			for(i=1; i<=DEL_WIN; i++){
				sum += (input[s][DEL_WIN-i][k] - input[s][DEL_WIN+i][k]) * i;
			}
			output_fbank[s][j] = sum * bfactor; // B_FACTOR計算を初期化へ移動
		}
		for(; j>=0; j--){
			output_fbank[s][j] = input[s][DEL_WIN][j]; // 非デルタ項はパワー項も含め、現在値（センター）をスルー
		}
	}
	return(OK);
}
#endif // BUILD_MODULE_DELTA

// EOF
