更新 #2:
私はコードをいじり続けました.私の唯一の問題は、マイクを通して音が存在するときに周波数を検出していることですが、アルゴリズムはまったく機能していません. 500Hz を要求すると、その周波数で音がまったくないタフな出力レベルでも出力されます。以下のコード (この記事はあまり注目されていないことがわかったので、定期的に更新しています)
private void button3_Click(object sender, EventArgs e)
{
waveIn = new WasapiLoopbackCapture();
waveIn.DataAvailable += OnDtAvailable;
waveIn.StartRecording();
}
void OnDtAvailable(object sender, WaveInEventArgs e)
{
byte[] buffer = e.Buffer;
int bytesRecorded = e.BytesRecorded;
int bufferIncrement = waveIn.WaveFormat.BlockAlign;
for (int index = 0; index < bytesRecorded; index += bufferIncrement)
{
float[] samples = new float[buffer.Length];
Buffer.BlockCopy(buffer, index, samples, 0, bufferIncrement);
double d1 = CalculateGoertzel(samples, 1336, 44100);
double c2 = CalculateGoertzel(samples, 770, 48000);
Console.WriteLine(index + ": Frequency 1336Hz - " + d1 + " Frequency 770Hz - " + c2);
}
}
private static double CalculateGoertzel(float[] samples, double frequency, int sampleRate)
{
var normalizedFrequency = Math.Round(frequency * samples.Length / sampleRate);
var w = (2.0 * Math.PI / samples.Length) * normalizedFrequency;
var cosine = Math.Cos(w);
var sine = Math.Sin(w);
var coeff = 2.0 * cosine;
var q0 = 0.0;
var q1 = 0.0;
var q2 = 0.0;
foreach (var sample in samples)
{
q0 = coeff * q1 - q2 + sample;
q2 = q1;
q1 = q0;
}
return Math.Sqrt(q1 * q1 + q2 * q2 - q1 * q2 * coeff);
}
更新 #1:
私はコードをいじっていて、最終的にエラーなしで動作するものを手に入れることができましたが、それは非常に不正確です.誰かがそれを行うためのより良い方法を教えてもらえますか(「動作」バージョンのコードは以下にあります)?
private void button3_Click(object sender, EventArgs e)
{
waveIn = new WasapiLoopbackCapture();
waveIn.DataAvailable += OnDataAvailable;
waveIn.StartRecording();
}
void OnDataAvailable(object sender, WaveInEventArgs e)
{
byte[] buffer = e.Buffer;
if ((CalculateGoertzel(buffer, 1633.0, 48000) > 84) && (CalculateGoertzel(buffer, 697.0, 48000) > 84))
{
DateTime dt = DateTime.Now;
Console.WriteLine(dt.ToString("mm:ss:fff - ") + "a");
}
}
public static double CalculateGoertzel(byte[] sample, double frequency, int samplerate)
{
double Skn, Skn1, Skn2;
Skn = Skn1 = Skn2 = 0;
for (int i = 0; i < sample.Length; i++)
{
Skn2 = Skn1;
Skn1 = Skn;
Skn = 2 * Math.Cos(2 * Math.PI * frequency / samplerate) * Skn1 - Skn2 + sample[i];
}
double WNk = Math.Exp(-2 * Math.PI * frequency / samplerate);
return 20 * Math.Log10(Math.Abs((Skn - WNk * Skn1)));
}
私は、マイクを介してコンピューターで再生されている周波数パワーを取得できるソリューションを作成しようとしています (私のプロジェクトでは複数の周波数も計画しているため、これは DTMF に似ています)。
以下に、エラーメッセージを表示しているこれを試しているコードを示します。
オフセットと長さが配列の範囲外であるか、カウントがインデックスからソース コレクションの末尾までの要素数を超えています。
範囲外のエラーが発生する理由を理解できないようです-おそらく、私はDSPとNAudioに非常に慣れていないためです(私は何時間も試しました-グーグルを試し、他のstackoverflowの投稿を検索しました.少し助けになったものを見つけて、それが私が今いる場所にたどり着いた方法です)。
Audacity の WASPI 再生オプションからデフォルトのマイクで再生している 525Hz 50 秒のトーン ファイルをダウンロードするには、ここをクリックしてください。
これを機能させるための助けがあれば大歓迎です。
public static double CalculateGoertzel(short[] sample, double frequency, int samplerate)
{
double Skn, Skn1, Skn2;
Skn = Skn1 = Skn2 = 0;
for (int i = 0; i < sample.Length; i++)
{
Skn2 = Skn1;
Skn1 = Skn;
Skn = 2 * Math.Cos(2 * Math.PI * frequency / samplerate) * Skn1 - Skn2 + sample[i];
}
double WNk = Math.Exp(-2 * Math.PI * frequency / samplerate);
return 20 * Math.Log10(Math.Abs((Skn - WNk * Skn1)));
}
private void button3_Click(object sender, EventArgs e)
{
waveIn = new WasapiLoopbackCapture();
waveIn.DataAvailable += OnDtAvailable;
waveIn.StartRecording();
}
void OnDtAvailable(object sender, WaveInEventArgs e)
{
byte[] buffer = e.Buffer;
int bytesRecorded = e.BytesRecorded;
int bufferIncrement = waveIn.WaveFormat.BlockAlign;
for (int index = 0; index < bytesRecorded; index += bufferIncrement)
{
short[] sampleBuffer = new short[buffer.Length];
Buffer.BlockCopy(buffer, index, sampleBuffer, 0, bytesRecorded);
Console.WriteLine(CalculateGoertzel(sampleBuffer, 525, 48000));
}
}