private static int[] getChangeSoundFDPSOLA(int[] oridata, double[][] zip, int tarlength) { int[] oricut = FToneAnalysis.cutIt(oridata); int[] resdata = new int[tarlength]; int orilength = oridata.Length; int[][] rescut = getCutPair(oricut, orilength, tarlength); int overlaplen = 0; for (int i = 0; i < rescut.Length; i++) { int oristart = rescut[i][0]; int tarstart = rescut[i][1]; int orilen = rescut[i][2]; int[] pitcdata = new int[orilen + overlaplen * 2]; double pitc = getZipValue(zip, (double)i * zip.Length / rescut.Length); for (int j = 0; j < pitcdata.Length; j++) { int p = oristart + j - overlaplen; if (p < 0 || p >= oridata.Length) { pitcdata[j] = 0; } else { pitcdata[j] = oridata[p]; } } pitcdata = ChangePitResutltFD(pitcdata, pitc); for (int j = 0; j < orilen; j++) { int p = tarstart + j - overlaplen; if (j < overlaplen && i != 0) { resdata[p] = (int)(resdata[p] * (1 - (double)j / overlaplen) + pitcdata[j] * (double)j / overlaplen); } else if (p >= 0 && p < resdata.Length) { resdata[p] = pitcdata[j]; } } } return(resdata); }
private static int[] getChangeSoundUTAU(int[] oridata, double[][] zip, int tarlength) { int[] oricut = FToneAnalysis.cutIt(oridata); int[] resdata = new int[tarlength]; int orilength = oridata.Length; int[][] rescut = getCutPair(oricut, orilength, tarlength, zip); int overlaplen = 0; double k = (double)tarlength / orilength; for (int i = 0; i < rescut.Length; i++) { int oristart = rescut[i][0]; int tarstart = rescut[i][1]; int orilen = rescut[i][2]; int[] pitcdata = new int[orilen + overlaplen * 2]; int laplen = orilen * 2; int orilapstart = oristart - laplen / 2; int tarlapstart = tarstart - laplen / 2; int[] oriframe = new int[laplen]; for (int j = 0; j < laplen; j++) { if (orilapstart + j < 0 || orilapstart + j >= orilength) { oriframe[j] = 0; } else { oriframe[j] = oridata[orilapstart + j]; } } var oriframeh = Hanning(oriframe); for (int j = 0; j < laplen; j++) { if (tarlapstart + j < 0 || tarlapstart + j >= tarlength) { continue; } else { resdata[tarlapstart + j] += oriframeh[j]; } } } //int framelen = 4096; //for(int i = 0; i < tarlength; i += framelen) //{ // int[] od = new int[framelen]; // int[] td = new int[framelen]; // for(int j = 0; j < framelen; j++) // { // int d = (int)(i * k) + j; // if (d >= oridata.Length) d = oridata.Length - framelen - 1 + j; // od[j] = oridata[d]; // td[j] = resdata[i + j]; // } //} return(resdata); }
/// <summary> /// TD-PSOLA法合成 /// </summary> /// <param name="oridata"></param> /// <param name="zip"></param> /// <param name="tarlength"></param> /// <returns></returns> private static int[] getChangeSoundTDPSOLA(int[] oridata, double[][] zip, int tarlength) { int[] oricut = FToneAnalysis.cutIt(oridata); int[] resdata = new int[tarlength]; int orilength = oridata.Length; int[][] rescut = getCutPair(oricut, orilength, tarlength, zip); //int overlaplen = 20; double k = (double)tarlength / orilength; for (int i = 0; i < rescut.Length; i++) { int oristart = rescut[i][0]; int tarstart = rescut[i][1]; int orilen = rescut[i][2]; int laplen = orilen * 2; int orilapstart = oristart - laplen / 2; int tarlapstart = tarstart - laplen / 2; int[] oriframe = new int[laplen]; for (int j = 0; j < laplen; j++) { if (orilapstart + j < 0 || orilapstart + j >= orilength) { oriframe[j] = 0; } else { oriframe[j] = oridata[orilapstart + j]; } } var oriframeh = Hanning(oriframe); for (int j = 0; j < laplen; j++) { if (tarlapstart + j < 0 || tarlapstart + j >= tarlength) { continue; } else { resdata[tarlapstart + j] += oriframeh[j]; } } } int[] resdata2 = new int[tarlength]; for (int i = 0; i < tarlength; i++) { resdata2[i] = 0; } int framelen = 1024; for (int i = 0; i < tarlength; i += framelen / 2) { int[] od = new int[framelen]; int[] td = new int[framelen]; for (int j = 0; j < framelen; j++) { int d = (int)((double)i * orilength / tarlength) + j; if (d >= oridata.Length) { d = oridata.Length - framelen - 1 + j; } if (i + j >= tarlength) { td[j] = 0; continue; } od[j] = oridata[d]; td[j] = resdata[i + j]; } //od = Hanning(od); //td = Hanning(td); repairWaveShape(od, td); //td = antiHanning(td); for (int j = 0; j < framelen; j++) { int d = i + j; if (d >= tarlength) { break; } if (j < framelen / 2) { resdata2[d] = (int)(resdata2[d] * (1 - (double)j * 2 / framelen) + td[j] * ((double)j * 2 / framelen)); } else { resdata2[d] += td[j]; } } } return(resdata); //int framenum = cut.Length-1; //// 获取逐帧频率压缩因子,用于接下来获取指定位置的压缩因子 //double[] framezip = getZipPoint(oridata.Length, zip); //int[] res = new int[length]; ////将开头段先放进去再说 ////Array.Copy(oridata, 0, res, 0, Math.Min(length, cut[1])); //int fbegin = cut[0]; //int fend = cut[1]; //double nowpos = 0; //int respos = 0; ////对小段重采样 //int i = 1; //while (i < framenum) //{ // fbegin = cut[i - 1]; // fend = cut[i]; // int thislen = fend - fbegin; // fbegin -= thislen / 2; // fend += thislen / 2; // double nowzip = 1 / Math.Max(framezip[Math.Max(fbegin, 0)], 0.1); // //reset nowpos // nowpos = fbegin; // List<int> tmp = new List<int>(); // while (nowpos < fend) // { // int val = getResampleValue(oridata, nowpos); // tmp.Add(val); // nowpos += nowzip; // } // // 滤波 // int[] tmp2 = MiddleFilterCorrection( tmp.ToArray(), 0, tmp.Count, oridata, Math.Max(0,fbegin), fend); // //tmp2 = FToneAnalysis.FrequencyFilter(tmp2, 0, 15000); // // 用汉宁窗合并 // //var hanningtmp = tmp.ToArray(); // var hanningtmp = hanning(tmp2.ToArray()); // for (int j = 0; j < hanningtmp.Length; j++) // { // if (respos + j - cut[i - 1] + fbegin >= res.Length) // { // break; // } // else if (respos+j - cut[i - 1] + fbegin >= 0) // { // res[respos + j - cut[i - 1] + fbegin] += hanningtmp[j]; // //respos++; // } // } // // 做中值平滑 // int width = thislen/2; // int phstart = Math.Max(0, respos - width); // int phlen = Math.Min(res.Length - phstart, width * 2); // int[] phdata = new int[phlen]; // Array.Copy(res, phstart, phdata, 0, phlen); // phdata = FToneAnalysis.MiddleFilter(phdata, 3); // //phdata = FToneAnalysis.MiddleFilter(phdata, 5); // Array.Copy(phdata, 0, res, phstart, phlen); // respos += hanningtmp.Length / 2; // i = getNearestFrameIndex(oridata.Length, length, cut, respos); //} //return res; }
private static int[] getChangeSoundOld(int[] oridata, double[] pit, int length) { int[] res = new int[length]; int[] frame = FToneAnalysis.cutIt(oridata); var zips = getZipPoint(length, pit); //for (int i = 0; i < frame.Length; i++) frame[i] += cutbegin; if (frame.Length == 0 || length < (int)(frame[0] * zips[0])) { // 目标长度小于第一个基音的长度,就不再合成,直接截断当作输出 double j = 0; for (int i = 0; i < length; i++) { res[i] = oridata[(int)j]; j += zips[0]; } } else { //步长缩放因子 double scale = (double)oridata.Length / length; int nowloc = 0; while (nowloc < length) { int tmpnow = (int)(nowloc * scale); int nextframe = getCRFrame(frame, tmpnow); int framelen = getFrameLength(frame, nextframe); if (nowloc > length - (oridata.Length - frame[frame.Length - 1]) / zips[nowloc]) { //use the final frame (tail) double j = 0; double oldj = 0; int stilltime = 1; int stilltimenow = stilltime; double olddelta = 1; for (int i = 0; i < oridata.Length - frame[frame.Length - 1]; i++) { if (nowloc + (int)j >= length || frame[frame.Length - 1] + i >= oridata.Length) { break; } else { //interpolation for (int s = (int)oldj; s < (int)j; s++) { if (nowloc + (int)s >= res.Length) { continue; } res[nowloc + (int)s] = oridata[frame[nextframe] - framelen + i]; } double delta = 1 / zips[nowloc + (int)j]; if (delta > 100) { delta = 100; } oldj = j; if (stilltimenow++ >= stilltime) { olddelta = delta; stilltimenow = 0; } j += olddelta; } } break; } else { //copy this frame double j = 0; double oldj = 0; int stilltime = 1; int stilltimenow = stilltime; double olddelta = 1; for (int i = 0; i < framelen; i++) { //interpolation for (int s = (int)oldj; s < (int)j; s++) { if (nowloc + (int)s >= res.Length) { break; } res[nowloc + (int)s] = oridata[Math.Min(oridata.Length - 1, frame[nextframe] - framelen + i)]; } if (nowloc + (int)j >= zips.Length) { continue; } double delta = 1 / zips[nowloc + (int)j]; if (delta > 100) { delta = 100; } oldj = j; if (stilltimenow++ >= stilltime) { olddelta = delta; stilltimenow = 0; } j += olddelta; } nowloc += (int)oldj; } } } ////全局整形 //int[] newres = new int[res.Length]; //int dx = 1024; //int nowx1 = 0; //int nowx2 = 0; //while (nowx1 < oridata.Length) //{ // double[] data1 = new double[dx]; // double[] data2 = new double[dx]; // double[] dataimag1 = new double[dx]; // for (int i = 0; i < dx; i++) dataimag1[i] = 0; // double[] dataimag2 = new double[dx]; // for (int i = 0; i < dx; i++) dataimag2[i] = 0; // for (int i = 0; i < dx; i++) // { // data1[i] = nowx1 + i < oridata.Length ? oridata[nowx1 + i] : 0; // data2[i] = nowx2 + i < res.Length ? (double)res[nowx2 + i] : 0; // } // TWFFT.FFT(data1, dataimag1); // TWFFT.FFT(data2, dataimag2); // double[] data1t = new double[dx]; // double[] data2t = new double[dx]; // for (int i = 0; i < dx; i++) data1t[i] = Math.Sqrt(data1[i] * data1[i] + dataimag1[i] * dataimag1[i]); // for (int i = 0; i < dx; i++) data2t[i] = Math.Sqrt(data2[i] * data2[i] + dataimag2[i] * dataimag2[i]); // int[,] envori = FormantAnalysis.getEnvelope3(data1t); // int[,] env = FormantAnalysis.getEnvelope3(data2t); // double[] envdelta = new double[env.GetLength(0)]; // //整形 // for (int i = 0; i < envdelta.Length; i++) // { // if (env[i, 1] == 0) envdelta[i] = 0; // else envdelta[i] = (double)envori[i, 1] / env[i, 1]; // } // for (int i = 1; i < envdelta.Length; i++) // { // for (int j = env[i - 1, 0]; j < env[i, 0]; j++) // { // data2[j] *= envdelta[i]; // dataimag2[j] *= envdelta[i]; // } // } // ////高通滤波 // //for (int i = 0; i < dx; i++) // //{ // // if (data1t[i] < 1000) // // { // // data2[i] = data1[i]; // // dataimag2[i] = dataimag1[i]; // // } // //} //for (int i = (int)(dx/2 * rbegin); i < (int)(dx/2 * rend); i++) //{ // data2[i] = 0; // dataimag2[i] = 0; //} //for (int i = (int)(dx - dx / 2 * rbegin)-1; i >= (int)(dx - dx / 2 * rend); i--) //{ // data2[i] = 0; // dataimag2[i] = 0; //} // TWFFT.IFFT(data2, dataimag2); // for (int i = 0; i < dx; i++) // if (nowx2 + i < res.Length) // newres[nowx2 + i] += (int)((double)data2[i] * (i < dx / 2 ? (double)i * 2.0 / dx : 2.0 - (double)(i) * 2.0 / dx)); // //newres[nowx2 + i] += (int)((double)data2[i] * Math.Sin(Math.PI * ((double)i / dx))); // nowx2 += dx / 2; // nowx1 += (int)((double)dx / 2 * oridata.Length / res.Length); //} //Array.Copy(newres, res, res.Length); ////填充空白 //for (int m = 0; m < 2; m++) //{ // int t = 1 + m; // for (int i = t; i < newlen - t; i++) // { // if (Math.Abs(res[i - t] * res[i + t]) > 100000 && res[i] < 20000) // { // res[i] = (res[i - t] + res[i + t]) / 2; // } // } //} //收尾 double percent = 0.1; int num = (int)(length * percent); //double scale = 1 / num; for (int i = length - num; i < length; i++) { res[i] = (int)(res[i] * (double)(length - i) / num); } //for (int i = 0; i < newlen; i++) //{ // if (Math.Abs(res[i]) <= 0) // { // res[i] = 0; // } //} return(res); }