






/*

#include <string.h>

#ifdef ENABLE_HARKIO3
  #include "HarkFileIO_NH.h"
#elif  ENABLE_HARKIO2
  #include "HarkFileIO.h"
  using namespace harkio2;
#elif ENABLE_HARKIO1
  #include "HarkFileIO.h"
  using namespace harkio;
#endif

#include "HarkFileIOByMatrix.h"

#include "EstimationTransferFunction.hpp"

const char _TRANSFER_FUNCTION_SIGNATURE_TFMAT[] = "transfer function";
const char _TRANSFER_FUNCTION_SIGNATURE_TFMAT_PARTIAL[] = "partial transfer function";

EstimationTransferFunction::EstimationTransferFunction(int sampling_rate, int fft_length, bool is_debug, 
  string dir_export, bool is_export, int history_frames, int history_period) :
  SamplingRate(sampling_rate), numFFT(fft_length), IsDebug(is_debug), 
  IsExport(is_export), DirExport(dir_export), HistoryFrames(history_frames), HistoryPeriod(history_period)
{
    this->numFreq = this->numFFT / 2 + 1;
}

EstimationTransferFunction::~EstimationTransferFunction()
{
    // (add 2020.10)
    if(this->initTransFuncDatabase != NULL){
        delete this->initTransFuncDatabase;
    }
}

bool EstimationTransferFunction::getBasefromFile(const string &file_name, int &num_frq, int &num_mic, int &num_src)
{
    num_frq = 0;
    num_mic = 0;
    num_src = 0;

    CHarkFileIOByMatrix cHarkFile;

    // read header
    std::string fileType = string("transfer function");
    long int hFs, hNFFT, hNSrc, hNMic;
    if(!cHarkFile.ReadHeader(file_name.c_str(), fileType.c_str(), &hFs, &hNFFT, &hNSrc, &hNMic)){
        std::cerr << "EstimationTransferFunction: Failed to get header from the file." << std::endl;
        return false;
    }
    // check sampling rate
    if(hFs != this->SamplingRate) {
        std::cerr << "EstimationTransferFunction: Sampling rate is different between parameter and TF header." << std::endl;
        return false;
    }

    // read TF
    if(!cHarkFile.ReadTFData(file_name.c_str(), -1.0f, this->TransFuncDatabase)){
        std::cerr << "EstimationTransferFunction: Failed to get transfer function from the file." << std::endl;
        return false;
    }

    // TF size is nfreq, element is Matrix(nmic, nsrc)

    int nfreq = this->TransFuncDatabase.Data.size();

    if(nfreq > 0){
        // check number of freq. bin
        if(nfreq != this->numFreq){
            std::cerr << "EstimationTransferFunction: Number of freq. bin is different between parameter and TF." << std::endl;
            return false;
        }

        this->numMic = this->TransFuncDatabase.Data[0].rows();
        this->numSrc = this->TransFuncDatabase.Data[0].cols();
    }
    else{
        this->numMic = 0;
        this->numSrc = 0;
    }
    // check size of TF
    if(this->numMic == 0 || this->numSrc == 0){
        std::cerr << "EstimationTransferFunction: Size of transfer function is invalid." << std::endl;
        return false;
    }

    num_frq = this->numFreq;
    num_mic = this->numMic;
    num_src = this->numSrc;

    // initialize intermediate data
    this->initIntermData();

    return true;
}

bool EstimationTransferFunction::getBaseinDirectory(const string &dir_name, int &num_frq, int &num_mic, int &num_src)
{
    num_frq = 0;
    num_mic = 0;
    num_src = 0;

    std::string spathname = dir_name + string("/source.xml");
    char *spath = (char *)malloc((spathname.length() + 1) * sizeof(char));
    std::strcpy(spath, spathname.c_str());
    harkio_XML* xml = harkio_XML_newFromXML(spath, NULL);
    free(spath);
    if(!xml){
        std::cerr << "EstimationTransferFunction: Failed to read source position file." << std::endl;
        return false;
    }
    // check sampling rate
    if(xml->cfg){
        if(xml->cfg->samplingRate != this->SamplingRate){
            std::cerr << "EstimationTransferFunction: Sampling rate is different between parameter and xml." << std::endl;
            harkio_XML_delete(&xml);
            return false;
        }
    }
    harkio_XML_delete(&xml);

    // read TF
    CHarkFileIOByMatrix cHarkFile;
    if(!cHarkFile.ReadTFDataFromDir(dir_name.c_str(), -1.0f, this->TransFuncDatabase)) {
        std::cerr << "EstimationTransferFunction: Failed to get transfer function in the directory." << std::endl;
        return false;
    }

    this->numMic = this->TransFuncDatabase.micLocations.size();
    this->numSrc = this->TransFuncDatabase.sourceLocations.size();

    // check number of microphone and source of xml
    if(this->numMic == 0 || this->numSrc == 0){
        std::cerr << "EstimationTransferFunction: Number of mic./source positions is invalid." << std::endl;
        return false;
    }

    int nfreq = this->TransFuncDatabase.Data.size();
cout << "nfreq:" << nfreq << endl;

    if(nfreq > 0){
        if(nfreq != this->numFreq){
            std::cerr << "EstimationTransferFunction: Number of freq. bin is different between parameter and TF." << std::endl;
            return false;
        }

        // check number of microphne and source of TF
        if((this->numMic != this->TransFuncDatabase.Data[0].rows()) || 
           (this->numSrc != this->TransFuncDatabase.Data[0].cols())) {
            std::cerr << "EstimationTransferFunction: Number of mic./source positions is different from TF." << std::endl;
            return false;
        }
    }
    else{
        this->TransFuncDatabase.Data.resize(this->numFreq, BF::Matrix::O(this->numMic, this->numSrc));
    }

    // read intermediate data
    std::string ipathname = dir_name + string("/intermediate.mat"); 
    char *ipath = (char *)malloc((ipathname.length() + 1) * sizeof(char));
    std::strcpy(ipath, ipathname.c_str());
    CHarkMatFileIOByFMatrix cHarkMat;
    bool rtn = cHarkMat.ReadMatData(ipath, this->IntermData);
    free(ipath);
    if(rtn){
        int nmic = (this->IntermData.cols() - 5) / (2 * 2 * this->numFreq);
        int nsrc = this->IntermData.rows();
        // check size of intermediate data
        if(nmic != this->numMic || nsrc != this->numSrc) {
            std::cerr << "EstimationTransferFunction: Number of mic./source of intermediate data is invalid." << std::endl;
            return false;
        }
    }
    else{
        std::cout << "EstimationTransferFunction: Initialize intermediate data." << std::endl;

        // initialize intermediate data
        this->initIntermData();
    }

    num_frq = this->numFreq;
    num_mic = this->numMic;
    num_src = this->numSrc;

    return true;
}

void EstimationTransferFunction::initIntermData()
{
    size_t rows = this->numSrc;
    size_t cols = 1 + 3 + 1 + this->numFreq * 2 * this->numMic + this->numFreq * 2 * this->numMic;
    this->IntermData = Matrix<float>(rows, cols);

    for(size_t i = 0; i < rows; i++) {
        size_t j = 0;
        this->IntermData(i, j++) = this->TransFuncDatabase.sourceLocations[i].id;
        this->IntermData(i, j++) = this->TransFuncDatabase.sourceLocations[i].x;
        this->IntermData(i, j++) = this->TransFuncDatabase.sourceLocations[i].y;
        this->IntermData(i, j++) = this->TransFuncDatabase.sourceLocations[i].z;
        for(; j < ncol; j++){
            this->IntermData(i, j) = 0.0f;
        }
    }
}

void EstimationTransferFunction::initHistoryData()
{
    size_t rows = this->HistoryFrames;
    size_t cols = 1 + 1 + 3 + 1 + this->numFreq * 2 * this->numMic + this->numFreq * 2 * this->numMic;
    this->HistoryData = Matrix<float>(rows, cols);

    for(size_t i = 0; i < rows; i++){
        for(size_t j = 0; j < cols; j++){
            this->HistoryData(i, j) = -1.0f;
        }
    }

    this->idxHist = -1; // index for ring
}

bool EstimationTransferFunction::exportIntermData(const std::string &dir_name, int i_row)
{
    std::string pathname = dir_name + string("/intermediate.mat");
    char *path = (char *)malloc((pathname.length() + 1) * sizeof(char));
    strcpy(path, pathname.c_str());

    CHarkMatFileIOByFMatrix cHarkMat;
    bool rtn;
    if(i_row < 0){
        rtn = cHarkMat.WriteMatData(path, this->IntermData);
    }
    else{
        rtn = cHarkMat.ReplaceMatData(path, this->IntermData, i_row);
    }

    free(path);	

    return rtn;
}

bool EstimationTransferFunction::exportHistoryData(const std::string &dir_name, int i_row)
{
    std::string pathname = dir_name + string("/history.mat");
    char *path = (char *)malloc((pathname.length() + 1) * sizeof(char));
    std::strcpy(path, pathname.c_str());

    CHarkMatFileIOByFMatrix cHarkMat;
    bool rtn;
    if(i_row < 0){
        rtn = cHarkMat.WriteMatData(path, this->HistoryData);
    }
    else{
        rtn = cHarkMat.ReplaceMatData(path, this->HistoryData, i_row);
    }

    free(path);

    return rtn;
}

bool EstimationTransferFunction::exportTransferFunction(const std::string &path, bool isDir)
{
    std::string comment = std::string("transferFunction");

    bool rtn;
    CHarkFileIOByMatrix cHarkFile;
    if(isDir){
        rtn = cHarkFile.WriteTFDataToDir(path.c_str(), this->SamplingRate, this->numFFT, comment.c_str(), this->TransFuncDatabase);
    }
    else{
        rtn = cHarkFile.WriteTFData(path.c_str(), this->SamplingRate, this->numFFT, comment.c_str(), this->TransFuncDatabase);
    }

    return rtn;
}

void EstimationTransferFunction::copyKeepTF()
{
    // size(numFreq), element(numMic,numSrc) -> size(numSrc), element(numMic,numFreq)

    this->keepTFdata.resize(this->numSrc, BF::Matrix(this->numMic, this->numFreq));

    for(size_t j = 0; j < this->numFreq; j++){
        for(size_t i = 0; i < this->numSrc; i++) {
            this->keepTFdata[i].col(j) = this->TransFuncDatabase.Data[j].col(i);
        }
    }
}

void EstimationTransferFunction::copyInitTFdatabase()
{	// リセット用に伝達関数データを取っておく (add 2020.10)
    if(this->initTransFuncDatabase != NULL){
        delete this->initTransFuncDatabase;
    }

    this->initTransFuncDatabase = new BF::TransformFunctionDatabase(this->TransFuncDatabase);
}

void EstimationTransferFunction::resetTFdatabase()
{	// 伝達関数データをリセットする (add 2020.10)
    BF::TransformFunctionDatabase *newTransformFunctionDatabase = new BF::TransformFunctionDatabase(*this->initTransFuncDatabase);
    std::swap(this->TransFuncDatabase, *newTransformFunctionDatabase);
    delete newTransformFunctionDatabase;
}

BF::Matrix EstimationTransferFunction::_RelaTF(BF::Matrix X)
{	// 相対TFの算出
    int rows = X.rows();
    int cols = X.cols();

    BF::Matrix Y0n(rows, cols);
    BF::Matrix Yr = BF::Matrix::O(rows, cols);
    BF::Complex Y0m, Y0p;

    for(size_t j = 0; j < cols; j++) {
        Y0n.col(j) = X.col(j) / X.col(j).norm(); // 振幅正規化
        Y0m = Y0n.col(j).sum();
        Y0m /= rows; // 平均位相
        Y0p = std::conj(Y0m / std::abs(Y0m)); // 振幅1にする
        Yr.col(j) = Y0n.col(j) * Y0p; // 位相正規化
    }

    return Yr;
}

void EstimationTransferFunction::_getIntermediate(int tfId, float &id, float &x, float &y, float &z, float &frames, Matrix<std::complex<float> > &myu, Matrix<std::complex<float> > &sig)
{	// 中間データの取得
    int ncol1 = 5 + this->numFreq * 2 * this->numMic;
    int ncol2 = ncol1 + this->numFreq * 2 * this->numMic;
    int ii, jj;
    int c = 0;
    id     = this->IntermData(tfId, c++);
    x      = this->IntermData(tfId, c++);
    y      = this->IntermData(tfId, c++);
    z      = this->IntermData(tfId, c++);
    frames = this->IntermData(tfId, c++);
    ii = 0; jj = 0;
    for( ; c < ncol1; ){
        double re = this->IntermData(tfId, c++);
        double im = this->IntermData(tfId, c++);
        myu(ii, jj++) = std::complex(re, im);
        if(jj == this->numFreq){ ii++; jj = 0; }
    }
    ii = 0; jj = 0;
    for ( ; c < ncol2; ) {
        double re = this->IntermData(tfId, c++);
        double im = this->IntermData(tfId, c++);
        sig(ii, jj++) = std::complex(re, im);
        if(jj == this->numFreq){ ii++; jj = 0; }
    }
}

void EstimationTransferFunction::_setIntermediate(int tfId, float frames, Matrix<std::complex<float> > myu, Matrix<std::complex<float> > sig)
{	// 中間データの更新
    int c = 4;
    this->IntermData(tfId, c++) = frames;
    for(size_t i = 0; i < this->numMic; i++){
        for(size_t j = 0; j < this->numFreq; j++){
            this->IntermData(tfId, c++) = myu(i, j).real();
            this->IntermData(tfId, c++) = myu(i, j).imag();
        }
    }
    for(size_t i = 0; i < this->numMic; i++){
        for(size_t j = 0; j < this->numFreq; j++){
            this->IntermData(tfId, c++) = sig(i, j).real();
            this->IntermData(tfId, c++) = sig(i, j).imag();
        }
    }
}

void EstimationTransferFunction::estimateTransferFunction(int count, BF::Matrix &x, std::vector<BF::SourceLocation> sources)
{
	BF::Matrix xx(x);	

	// 入力スペクトルから相対TFを算出
	BF::Matrix YR = _RelaTF(xx);//

	// TF更新処理

	BF::Matrix TF1(this->numMic, this->numFreq); // 更新TF
	
	float i_id;                                    // 当該座標の中間データ:TFID
	float i_x, i_y, i_z;                           //                   :x,y,z座標
	float i_frames;                                //                   :処理フレーム数
	BF::Matrix i_myu(this->numMic, this->numFreq); //                   :平均(Mic x Freq)
	BF::Matrix i_sig(this->numMic, this->numFreq); //                   :分散(Mic x Freq)
	
	for (int k = 0; k < sources.size(); k++) {
		int tfid = sources[k].id; // 更新対象tfid

		if (tfid > this->numSrc) { continue; };

		// 当該座標の中間データを取得
		_getIntermediate(tfid, i_id, i_x, i_y, i_z, i_frames, i_myu, i_sig);

		float inc_frames = i_frames + 1.0f; // 次のフレーム数
		
		if (i_frames > 0) {
			// 伝達関数の更新
			TF1 = this->keepTFdata[tfid]; // ノーマライズ前の伝達関数
			BF::Matrix TFa = YR;
			BF::Matrix TFp = TF1.elementwiseFMultiplied(TFa);
			BF::Complex Y0m, Y0p;
			for (int j = 0; j < this->numFreq; j++) {
				Y0m = TFp.getColumn(j).getElementSum(); // 更新前と本フレームの位相差
				Y0p = std::conj(Y0m / abs(Y0m)); // 振幅1にする
				TFa.setColumn(j, TFa.getColumn(j) * Y0p); // 更新量
			}
			TF1 = TF1 * i_frames;
			TF1 = TF1 + TFa;
			TF1 = TF1 / inc_frames; // フレームの加重をかける
			this->keepTFdata[tfid] = TF1; // ノーマライズ前のデータをとっておく			
			TF1 = _RelaTF(TF1); // 中間データに保存するのはノーマライズ後のもの

			// 分散の更新
			BF::Complex myuAt, sigAt, TFat;
			double sqr_old, sqr_new, myu_r, sig_r, myu_i, sig_i;
			for (int i = 0; i < this->numMic; i++) {
				for (int j = 0; j < this->numFreq; j++) {
					myuAt = i_myu.getElementAt(i, j);
					sigAt = i_sig.getElementAt(i, j);
					TFat = TF1.getElementAt(i, j);
					
					sqr_old = (sigAt.real() + myuAt.real() * myuAt.real()) * i_frames;
					sqr_new = sqr_old + TFat.real() * TFat.real();
					myu_r = (myuAt.real() * i_frames + TFat.real()) / inc_frames;
					sig_r = sqr_new / inc_frames - myu_r * myu_r;
					
					sqr_old = (sigAt.imag() + myuAt.imag() * myuAt.imag()) * i_frames;
					sqr_new = sqr_old + TFat.imag() * TFat.imag();
					myu_i = (myuAt.imag() * i_frames + TFat.imag()) / inc_frames;
					sig_i = sqr_new / inc_frames - myu_i * myu_i;
					
					i_myu.setElementAt(i, j, BF::Complex(myu_r, myu_i));
					i_sig.setElementAt(i, j, BF::Complex(sig_r, sig_i));
				}
			}
		}
		else {
			// 伝達関数
			TF1 = YR; // 最初はコピー
			this->keepTFdata[tfid] = TF1; // ノーマライズ前のデータをとっておく

			// 分散
			i_myu = TF1;
			i_sig = BF::Matrix::O(this->numMic, this->numFreq);
		}

//for (int i = 0; i < this->numMic; i++) {
//  for (int j = 0; j < this->numFreq; j++) {
//    cout << TF1.getElementAt(i, j) << ", ";
//    cout << i_myu.getElementAt(i, j) << ", ";
//    cout << i_sig.getElementAt(i, j) << ", ";
//  }
//  cout << endl;
//}
//cout << endl;

		// 伝達関数更新
		for(int j = 0; j < this->numFreq; j++) {
			this->TransFuncDatabase.Data[j].setColumn(tfid, TF1.getColumn(j));
		}

		// 中間データの更新
		_setIntermediate(tfid, inc_frames, i_myu, i_sig);

		if (!this->DirExport.empty()) {
			// 伝達関数のエクスポート
			CHarkFileIOByMatrix	cHarkFile;
			if (!cHarkFile.UpdateTFDataToDir(this->DirExport.c_str(), tfid, this->TransFuncDatabase)) {
				cerr << "EstimationTransferFunction: Failed to update TF." << endl;
			}

			// 中間データのエクスポート
			if (!exportIntermData(this->DirExport.c_str(), tfid)) {
				cerr << "EstimationTransferFunction: Failed to export intermediate data." << endl;
			}
		}
		
		// ヒストリデータ
		if (this->IsExport && (count % this->HistoryPeriod) == 0) {
			// ヒストリ追加			
			if (++this->idxHist == this->HistoryFrames) { this->idxHist = 0; }; // リングバッファ			
			this->HistoryData.setElementAt(this->idxHist, 0, count); // フレームインデクス			
			BF::FMatrix hDmat = this->IntermData.getRow(tfid);       // 更新した中間データを
			this->HistoryData.setSubmatrix(this->idxHist, 1, hDmat); //                   追加

			// エクスポート
			if (!exportHistoryData(this->DirExport, this->idxHist)) {
				cerr << "EstimationTransferFunction: Failed to export history data." << endl;
			}
		}
		
		if (this->IsDebug) {
			printf("(Frame %d) Estimate transfer function:\n", count);
			// 更新音源座標
			printf("Source: %d %f %f %f\n", (int)i_id, i_x, i_y, i_z);
			// 更新後の伝達関数
			BF::Complex TFat;
			printf("Updated TF:\n");
			for (int j = 0; j < this->numFreq; j++) {
				for (int i = 0; i < this->numMic; i++) {
					TFat = TF1.getElementAt(i, j);
					printf("%f+%fi ", TFat.real(), TFat.imag());
				}
			}
			printf("\n");
		}

	}
}

void EstimationTransferFunction::outputTF(const bool &isSendAll, 
	                                      RCPtr<TransferFunction> &tfData,
                                          vector<BF::SourceLocation> location)
{	// 伝達関数データを出力する (add 2020.10)
	// isSendAll : (true)全伝達関数・伝達関数以外の情報を出力 / (false)当該音源位置に対応する伝達関数のみ出力

	// WhatIsThis
	if (isSendAll) {
		(*tfData).SetWhatIsThis(_TRANSFER_FUNCTION_SIGNATURE_TFMAT);
	} else {
		(*tfData).SetWhatIsThis(_TRANSFER_FUNCTION_SIGNATURE_TFMAT_PARTIAL);
	}

	// 音源位置
	Vector<HARK::Position> sources;
	if (isSendAll) {
		for (int i = 0; i < this->TransFuncDatabase.sourceLocations.size(); i++) {
			HARK::Position pos;
			pos.id = this->TransFuncDatabase.sourceLocations[i].id;
			pos.sys = HARK::Cartesian;
			pos.coord[0] = this->TransFuncDatabase.sourceLocations[i].x;
			pos.coord[1] = this->TransFuncDatabase.sourceLocations[i].y;
			pos.coord[2] = this->TransFuncDatabase.sourceLocations[i].z;
			pos.path = "";
		    pos.channelsUse = 0;
			pos.channels.clear();
			sources.push_back(pos);
		}
	}
	(*tfData).SetSources(sources);

	// 音源位置（隣接情報）
	HARK::Neighbor neighbors;
	if (isSendAll) {
		for (int i = 0; i < this->TransFuncDatabase.sourceNeighbors.size(); i++) {
			neighbors.ids.push_back(this->TransFuncDatabase.sourceLocations[i].id);

			Vector<int>	neighborIds;
			for (int j = 0; j < this->TransFuncDatabase.sourceNeighbors[i].size(); j++) {
				neighborIds.push_back(this->TransFuncDatabase.sourceNeighbors[i][j]);
			}
			neighbors.neighbors.push_back(neighborIds);

			*//*Vector<Position> poses;
			for (int j = 0; j < this->TransFuncDatabase.sourceNeighbors[i].size(); j++) {
				Position pos;
				pos.id = this->TransFuncDatabase.sourceNeighbors[i][j];
				pos.sys = HARK::Cartesian;
				pos.coord[0] = this->TransFuncDatabase.sourceLocations[pos.id].x;
				pos.coord[1] = this->TransFuncDatabase.sourceLocations[pos.id].y;
				pos.coord[2] = this->TransFuncDatabase.sourceLocations[pos.id].z;
				pos.path = "";
			    pos.channelsUse = 0;
				pos.channels.clear();
				poses.push_back(pos);
			}
			neighbors.poses.push_back(poses);*//*

			neighbors.alg = HARK::NearestNeighbor;
		}
	}
	(*tfData).SetNeighbors(neighbors);

	// マイクロホン位置
	Vector<HARK::Position> microphones;
	if (isSendAll) {
		for (int i = 0; i < this->TransFuncDatabase.micLocations.size(); i++) {
			HARK::Position pos;
			pos.id = this->TransFuncDatabase.micLocations[i].id;
			pos.sys = HARK::Cartesian;
			pos.coord[0] = this->TransFuncDatabase.micLocations[i].x;
			pos.coord[1] = this->TransFuncDatabase.micLocations[i].y;
			pos.coord[2] = this->TransFuncDatabase.micLocations[i].z;
			pos.path = "";
		    pos.channelsUse = 0;
			pos.channels.clear();
			microphones.push_back(pos);
		}
	}
	(*tfData).SetMicrophones(microphones);

	// コンフィグ情報
	HARK::Config config;
	if (isSendAll) {
		config.comment = string("transferFunction");
		config.synchronousAverage = 1;
		config.TSPpath = "";
		config.TSPoffset = 0;
		config.TSPLength = 1;
		config.peakSearchFrom = 0;
		config.peakSearchTo = 0;
		config.nfft = this->numFFT;
		config.samplingRate = this->SamplingRate;
		config.signalMax = 1;
	}
	(*tfData).SetConfig(config);

	const int frqs = this->TransFuncDatabase.Data.size(); // this->numFFT/2+1
	const int mics = this->TransFuncDatabase.micLocations.size(); // this->TransFuncDatabase.Data[0].getRowCount()
	const int srcs = this->TransFuncDatabase.sourceLocations.size(); // this->TransFuncDatabase.Data[0].getColumnCount()

	// 定位用伝達関数情報
	Map<int, Matrix<complex<float>>> localization;
	if (isSendAll) {
		for (int i = 0; i < srcs; i++) {
			Matrix<complex<float>> mat;
			mat.resize(mics, frqs);
			for (int j = 0; j < mics; j++) {
				for (int k = 0; k < frqs; k++) {
					BF::Complex value = this->TransFuncDatabase.Data[k].getElementAt(j, i);
					mat(j, k) = complex<float>(value);
				}
			}
			localization.insert(make_pair(this->TransFuncDatabase.sourceLocations[i].id, mat));
		}
	} else {
		for (int i = 0; i < location.size(); i++) {
			int tfid = location[i].id;
			Matrix<complex<float>> mat;
			mat.resize(mics, frqs);
			for (int j = 0; j < mics; j++) {
				for (int k = 0; k < frqs; k++) {
					BF::Complex value = this->TransFuncDatabase.Data[k].getElementAt(j, tfid);
					mat(j, k) = complex<float>(value);
				}
			}
			localization.insert(make_pair(tfid, mat));
		}
	}
	(*tfData).SetLocalization(localization);

	// 分離用伝達関数情報
	Map<int, Matrix<complex<float>>> separation;
	if (isSendAll) {
		for (int i = 0; i < srcs; i++) {
			Matrix<complex<float>> mat;
			mat.resize(mics, frqs);
			for (int j = 0; j < mics; j++) {
				for (int k = 0; k < frqs; k++) {
					BF::Complex value = std::conj(this->TransFuncDatabase.Data[k].getElementAt(j, i));
					mat(j, k) = complex<float>(value);
				}
			}
			separation.insert(make_pair(this->TransFuncDatabase.sourceLocations[i].id, mat));
		}
	} else {
		for (int i = 0; i < location.size(); i++) {
			int tfid = location[i].id;
			Matrix<complex<float>> mat;
			mat.resize(mics, frqs);
			for (int j = 0; j < mics; j++) {
				for (int k = 0; k < frqs; k++) {
					BF::Complex value = std::conj(this->TransFuncDatabase.Data[k].getElementAt(j, tfid));
					mat(j, k) = complex<float>(value);
				}
			}
			separation.insert(make_pair(tfid, mat));
		}
	}
	(*tfData).SetSeparation(separation);
}
*/
