/// <summary> /// Time stretching with auto-derived parameters /// </summary> /// <param name="signal">Signal</param> /// <param name="stretch">Stretch factor (ratio)</param> /// <param name="algorithm">Algorithm for TSM (optional)</param> /// <returns>Time stretched signal</returns> public static DiscreteSignal TimeStretch(DiscreteSignal signal, double stretch, TsmAlgorithm algorithm = TsmAlgorithm.PhaseVocoderPhaseLocking) { if (Math.Abs(stretch - 1.0) < 1e-10) { return(signal.Copy()); } IFilter stretchFilter; var frameSize = MathUtils.NextPowerOfTwo(1024 * signal.SamplingRate / 16000); switch (algorithm) { case TsmAlgorithm.PhaseVocoder: stretchFilter = new PhaseVocoder(stretch, frameSize / 10, frameSize); break; case TsmAlgorithm.PhaseVocoderPhaseLocking: stretchFilter = new PhaseLockingVocoder(stretch, frameSize / 8, frameSize); break; case TsmAlgorithm.PaulStetch: stretchFilter = new PaulStretch(stretch, frameSize / 10, frameSize * 4); break; default: stretchFilter = new Wsola(stretch); break; } return(stretchFilter.ApplyTo(signal, FilteringMethod.Auto)); }
/// <summary> /// Time stretching /// </summary> /// <param name="signal">Signal</param> /// <param name="stretch">Stretch factor (scale)</param> /// <param name="fftSize">Size of FFT</param> /// <param name="hopSize">Hop size</param> /// <param name="algorithm">Algorithm for TSM</param> /// <returns></returns> public static DiscreteSignal TimeStretch(DiscreteSignal signal, double stretch, int fftSize = 1024, int hopSize = -1, TsmAlgorithm algorithm = TsmAlgorithm.Wsola) { if (Math.Abs(stretch - 1.0) < 1e-10) { return(signal.Copy()); } var hopAnalysis = hopSize > 0 ? hopSize : fftSize / 4; IFilter stretchFilter; switch (algorithm) { case TsmAlgorithm.PhaseVocoder: stretchFilter = new PhaseVocoder(stretch, hopAnalysis, fftSize); break; default: stretchFilter = new Wsola(stretch, fftSize); break; } return(stretchFilter.ApplyTo(signal, FilteringOptions.Auto)); }
/// <summary> /// Time stretching with parameters set by user /// </summary> /// <param name="signal">Signal</param> /// <param name="stretch">Stretch factor (ratio)</param> /// <param name="windowSize">Window size (for vocoders - FFT size)</param> /// <param name="hopSize">Hop size</param> /// <param name="algorithm">Algorithm for TSM (optional)</param> /// <returns>Time stretched signal</returns> public static DiscreteSignal TimeStretch(DiscreteSignal signal, double stretch, int windowSize, int hopSize, TsmAlgorithm algorithm = TsmAlgorithm.PhaseVocoderPhaseLocking) { if (Math.Abs(stretch - 1.0) < 1e-10) { return(signal.Copy()); } IFilter stretchFilter; switch (algorithm) { case TsmAlgorithm.PhaseVocoder: stretchFilter = new PhaseVocoder(stretch, hopSize, windowSize); break; case TsmAlgorithm.PhaseVocoderPhaseLocking: stretchFilter = new PhaseLockingVocoder(stretch, hopSize, windowSize); break; case TsmAlgorithm.PaulStetch: stretchFilter = new PaulStretch(stretch, hopSize, windowSize); break; default: stretchFilter = new Wsola(stretch, windowSize, hopSize); break; } return(stretchFilter.ApplyTo(signal, FilteringMethod.Auto)); }
/// <summary> /// Time stretching /// </summary> /// <param name="signal"></param> /// <param name="stretch"></param> /// <param name="fftSize"></param> /// <param name="hopSize"></param> /// <returns></returns> public static DiscreteSignal TimeStretch(DiscreteSignal signal, double stretch, int fftSize = 1024, int hopSize = -1) { if (Math.Abs(stretch - 1.0) < 1e-10) { return(signal.Copy()); } var hopAnalysis = hopSize > 0 ? hopSize : fftSize / 4; var hopSynthesis = (int)(hopAnalysis * stretch); var vocoder = new PhaseVocoder(hopAnalysis, hopSynthesis, fftSize); return(vocoder.ApplyTo(signal)); }