// Copyright (C) 1999 Jean-Marc Valin #include "BufferedNode.h" #include "Buffer.h" #include "Vector.h" #include #include #ifdef HAVE_FLOAT_H #include #endif using namespace std; namespace FD { class LTP; DECLARE_NODE(LTP) /*Node * * @name LTP * @category DSP:Adaptive * @description Long-term predictor, finds best correlation (pitch) within (START <= sample delay <= END) * * @input_name INPUT * @input_type Vector * @input_description Input frame * * @output_name OUTPUT * @output_type Vector * @output_description [pitch gain, pitch period] * * @parameter_name START * @parameter_type int * @parameter_description Smallest pitch allowed * * @parameter_name END * @parameter_type int * @parameter_description Largest pitch allowed * END*/ class LTP : public BufferedNode { int inputID; int outputID; int start; int end; public: LTP(string nodeName, ParameterSet params) : BufferedNode(nodeName, params) { inputID = addInput("INPUT"); outputID = addOutput("OUTPUT"); start = dereference_cast (parameters.get("START")); end = dereference_cast (parameters.get("END")); inputsCache[inputID].lookBack=1; } void calculate(int output_id, int count, Buffer &out) { ObjectRef inputValue = getInput(inputID, count); const Vector &in = object_cast > (inputValue); int inputLength = in.size(); Vector &output = *Vector::alloc(2); out[count] = &output; const Vector *past; bool can_look_back = false; if (count > 0) { ObjectRef pastInputValue = getInput(inputID, count-1); can_look_back=true; past = &object_cast > (pastInputValue); } float best=-FLT_MAX; float best_gain=0; int best_T=0; //float scores[end+1]; //float gains[end+1]; DYN_VEC(float, end+1, scores); DYN_VEC(float, end+1, gains); /*static float old_scores[2000]; static bool init=false; if (!init) { for (int i=0;i<2000;i++) old_scores[i]=0; init=true; }*/ for (int i=0;i best) { //prevents period doubling if (1 || score/best > 1.6 || abs(lag-2*best_T) > 5) { best = score; best_T = lag; best_gain = corr/(energy+.00000001); } //else {cerr << "doubling\n";} } } //cout << endl; /* for (int i=start;i<=end;i++) { scores[i] += .6*old_scores[i]; old_scores[i]=scores[i]; cout << scores[i] << " "; } cout << endl; */ for (int i=4;i>=2;i--) { int div = best_T/i; float max_score = 0; float max_gain = 0; int max_T=0; for (int j=div-2; j <= div+2 ; j++) { if (scores[j]>max_score) { max_score = scores[j]; max_gain = gains[j]; max_T = j; } } if (max_score*2 > best || max_gain > .3) { if (i==2) { int div2 = best_T+max_T; float max_score2 = 0; float max_gain2 = 0; int max_T2=0; for (int j=div2-2; j <= div2+2 && jmax_score2) { max_score2 = scores[j]; max_gain2 = gains[j]; max_T2 = j; } } if (!(max_score2*2 > best || max_gain > .2)) continue; } best_T = max_T; best_gain = max_gain; break; } } //cout << endl; if (best_gain > 1.2) best_gain = 1.2; if (best_gain < -.2) best_gain = -.2; //cout << endl; output[0] = best_gain; output[1] = best_T; //cout << output[0] << " " << output[1] << endl; } }; }//namespace FD