Oups I've accidentally erased this post while updating the code.

`using ManagedBass;`

// ReSharper disable LocalizableElement

namespace HanumanInstitute.BassAudio;

public class PitchDetector : IPitchDetector

{

private readonly IFileSystemService _fileSystem;

public PitchDetector(IFileSystemService fileSystem)

{

_fileSystem = fileSystem;

}

public async Task<float> GetPitchAsync(string filePath) =>

await Task.Run(() => GetPitch(filePath), default).ConfigureAwait(false);

public float GetPitch(string filePath)

{

if (!_fileSystem.File.Exists(filePath))

{

throw new FileNotFoundException("Source audio file was not found.", filePath);

}

BassDevice.Instance.Init();

var chan = Bass.CreateStream(filePath, Flags: BassFlags.Float | BassFlags.Decode).Valid();

try

{

var chanInfo = Bass.ChannelGetInfo(chan);

var fft = new float[(int)32768 / 2];

var fftBuffer = new float[fft.Length];

var freqStep = (float)chanInfo.Frequency / fft.Length;

var read = 0;

var readTotal = 0;

var maxRead = (int)Bass.ChannelSeconds2Bytes(chan, 100);

do

{

read = Bass.ChannelGetData(chan, fftBuffer, (int)DataFlags.FFT32768);

if (read > 0)

{

readTotal += read;

for (var i = 0; i < fft.Length; i++)

{

fft[i] += fftBuffer[i];

}

}

}

while (read > 0 && readTotal < maxRead);

// var toneFreq = new[]{16.35f,17.32f,18.35f,19.45f,20.6f,21.83f,23.12f,24.5f,25.96f,27.5f,29.14f,30.87f,32.7f,34.65f,36.71f,38.89f,41.2f,43.65f,46.25f,49f,51.91f,55f,58.27f,61.74f,65.41f,69.3f,73.42f,77.78f,82.41f,87.31f,92.5f,98f,103.83f,110f,116.54f,123.47f,130.81f,138.59f,146.83f,155.56f,164.81f,174.61f,185f,196f,207.65f,220f,233.08f,246.94f,261.63f,277.18f,293.66f,311.13f,329.63f,349.23f,369.99f,392f,415.3f,440f,466.16f,493.88f,523.25f,554.37f,587.33f,622.25f,659.25f,698.46f,739.99f,783.99f,830.61f,880f,932.33f,987.77f,1046.5f,1108.73f,1174.66f,1244.51f,1318.51f,1396.91f,1479.98f,1567.98f,1661.22f,1760f,1864.66f,1975.53f,2093f,2217.46f,2349.32f,2489.02f,2637.02f,2793.83f,2959.96f,3135.96f,3322.44f,3520f,3729.31f,3951.07f,4186.01f,4434.92f,4698.63f,4978.03f,5274.04f,5587.65f,5919.91f,6271.93f,6644.88f,7040f,7458.62f,7902.13f};

var toneFreq = new float[60];

for (var i = 0; i < 60; i++)

{

toneFreq[i] = GetFrequency(i + 20);

}

// Find the tuning frequency

var maxSum = 0.0f;

var maxFreq = 0.0f;

for (var i = 424.0f; i < 448.1f; i += 0.1f)

{

var sum = 0.0f;

var tones = Array.ConvertAll(toneFreq, x => x * i / 440f);

var lastFreq = 0f;

foreach (var freq in tones)

{

if (lastFreq > 0)

{

var index = (int)(freq / freqStep);

var factor = (freq - lastFreq) / freqStep;

sum += fft[index] * factor;

}

lastFreq = freq;

}

if (sum > maxSum)

{

maxSum = sum;

maxFreq = i;

}

}

return maxFreq;

}

finally

{

Bass.StreamFree(chan);

}

}

private float GetFrequency(int keyIndex) => (float)Math.Pow(2, (keyIndex - 49) / 12.0) * 440;

}