public float DetectPitch(float[] buffer, int inFrames) { Func <int, int, float> window = HammingWindow; if (prevBuffer == null) { prevBuffer = new float[inFrames]; } // double frames since we are combining present and previous buffers int frames = inFrames * 2; if (fftBuffer == null) { fftBuffer = new float[frames * 2]; // times 2 because it is complex input } for (int n = 0; n < frames; n++) { if (n < inFrames) { fftBuffer[n * 2] = prevBuffer[n] * window(n, frames); fftBuffer[n * 2 + 1] = 0; // need to clear out as fft modifies buffer } else { fftBuffer[n * 2] = buffer[n - inFrames] * window(n, frames); fftBuffer[n * 2 + 1] = 0; // need to clear out as fft modifies buffer } } // assuming frames is a power of 2 SmbPitchShift.smbFft(fftBuffer, frames, -1); float binSize = sampleRate / frames; int minBin = (int)(85 / binSize); int maxBin = (int)(300 / binSize); float maxIntensity = 0f; int maxBinIndex = 0; for (int bin = minBin; bin <= maxBin; bin++) { float real = fftBuffer[bin * 2]; float imaginary = fftBuffer[bin * 2 + 1]; float intensity = real * real + imaginary * imaginary; if (intensity > maxIntensity) { maxIntensity = intensity; maxBinIndex = bin; } } return(binSize * maxBinIndex); }
public void ShiftPitch(float[] inputBuff, float inputPitch, float targetPitch, float[] outputBuff, int nFrames) { UpdateSettings(); detectedPitch = inputPitch; float shiftFactor = 1.0f; if (this.settings.SnapMode) { if (inputPitch > 0) { shiftFactor = snapFactor(inputPitch); shiftFactor += addVibrato(nFrames); } } else { float midiPitch = targetPitch; shiftFactor = 1.0f; if (inputPitch > 0 && midiPitch > 0) { shiftFactor = midiPitch / inputPitch; } } if (shiftFactor > 2.0) { shiftFactor = 2.0f; } if (shiftFactor < 0.5) { shiftFactor = 0.5f; } // fftFrameSize was nFrames but can't guarantee it is a power of 2 // 2048 works, let's try 1024 int fftFrameSize = 2048; int osamp = 8; // 32 is best quality SmbPitchShift.smbPitchShift(shiftFactor, nFrames, fftFrameSize, osamp, this.sampleRate, inputBuff, outputBuff); //vibrato //addVibrato(outputBuff, nFrames); shiftedPitch = inputPitch * shiftFactor; updateShifts(detectedPitch, shiftedPitch, this.currPitch); }