예제 #1
0
 public PhaseVocoder(int Pt, int Qt, int Pp, int Qp, bool robotoFX, int winLength)
 {
     this.Qt       = Qt;
     this.Pt       = Pt;
     this.Qp       = Qp;
     this.Pp       = Pp;
     this.robotoFX = robotoFX;
     tfr           = new TFR();
     stft          = new STFT(winLength);
     resampler     = new Resample.Resampler((uint)Qp, (uint)Pp);
 }
예제 #2
0
        /*
         * Pt/Qt = tempo change factor. A tempo change factor < 1 will lead to slower tempo. A tempo change factor > 1 will lead to faster tempo
         * Pp/Qp = pitch shift factor. A pitch shift factor < 1 will lead to reduced/lower pitch. A pitch shift factor > 1 will lead to increased/raised pitch.
         *
         */

        public PhaseVocoder(int Pt, int Qt, int Pp, int Qp)
        {
            this.Qt       = Qt;
            this.Pt       = Pt;
            this.Qp       = Qp;
            this.Pp       = Pp;
            this.robotoFX = false;
            tfr           = new TFR();
            stft          = new STFT(128);
            resampler     = new Resample.Resampler((uint)Qp, (uint)Pp);
        }
예제 #3
0
        public double[] apply(double[] input_signal)
        {
            tfr = stft.forward(input_signal);
            tfr.applyTempoChange((double)Pt / (double)Qt * (double)Qp / (double)Pp, false, this.robotoFX, ref fi, ref dfi); /* Tempo change step */
            double[] output_signal = stft.inverse(tfr);

            /* Pitch shift step. Apply function resample(Qp, Pp) on output_signal to change its sample rate by a factor Qp/Pp (multiplied by) */

            output_signal = resampler.Resample(output_signal);

            return(output_signal);
        }
예제 #4
0
        /* For real-time usage, ensure that the output blocks are continuous */
        public double[] applyContinuous(double[] input_signal, int Pt, int Qt, int Pp, int Qp, bool robotoFX)
        {
            List <double[]> frame = prepFrame(input_signal, prev_input_signal);

            for (int frameNum = 0; frameNum < frame.Count; frameNum++)
            {
                tfr = stft.forward(frame[frameNum]);
                tfr.applyTempoChange((double)Pt / (double)Qt * (double)Qp / (double)Pp, true, robotoFX, ref fi, ref dfi); /* Tempo change step */
                if (input_signal == null)
                {
                    frame[frameNum] = stft.inverse(tfr, ref prev_output_signal, true);
                }
                else
                {
                    frame[frameNum] = stft.inverse(tfr, ref prev_output_signal, false);
                }
            }

            /* Combine blocks to produce single output block */
            double[] output_signal;
            if (frame.Count == 1)
            {
                if (input_signal == null)
                {
                    output_signal = bondFrames(frame, FRAMETYPE.START);
                }
                else
                {
                    output_signal = bondFrames(frame, FRAMETYPE.END);
                }
            }
            else
            {
                output_signal = bondFrames(frame, FRAMETYPE.MID);
            }

            if (input_signal != null)
            {
                prev_input_signal = new double[input_signal.Length];
                for (int sample = 0; sample < input_signal.Length; sample++)
                {
                    prev_input_signal[sample] = input_signal[sample];
                }
            }

            /* Pitch shift step. Apply OUTPUT-BLOCK-CONTINUOUS function resampleContinuous(Qp, Pp) on output_signal to change its sample rate by a factor Qp/Pp (multiplied by) */
            output_signal = resampler.ResampleContinuous(output_signal);

            return(output_signal);
        }
예제 #5
0
        public double[] inverse(TFR tfr)
        {
            int nf = tfr.getTFRAsDoubleArray().Length - 1;
            int nw = tfr.getTFRAsDoubleArray()[0].Length;
            int ns = nf * hopSize + nw;

            double[] output = new double[ns];

            fftw_complexarray mdin  = new fftw_complexarray(nw);
            fftw_complexarray mdout = new fftw_complexarray(nw);
            fftw_plan         plan;

            int hopInd = 0;

            Complex[] buf = new Complex[nw];

            try
            {
                for (int hop = 0; hop <= nf * hopSize; hop += hopSize)
                {
                    mdout.SetData(buf);
                    mdin.SetData(tfr.getTFRAsDoubleArray()[hopInd++]);

                    plan = fftw_plan.dft_1d(winLength, mdin, mdout, fftw_direction.Backward, fftw_flags.Estimate);
                    plan.Execute();

                    buf = mdout.GetData_Complex();

                    for (int sample = 0; sample < nw; sample++)
                    {
                        output[sample + hop] = output[sample + hop] + (buf[sample].Real / nw) * win[sample].Real;
                    }
                }

                return(output);
            }
            catch (Exception)
            {
                return(output);
            }
        }
예제 #6
0
        public double[] inverse(TFR tfr, ref double[] output_signal_prev, bool last)
        {
            int nf = tfr.getTFRAsDoubleArray().Length - 1;
            int nw = tfr.getTFRAsDoubleArray()[0].Length;
            int ns = nf * hopSize + nw;

            double[] output_signal_tmp = new double[ns];
            double[] output_signal     = new double[output_signal_tmp.Length - 3 * hopSize];

            fftw_complexarray mdin  = new fftw_complexarray(nw);
            fftw_complexarray mdout = new fftw_complexarray(nw);
            fftw_plan         plan;

            if (output_signal_prev == null)
            {
                output_signal_prev = new double[3 * hopSize];
            }
            for (int sample = 0; sample < hopSize * 3; sample++)
            {
                output_signal_tmp[sample] = output_signal_prev[sample];
            }

            int hopInd = 0;

            Complex[] buf = new Complex[nw];

            try
            {
                for (int hop = 0; hop <= nf * hopSize; hop += hopSize)
                {
                    mdout.SetData(buf);
                    mdin.SetData(tfr.getTFRAsDoubleArray()[hopInd++]);

                    plan = fftw_plan.dft_1d(winLength, mdin, mdout, fftw_direction.Backward, fftw_flags.Estimate);
                    plan.Execute();

                    buf = mdout.GetData_Complex();

                    for (int sample = 0; sample < nw; sample++)
                    {
                        output_signal_tmp[sample + hop] = output_signal_tmp[sample + hop] + (buf[sample].Real / nw) * win[sample].Real;
                    }
                }

                for (int sample = 0; sample < hopSize * 3; sample++)
                {
                    output_signal_prev[sample] = output_signal_tmp[output_signal_tmp.Length - hopSize * 3 + sample];
                }

                for (int sample = 0; sample < output_signal.Length; sample++)
                {
                    output_signal[sample] = output_signal_tmp[sample];
                }

                if (last)
                {
                    return(output_signal_tmp);
                }
                else
                {
                    return(output_signal);
                }
            }
            catch (Exception)
            {
                if (last)
                {
                    return(output_signal_tmp);
                }
                else
                {
                    return(output_signal);
                }
            }
        }