private static Bin[] PitchShiftBins(float pitchShift, Bin[] bins) { return bins.Select(x => new Bin(x.Frequency*pitchShift, x.Magnitude)).ToArray(); //var shiftedBins = new Bin[bins.Length]; //for (var i = 0; i < shiftedBins.Length; i++) //{ // shiftedBins[i] = new Bin(0f, 0f); //} //for (var i = 0; i < bins.Length; i++) //{ // var index = (int)(i * pitchShift); // if (index < bins.Length) // { // shiftedBins[i].Magnitude = bins[i].Magnitude; // shiftedBins[i].Frequency = bins[i].Frequency * pitchShift; // } //} //return shiftedBins; }
private static Complex[] SynthesizeFft(float sampleRate, Bin[] bins) { const float expectedPhaseDifference = (float) (2*Math.PI); var fftBuffer = new Complex[bins.Length * 2]; var frequencyPerBin = (sampleRate / (float)fftBuffer.Length); var phase = 0f; for (var i = 0; i < bins.Length; i++) { var tmp = bins[i].Frequency; tmp -= i*frequencyPerBin; tmp /= frequencyPerBin; tmp *= (float) (2*Math.PI); tmp += i*expectedPhaseDifference; phase += tmp; var real = (float)(bins[i].Magnitude * Math.Cos(phase)); var imaginary = (float)(bins[i].Magnitude * Math.Sin(phase)); fftBuffer[i] = new Complex(real, imaginary); } for (var i = bins.Length; i < fftBuffer.Length; i++) { fftBuffer[i] = new Complex(0f, 0f); } return fftBuffer; }
private static Bin[] CalculateBins(int sampleRate, IList<Complex> fftBuffer) { const float expectedPhaseDifference = (float) (2*Math.PI); var frequencyPerBin = sampleRate / (float) fftBuffer.Count; var lastPhase = 0f; var bins = new Bin[fftBuffer.Count / 2]; for (var i = 0; i < bins.Length; i++) { var magnitude = CalculateMagnitude(fftBuffer[i]); var phase = CalculatePhase(fftBuffer[i]); var tmp = phase - lastPhase; lastPhase = phase; tmp -= i*expectedPhaseDifference; var qpd = (long) (tmp/Math.PI); if (qpd >= 0) qpd += qpd & 1; else qpd -= qpd & 1; tmp -= (float) (Math.PI*qpd); tmp /= expectedPhaseDifference; tmp = i*frequencyPerBin + tmp*frequencyPerBin; bins[i] = new Bin(tmp, magnitude); } return bins; }