/// <summary> /// 频率滤波。传入要保留的起止频率 /// </summary> /// <param name="data"></param> /// <param name="beginf"></param> /// <param name="endf"></param> /// <returns></returns> public static int[] FrequencyFilter(int[] data, double beginf, double endf) { int k = data.Length; int dx = getmin2x(k); double dl = (double)NNLink.NBankManager.samplingRate / dx; double[] data1 = new double[dx]; double[] dataimag1 = new double[dx]; Array.Copy(data, data1, k); TWFFT.FFT(data1, dataimag1); //double[] data1t = new double[dx]; //for (int i = 0; i < dx; i++) data1t[i] = Math.Sqrt(data1[i] * data1[i] + dataimag1[i] * dataimag1[i]); int beginx = (int)(beginf / dl); int endx = (int)(endf / dl); for (int i = 0; i < dx; i++) { if (i < beginx || i > dx - beginx || (i > endx && i < dx - endx)) { data1[i] = 0; //dataimag1[i] = 0; } } TWFFT.IFFT(data1, dataimag1); int[] res = new int[k]; for (int i = 0; i < k; i++) { res[i] = (int)data1[i]; } return(res); }
/// <summary> /// 频域修正 /// </summary> /// <param name="data1"></param> /// <param name="begin1"></param> /// <param name="end1"></param> /// <param name="data2"></param> /// <param name="begin2"></param> /// <param name="end2"></param> /// <returns></returns> public static int[] MiddleFilterCorrection(int[] data1, int begin1, int end1, int[] data2, int begin2, int end2) { int[] res = new int[end1 - begin1]; int k = Math.Max(end1 - begin1, end2 - begin2); int dx = FToneAnalysis.getmin2x(k); //double dl = (double)NNAnalysis.samplingRate / dx; double[] fftdata1 = new double[dx]; double[] fftdataimag1 = new double[dx]; Array.Copy(data1, begin1, fftdata1, 0, Math.Min(k, end1 - begin1)); TWFFT.FFT(fftdata1, fftdataimag1); double[] fftdata2 = new double[dx]; double[] fftdataimag2 = new double[dx]; Array.Copy(data2, begin2, fftdata2, 0, Math.Min(k, end2 - begin2)); TWFFT.FFT(fftdata2, fftdataimag2); int num = 15; double[] lineori1 = new double[dx]; double[] lineori2 = new double[dx]; for (int i = 0; i < dx; i++) { lineori1[i] = Math.Abs(fftdata1[i]); lineori2[i] = Math.Abs(fftdata2[i]); //lineori1[i] = Math.Sqrt(Math.Pow(fftdata1[i], 2) + Math.Pow(fftdataimag1[i], 2)); //lineori2[i] = Math.Sqrt(Math.Pow(fftdata2[i], 2) + Math.Pow(fftdataimag2[i], 2)); } double[] line1 = FToneAnalysis.MiddleFilter(lineori1, num); //double[] linei1 = FToneAnalysis.MiddleFilter(fftdataimag1, num); double[] line2 = FToneAnalysis.MiddleFilter(lineori2, num); //double[] linei2 = FToneAnalysis.MiddleFilter(fftdataimag2, num); for (int i = 0; i < line1.Length; i++) { //Complex c1 = new Complex(fftdata1[i], fftdataimag1[i]); //Complex cl1 = new Complex(line1[i], linei1[i]); //Complex cl2 = new Complex(line2[i], linei2[i]); //c1 = c1.Multiply(cl1.Division(cl2)); fftdata1[i] = (int)((double)fftdata1[i] * (line2[i] / line1[i])); //fftdataimag1[i] += (int)(linei2[i]-linei1[i]); } for (int i = dx / 4; i < dx / 2; i++) { if (line2[i] < line1[i]) { fftdata1[i] = fftdata2[i]; fftdata1[dx - i] = fftdata2[dx - i]; } } TWFFT.IFFT(fftdata1, fftdataimag1); for (int i = 0; i < res.Length; i++) { res[i] = (int)fftdata1[i]; } return(res); }
/// <summary> /// 用倒谱获得频谱包络 /// </summary> /// <param name="data"></param> /// <returns></returns> private static double[] GetEnvelopeFD(double[] data) { int n = data.Length; double[] data1 = new double[n]; double[] data1i = new double[n]; for (int i = 0; i < n; i++) { data1[i] = Math.Log(data[i]); } for (int i = 0; i < n; i++) { data1i[i] = 0; } TWFFT.FFT(data1, data1i); double therehold = 100; double[] data2 = new double[n]; double[] data2i = new double[n]; // 低通滤波 for (int i = 0; i < n; i++) { if (i < therehold || i > n - therehold) { data2[i] = data1[i]; data2i[i] = data1i[i]; } else { data2[i] = 0; data2i[i] = 0; } } //for (int i = 0; i < n; i++) data2i[i] = 0; TWFFT.IFFT(data2, data2i); var res = FToneAnalysis.MiddleFilter(data2, 5); for (int i = 0; i < n; i++) { res[i] = Math.Pow(Math.E, res[i]); } return(res); }
private static void repairWaveShape(int[] oridata, int[] tardata) { int n = FToneAnalysis.getmin2x(oridata.Length); double[] odata = new double[n]; double[] odatai = new double[n]; for (int i = 0; i < n; i++) { if (i < oridata.Length) { odata[i] = oridata[i]; } else { odata[i] = 0; } odatai[i] = 0; } TWFFT.FFT(odata, odatai); double[] odatamod = new double[n]; for (int i = 0; i < n; i++) { odatamod[i] = Math.Sqrt(odata[i] * odata[i] + odatai[i] * odatai[i]); } var odataenv = GetEnvelopeFD(odatamod); double[] tdata = new double[n]; double[] tdatai = new double[n]; for (int i = 0; i < n; i++) { if (i < tardata.Length) { tdata[i] = tardata[i]; } else { tdata[i] = 0; } tdatai[i] = 0; } TWFFT.FFT(tdata, tdatai); double[] tdatamod = new double[n]; for (int i = 0; i < n; i++) { tdatamod[i] = Math.Sqrt(tdata[i] * tdata[i] + tdatai[i] * tdatai[i]); } var tdataenv = GetEnvelopeFD(tdatamod); for (int i = 1; i < n / 2; i++) { //if (odataenv[i] >= tdataenv[i]) continue; tdata[i] = tdata[i] * (odataenv[i] / tdataenv[i]); tdatai[i] = tdatai[i] * (odataenv[i] / tdataenv[i]); tdata[n - i] = tdata[i]; tdatai[n - i] = tdatai[i]; } TWFFT.IFFT(tdata, tdatai); for (int i = 0; i < tardata.Length; i++) { tardata[i] = (int)tdata[i]; } }
private static int[] ChangePitResutltFD(int[] data, double dpit) { // 傅里叶点数必须2的倍数 int n = FToneAnalysis.getmin2x(data.Length * 2); n = 4096; double[] ddata = new double[n]; for (int i = 0; i < n; i++) { if (i < data.Length) { ddata[i] = data[i]; } else { ddata[i] = 0; } } double[] ddatai = new double[n]; for (int i = 0; i < n; i++) { ddatai[i] = 0; } TWFFT.FFT(ddata, ddatai); // ln(|X(n)|) double[] ddatalnmod = new double[n]; for (int i = 0; i < n; i++) { ddatalnmod[i] = Math.Sqrt(ddata[i] * ddata[i] + ddatai[i] * ddatai[i]); } // 根据倒谱获取频谱包络,即声道滤波器 var ddataenv = GetEnvelopeFD(ddatalnmod); // double[] ddataenv = new double[n]; //for (int i = 0; i < n; i++) ddataenv[i] = Math.Pow(Math.E, ddatalnenv[i]); // 除以包络,得到激励谱 double[] ddatabase = new double[n]; double[] ddataibase = new double[n]; for (int i = 0; i < n; i++) { ddatabase[i] = ddata[i]; /// ddataenv[i]; } for (int i = 0; i < n; i++) { ddataibase[i] = ddatai[i]; /// ddataenv[i]; } // 拉伸激励谱,得到新基频下的激励谱 double[] ddatabaser = new double[n]; double[] ddataibaser = new double[n]; // 对称共轭,所以分两半分别压缩 ddatabaser[0] = ddatabase[0]; ddataibaser[0] = ddataibase[0]; //dpit = 1.4; for (int i = 1; i < n / 2; i++) { int j = (int)(i - 3000 * (dpit - 1)); if (j < 1 || j >= n / 2) { ddatabaser[i] = 0; ddataibaser[i] = 0; } else { ddatabaser[i] = ddatabase[j]; ddataibaser[i] = ddataibase[j]; } ddatabaser[n - i] = ddatabaser[i]; ddataibaser[n - i] = -ddataibaser[i]; } //for(int i = 1; i <= n/2; i++) //{ // ddatabaser[i] = getResampleValue(ddatabase, (double)i / dpit); // ddatabaser[n - i] = ddatabaser[i]; // ddataibaser[i] = getResampleValue(ddataibase, (double)i / dpit); // ddataibaser[n - i] = -ddataibaser[i]; //} // 激励谱与包络相乘,重建频谱 double[] ddatar = new double[n]; double[] ddatair = new double[n]; for (int i = 0; i < n; i++) { ddatar[i] = ddatabaser[i]; //* ddataenv[i]; } for (int i = 0; i < n; i++) { ddatair[i] = ddataibaser[i]; //* ddataenv[i]; } TWFFT.IFFT(ddatar, ddatair); // int结果 int[] datar = new int[data.Length]; for (int i = 0; i < data.Length; i++) { datar[i] = (int)ddatar[i]; } return(datar); }