void performanceGate() {
	std::vector<double> input;
	input.resize(8192, 0);
	std::vector<double> output;
	output.resize(8192, 0);
	double sampleRate = 48000.0;
	{
		double phase = 0;
		double baseCycle = 2.0*M_PI/sampleRate * 1280.0;
		for (int32_t iii=0; iii<input.size(); iii++) {
			input[iii] = cos(phase) * 5.0;
			phase += baseCycle;
			if (phase >= 2*M_PI) {
				phase -= 2*M_PI;
			}
		}
	}
	TEST_PRINT("Start Gate performance ...");
	Performance perfo;
	audio::algo::chunkware::Gate algo;
	algo.setSampleRate(48000);
	algo.setThreshold(0);
	algo.setAttack(0.1);
	algo.setRelease(2);
	algo.init();
	for (int32_t iii=0; iii<4096; ++iii) {
		perfo.tic();
		algo.process(&output[0], &input[0], input.size(), 1, audio::format_double);
		perfo.toc();
		std::this_thread::sleep_for(std::chrono::milliseconds(1));
	}
	TEST_PRINT("Performance Gate (double): ");
	TEST_PRINT("    blockSize=" << input.size() << " sample");
	TEST_PRINT("    min < avg < max =" << perfo.getMinProcessing().count() << "ns < "
	                                   << perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration() << "ns < "
	                                   << perfo.getMaxProcessing().count() << "ns ");
	TEST_PRINT("    min < avg < max = " << (float((perfo.getMinProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < "
	                                    << (float(((perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration())*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "% < "
	                                    << (float((perfo.getMaxProcessing().count()*sampleRate)/double(input.size()))/1000000000.0)*100.0 << "%");
}
int main(int _argc, const char** _argv) {
	// the only one init for etk:
	etk::init(_argc, _argv);
	std::string inputName = "";
	bool performance = false;
	bool perf = false;
	int64_t sampleRate = 48000;
	for (int32_t iii=0; iii<_argc ; ++iii) {
		std::string data = _argv[iii];
		if (etk::start_with(data,"--in=")) {
			inputName = &data[5];
		} else if (data == "--performance") {
			performance = true;
		} else if (data == "--perf") {
			perf = true;
		} else if (etk::start_with(data,"--sample-rate=")) {
			data = &data[14];
			sampleRate = etk::string_to_int32_t(data);
		} else if (    data == "-h"
		            || data == "--help") {
			TEST_PRINT("Help : ");
			TEST_PRINT("    ./xxx --fb=file.raw --mic=file.raw");
			TEST_PRINT("        --in=YYY.raw        inout file");
			TEST_PRINT("        --performance       Generate signal to force algo to maximum process time");
			TEST_PRINT("        --perf              Enable performence test (little slower but real performence test)");
			TEST_PRINT("        --sample-rate=XXXX  Signal sample rate (default 48000)");
			exit(0);
		}
	}
	// PERFORMANCE test only ....
	if (performance == true) {
		performanceCompressor();
		performanceLimiter();
		performanceGate();
		return 0;
	}
	if (inputName == "") {
		TEST_ERROR("Can not Process missing parameters...");
		exit(-1);
	}
	TEST_INFO("Read input:");
	std::vector<double> inputData = convert(etk::FSNodeReadAllDataType<int16_t>(inputName));
	TEST_INFO("    " << inputData.size() << " samples");
	// resize output :
	std::vector<double> output;
	output.resize(inputData.size(), 0);
	// process in chunk of 256 samples
	int32_t blockSize = 256;
	
	Performance perfo;
	/*
	audio::algo::chunkware::Compressor algo;
	algo.setThreshold(-10);
	algo.setRatio(-5);
	int32_t lastPourcent = -1;
	for (int32_t iii=0; iii<output.size()/blockSize; ++iii) {
		if (lastPourcent != 100*iii / (output.size()/blockSize)) {
			lastPourcent = 100*iii / (output.size()/blockSize);
			TEST_INFO("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize << " " << lastPourcent << "/100");
		} else {
			TEST_VERBOSE("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize);
		}
		perfo.tic();
		algo.process(audio::format_double, &output[iii*blockSize], &inputData[iii*blockSize], blockSize, 1);
		if (perf == true) {
			perfo.toc();
			std::this_thread::sleep_for(std::chrono::milliseconds(1));
		}
	}
	*/
	audio::algo::chunkware::Limiter algo;
	algo.setSampleRate(48000);
	algo.setThreshold(0);
	algo.setAttack(0.1);
	algo.setRelease(2);
	algo.init(1);
	int32_t lastPourcent = -1;
	for (int32_t iii=0; iii<output.size()/blockSize; ++iii) {
		if (lastPourcent != 100*iii / (output.size()/blockSize)) {
			lastPourcent = 100*iii / (output.size()/blockSize);
			TEST_INFO("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize << " " << lastPourcent << "/100");
		} else {
			TEST_VERBOSE("Process : " << iii*blockSize << "/" << int32_t(output.size()/blockSize)*blockSize);
		}
		perfo.tic();
		algo.process(&output[iii*blockSize], &inputData[iii*blockSize], blockSize, 1, audio::format_double);
		if (perf == true) {
			perfo.toc();
			std::this_thread::sleep_for(std::chrono::milliseconds(1));
		}
	}
	
	
	if (perf == true) {
		TEST_INFO("Performance Result: ");
		TEST_INFO("    blockSize=" << blockSize << " sample");
		TEST_INFO("    min=" << perfo.getMinProcessing().count() << " ns");
		TEST_INFO("    max=" << perfo.getMaxProcessing().count() << " ns");
		TEST_INFO("    avg=" << perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration() << " ns");
		
		TEST_INFO("    min=" << (float((perfo.getMinProcessing().count()*sampleRate)/blockSize)/1000000000.0)*100.0 << " %");
		TEST_INFO("    max=" << (float((perfo.getMaxProcessing().count()*sampleRate)/blockSize)/1000000000.0)*100.0 << " %");
		TEST_INFO("    avg=" << (float(((perfo.getTotalTimeProcessing().count()/perfo.getTotalIteration())*sampleRate)/blockSize)/1000000000.0)*100.0 << " %");
	}
	etk::FSNodeWriteAllDataType<int16_t>("output.raw", convert(output));
	
}