Not signed in (Sign In)

Categories

Welcome, Guest

Want to take part in these discussions? Sign in if you have an account, or apply for one below

Vanilla 1.1.4 is a product of Lussumo. More Information: Documentation, Community Support.

Welcome Guest!
Want to take part in these discussions? If you have an account, sign in now.
If you don't have an account, apply for one now.
    • CommentAuthormlew
    • CommentTimeJun 14th 2010
     
    I'm working on a filtering application using microphone input through DirectSound. Whenever I run the ILMath.fft function on my array of data from the microphone, I get an array of junk data (NaN + NaNi). I've already tried replacing any NaN values in the input data with 0's, and that hasn't worked. Any ideas why this is happening?
    • CommentAuthorhaymo
    • CommentTimeJun 15th 2010
     

    some ideas:

    1) try replacing prior NaNs with MachineParameterDouble.eps instead of 0

    2) find out, why any NaN exist at all (they shouldn't be there, I suppose?)

    3) make sure, you are using the proper datatype (single ? double? complex double? etc... )

    4) make sure, the array is properly detached from the DS buffer (by COPYING from the buffer or by cloning the array)

    If nothing helps, please post your code here and/or prepare a small test case for reference and reproducability. (I doubt, the reason is in the fft)

    • CommentAuthormlew
    • CommentTimeJun 27th 2010
     
    Thanks for the tips - sorry it took so long to reply; I've been tied up with some other work. I tried replacing prior NaNs with MachineParameterDouble.eps, but that didn't work either. Not quite sure why those NaNs exist - all I'm doing is getting an array of data by reading the directsound buffer. Here's the code I've been working on (at least the relevant bits of it):

    private double[] processData(double[] data)
    {
    //create new ILArray from data to process
    ILArray<double> dataToProcess = new ILArray<double>(data);

    //compute 1D FFT on dataToProcess
    ILArray<ILNumerics.complex> processedData = ILMath.fft(dataToProcess);

    //get length of processedData
    int theLength = processedData.Length / 2;
    for (int i = 0; i < theLength; i++)
    {
    ILNumerics.complex c = (ILNumerics.complex)processedData[i];
    //get frequency at i
    double freq = Common.sampleRate * i / theLength;
    if (freq >= Common.lBound && freq <= Common.uBound) // amplify this region
    {
    c.real /= 2;
    }
    }
    ILArray<double> fData = ILMath.abs(ILMath.ifft(processedData));
    double[] final = fData.Values.ToArray<double>();

    return final; //change this later
    }

    private void EchoThread()
    {
    while (true)
    {
    Common.notificationEvent.WaitOne(Timeout.Infinite, true);

    byte[] theBuf = (byte[])buffer.Read(offset, typeof(byte), LockFlag.None, Common.notifySize);
    double[] dblBuf = (double[])buffer.Read(offset, typeof(double), LockFlag.None, Common.notifySize);
    for (int i = 0; i < dblBuf.Length; i++)
    {
    if (Double.IsNaN(dblBuf[i]))
    dblBuf[i] = new MachineParameterDouble().eps;
    }
    //process data
    double[] procBuf = processData(dblBuf);
    //System.Buffer.BlockCopy(procBuf, 0, theBuf, 0, theBuf.Length);
    byte[] fprocBuf = new byte[procBuf.Length];
    for (int i = 0; i < procBuf.Length; i++)
    {
    if (Double.IsNaN(procBuf[i]))
    fprocBuf[i] = (byte)0;
    else
    fprocBuf[i] = byte.Parse(procBuf[i].ToString());
    }
    //write contents of capture buffer to playback buffer
    Common.ampBuffer.Write(offset, fprocBuf, LockFlag.None);
    //move capture offset
    offset = (offset + Common.notifySize) % (Common.bufferPositions * Common.notifySize);
    //write captured sound to wav file and update length of wave file
    Writer.Write(theBuf, 0, theBuf.Length);
    length += theBuf.Length;
    }
    }
    • CommentAuthorhaymo
    • CommentTimeJun 27th 2010
     

    Just some thoughts on possible optimizations... :

    private double[] processData(double[] data) //why not take an ILArray<double> here?
    {
    //create new ILArray from data to process
    ILArray<double> dataToProcess = new ILArray<double>(data);

    //compute 1D FFT on dataToProcess
    ILArray<ILNumerics.complex> processedData = ILMath.fft(dataToProcess);

    //get length of processedData

    // // the loop can be replaced by:
    // processedData[startIndex + ":" + endIndex] /= 2.0;

    // // (precomputed startIndex, endIndex)

    int theLength = processedData.Length / 2;
    for (int i = 0; i < theLength; i++)
    {
    ILNumerics.complex c = (ILNumerics.complex)processedData[i];
    //get frequency at i
    double freq = Common.sampleRate * i / theLength; // sampleRate / 2!
    if (freq >= Common.lBound && freq <= Common.uBound) // amplify this region
    {
    c.real /= 2;
    }
    }
    ILArray<double> fData = ILMath.real(ILMath.ifft(processedData));
    double[] final = fData.Values.ToArray<double>();

    return final; //change this later
    // why not return ILArray<double>?
    }

     

    Regarding NaN: make sure, not to confuse byte / double datatypes! This would produce NaNs as well. Make sure, no NaNs are coming from buffer. Checks on NaN can be done with:

    find(isnan(fprocBuf)).Length > 0, or
    fprocBuf[find(isnan(fprocBuf))] = MachineParameterDouble.eps

     

    • CommentAuthormlew
    • CommentTimeJul 13th 2010
     
    Funnily enough, the problem seemed to solve itself when I converted the byte array from the directsound buffer to a double array. I'm willing to guess that the bit of code that read a double array from the buffer introduced some conversion problems that ended up manifesting themselves as NaN.

    Thanks for the help!