簡體   English   中英

C#頻率檢索

[英]C# Frequency Retrieval

我需要做的是計算麥克風輸入的頻率。 我為此使用IWaveProvider及其實現的Read() 緩沖區的大小始終為8820個元素,並且從字節數組到float數組的轉換似乎也出了問題( FloatBuffer屬性部分)。

以下是一些重要的方面...

這是我開始錄制的地方:

private void InitializeSoundRecording()
{
    WaveIn waveIn = new WaveIn();
    waveIn.DeviceNumber = 0;   
    waveIn.DataAvailable += (s, e) => this.waveIn_DataAvailable(s, e); 
    waveIn.RecordingStopped += (s, e) => this.waveIn_RecordingStopped(s, e);
    waveIn.WaveFormat = new WaveFormat(44100, 1);
    waveIn.StartRecording();
}

調用DataAvailable事件處理程序時,將執行以下操作:

private void waveIn_DataAvailable(object sender, WaveInEventArgs e)
{
    WaveBuffer wb = new WaveBuffer(e.Buffer.Length);

    IWaveProvider iWaveProvider = new PitchDetector(new WaveInProvider(sender as WaveIn), new WaveBuffer(e.Buffer));
    iWaveProvider.Read(wb, 0, e.Buffer.Length);

    PitchDetector pd = iWaveProvider as PitchDetector;

    this.ShowPitch(pd.Pitch);
}

最后,這是“實際”重要的一點:

private const int FLOAT_BUFFER_SIZE = 8820;
private IWaveProvider source;
private WaveBuffer waveBuffer;
private int sampleRate;
private float[] fftBuffer;
private float[] prevBuffer;
public float Pitch { get; private set; }

public WaveFormat WaveFormat { get { return this.source.WaveFormat; } }

internal PitchDetector(IWaveProvider waveProvider, WaveBuffer waveBuffer = null)
{
    this.source = waveProvider;
    this.sampleRate = waveProvider.WaveFormat.SampleRate;
    this.waveBuffer = waveBuffer;
}

/// <summary>
/// UNSAFE METHOD! 
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
private unsafe float[] ByteArrayToFloatArray(byte[] input)
{
    float[] fb = new float[FLOAT_BUFFER_SIZE];
    unsafe
    {
        fixed (byte* ptrBuffer = input)
        {
            float* ptrFloatBuffer = (float*)ptrBuffer;
            for (int i = 0; i < FLOAT_BUFFER_SIZE; i++)
            {
                fb[i] = *ptrFloatBuffer;
                ptrFloatBuffer++;
            }
        }
    }
    return fb;
}

public int Read(byte[] buffer, int offset = 0, int count = 0)
{
    if (this.waveBuffer == null || this.waveBuffer.MaxSize < count)
        this.waveBuffer = new WaveBuffer(count);

    int readBytes = this.source.Read(this.waveBuffer, 0, count);

    if (readBytes > 0) readBytes = count;

    int frames = readBytes / sizeof(float);

    this.Pitch = this.DeterminePitch(this.waveBuffer.FloatBuffer, frames);

    return frames * 4;
}

奇怪的是,當它進入構造函數時,waveBuffer包含一些數據(255、1、0等),但是當我檢查Read()的“ buffer”參數時,它完全為0。每個元素。

同樣出於好奇,為什么Read()有一個buffer參數,但實際上根本沒有在該方法中使用(我從您的一篇文章中得到了這段代碼)?

解決此問題的任何幫助將不勝感激! 我已經花了很長時間了,但是這毫無意義。

謝謝阿蘭

您所指的是什么文章尚不清楚,並且我對該庫不熟悉。 但是, Read方法顯然是在讀取“時間序列” /或其他數據。 由此看來,您所說的buffer參數可能是您要放置在數據集任一端的填充長度。

這種填充稱為“零填充”,它用零填充您記錄的信號(在信號的兩端放置n個零,其中n根據所用的基數設置)。 這允許使用更長的FFT,這將產生更長的FFT結果向量。

較長的FFT結果具有更多的頻率段,這些頻率段的頻率間隔更近。 但是,它們實際上將提供與原始數據較短的非零填充FFT的高質量Sinc插值相同的結果。

在不進行進一步插值的情況下繪制時,這可能會導致頻譜看起來更平滑。

如需進一步了解,請參閱

https://dsp.stackexchange.com/questions/741/why-should-i-zero-pad-a-signal-before-take-the-fourier-transform

我希望這有幫助。

這並不是您問題的真正答案,但我為數組轉換函數寫了一個safe通用替代方案。

using System;
using System.Runtime.InteropServices;

public static class Extensions
{
    public staitc TDestination[] Transform<TSource, TDestination>(
        this TSource[] source)
        where TSource : struct
        where TDestination : struct
    {
        if (source.Length == 0)
        {
            return new TDestination[0];
        }

        var sourceSize = Marshal.SizeOf(typeof(TSource));
        var destinationSize = Marshal.SizeOf(typeof(TDestination));

        var byteLength = source.Length * sourceSize;

        int remainder;
        var destinationLength = Math.DivRem(
            byteLength,
            destinationSize,
            out remainder);
        if (remainder > 0)
        {
            destinationLength++;
        }

        var destination = new TDestination[destinationLength];
        Buffer.BlockCopy(source, 0, destination, 0, byteLength);
        return destination;
    }
}

顯然,您可以使用

var bytes = new byte[] { 1, 1, 2, 3, 5, 8, 13, 21 };
var floats = bytes.Transform<byte, float>();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM