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);
        }
Example #2
0
        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);
        }