0
votes

I am currently creating a Winforms application for Windows 8.1, I have been able to perform an FFT on the input data from the devices microphone using ASIO Out, however to be able to use ASIO on my machine I needed to download ASIO4ALL,

This is causing a huge amount of feedback in the microphone and is resulting in very inaccurate frequency readings (to make sure it was the sound itself I wrote a copy to disc to playback),

So to get around this I have been trying to adapt my code to work with Naudio's WaveIn class, however this is returning either no data or NaN for the FFT algorithm (although I can save a recording to disk which plays back with no issues),

I've been trying to fix this for some time now and am sure it is just a silly mistake somewhere, any help would be greatly appreciated!

Below is the code for the "OnDataAvailable" event (where I'm 99% sure I am going wrong):

 void OnDataAvailable(object sender, WaveInEventArgs e)
    {
        if (this.InvokeRequired)
        {
            this.BeginInvoke(new EventHandler<WaveInEventArgs>(OnDataAvailable), sender, e);
        }
        else
        {
            byte[] buffer = e.Buffer;
            int bytesRecorded = e.BytesRecorded;
            int bufferIncrement = waveIn.WaveFormat.BlockAlign;

            for (int index = 0; index < bytesRecorded; index += bufferIncrement)
            {
                float sample32 = BitConverter.ToSingle(buffer, index);
                sampleAggregator.Add(sample32);
            }

            if (waveFile != null)
            {
            waveFile.Write(e.Buffer, 0, e.BytesRecorded);
            waveFile.Flush();
            }

        }


    }

If any more details and/or code is required please let me know.

waveFile: Name of the file writer

e.Buffer: The buffer containing the recorded data

e.BytesRecorded: The total number of bytes recorded

For reference below is the working code when using the ASIO class:

  void asio_DataAvailable(object sender, AsioAudioAvailableEventArgs e)
    {
        byte[] buf = new byte[e.SamplesPerBuffer * 4];

        for (int i = 0; i < e.InputBuffers.Length; i++)
        {
            Marshal.Copy(e.InputBuffers[i], buf, 0, e.SamplesPerBuffer * 4);     
        }

        for (int i = 0; i < e.SamplesPerBuffer * 4; i++)
        {
            float sample32 = Convert.ToSingle(buf[i]);
            sampleAggregator.Add(sample32);
        }
    }

EDIT: The samples which are being returned are now accurate after changing the convert statement to Int16 as per the advice on this page, I had some other issues in my code which prevented actual results from being returned originally.

However, the file which is being written to disk is very choppy, I'm sure this is a problem with my laptop and the number of processes which is trying to perform, could anyone please advise a way around this issue?

2
BitConverter.ToSingle(buffer, index) - are you sure that your buffer contains Float32 samples? (not Int16 or Int32)Serge Semenov
If your buffer does indeed contain float samples, it's also possible that the sampleAggregator you are using is problematic. In the later case you could try this answer.SleuthEye
The buffer returns an array of bytes, although I didn't have an issue with this when using ASIO, also the sample provided by @SleuthEye is the code I based mine on :)JBrian30221

2 Answers

0
votes

In the NAudio WPF demo project there is an example of calculating FFTs while playback is happening with a class called SampleAggregator, that stores up blocks of 1024 samples and then performs FFTs on them.

It looks like you are trying to do something similar to this. I suspect the problem is that you are getting 16 bit samples, not 32 bit. Try using BitConverter.ToShort on every pair of bytes.

0
votes
mWaveInDevice = new WaveIn();
mWaveInDevice.WaveFormat = WaveFormat.**CreateIeeeFloatWaveFormat(44100,2)**;

Set CreateIeeeFloatWaveFormat for WaveFormat, and then you will get right values after fft.