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);
        }