C# C# FFT Troubleshooting: Sampling at 44100 Hz, 16384 Samples

  • Thread starter Thread starter btb4198
  • Start date Start date
  • Tags Tags
    Fft
AI Thread Summary
The discussion revolves around troubleshooting FFT issues in a C# program that samples audio at 44100 Hz using 16384 samples. The user is experiencing discrepancies between their FFT output and expected values, particularly when compared to MATLAB results. Key suggestions include ensuring proper windowing of sample data, verifying that the audio data is correctly interpreted as signed 16-bit integers, and testing with known sine wave inputs to validate the FFT implementation. Additionally, there are concerns about whether the microphone is capturing stereo or mono audio, which could affect the input samples. The user is encouraged to isolate and test different components of their code to identify the source of the inaccuracies.
btb4198
Messages
570
Reaction score
10
I am trying to make this



but my FFT is not getting close enough to the right Values

I am Sampling at a 44100 Hz rate

and I am sending

16384 samples to the fft at a time

but it is not close

I have attach a pic

what should i do?
I know the FFT work.. because i compared it to mat lab...

so how can I troubleshoot this?
 

Attachments

  • text1.jpg
    text1.jpg
    50.8 KB · Views: 531
Last edited by a moderator:
Technology news on Phys.org
How did you compare to Matlab? By giving both a simple n cycle sine wave?
What happens if you give both the same 16k sampled mixed sound source?
In what way is the answer then not close? What does Matlab give and what does your code give?
Are you windowing your sample data before FFT? http://en.wikipedia.org/wiki/Window_function
 
I have posting on my other fft threads... but I just enter sinewaves and just buffer with samples, both in mat lab and in my program.

if you look at my picture you will see that
youtube is outputting a frequency of 117Hz

but my programs highest peek is over 60 then 70.
that is not right
 
no I am not windowing my sample before the FFT...
the FFT gets raw data

Code:
 for (int index = 0; index < 32768; index += 2)
            {

                short sample = (short)((buffer[index + 1] << 8) |
                                        buffer[index + 0]);

                float sample32 = sample / 32768f;
                buffer1[tempint] = (double)sample32;
                tempint++;

            }

I am Sampling at a 44100 Hz rate

and I am sending

16384 samples to the fft at a time
 
I presume that tempint has been initialized to zero.
Also, how did you fill that buffer? Was it with a WAV file?
 
no it is from a microphone ..
and yes tempint is.
I am writing this in C#
 
btb4198 said:
no it is from a microphone ..
and yes tempint is.
I am writing this in C#
What evidence do you have that you are successfully sampling amplitude information from the microphone, and that it contains a sine waveform of significant amplitude.

As a test, have you tried putting samples into array that are generated from the sin() function?
 
it is not a sine waveform... should it be ?

if you send me you email
I can send you my program
 
btb4198 said:
it is not a sine waveform... should it be ?

if you send me you email
I can send you my program
I didn't look at the youtube video, but the frame gram you showed as an attachment showed a sine wave. Also, a sine wave is a good test pattern for an FFT exercise since it should show a single spike at the corresponding wavelength.

I guessing that you played the youtube video, picked up the sound with the mic, and tried to capture a segment of it at 44.1KHz.

If that's about what you did, then I would definitely put a known sine wave (computed from the sin() function) into your FFT subroutine or tool to verify that you have that part of the problem working. Then work on getting good data from your microphone to "buffer".

I don't want to look at that much of your code. You get to do all the real work.
 
  • #10
sorry I miss understood you.

yes the youtube video is a sinewave
if you go to youtube and look up "high frequency" you will see it
 
  • #11
also I have tested the fft by enter in a know sinewave and out putting the answered...
that works,
I have also compared my fft to MATLAB and my fft works for 2^n number of samples
 
  • #12
btb4198 said:
also I have tested the fft by enter in a know sinewave and out putting the answered...
that works,
I have also compared my fft to MATLAB and my fft works for 2^n number of samples
So it's really looking as though the problem is getting the signal you want through the microphone to "buffer".
 
  • #13
yeah I guess
 
  • #14
btb4198 said:
yeah I guess
Supposedly your collecting at 44.1KHz. So find a tone that's about 5KHz, capture that sound with you mic, and then print out the first 20 values in buffer. If all is working well, you will see about two full sine waves.

If you see something else, you're not capturing correctly.

For example:
onlinetonegenerator.com/?freq=5000

In general, you want to be able to test isolated parts of your code so that you can determine where the problem is.
 
  • #15
ok i can't add the right picture on here... the forum will not let me ...

but this is how it looks
the highest peek is 2500
which is haft of 5000
 

Attachments

  • picnow.jpg
    picnow.jpg
    47.7 KB · Views: 620
  • #16
this is how the sample input looks

it repeats
 

Attachments

  • test.jpg
    test.jpg
    22 KB · Views: 601
  • #17
I saw this one too :
test2.jpg
 
  • #18
also this
test3.jpg
 
  • #19
I'm guessing there's something wrong with the raw data charts - probably some sort of under-sampling issue.

The fact that you're getting a spike at 2500Hz, with harmonics at 2500Hz intervals is very encouraging. It means that some rendition of the sound is making to your buffer.

My guess is that the samples are actually 8-bit samples, not 16-bit - or that you are capturing stereo instead on mono.
 
  • #20
well this is weird : I use that same site you sent to me and I did 4000 Hz
and the highest point is 2000Hz

I also did 3000Hz from that same site
and the highest point I get is 1499.249

I also did 10,000
but this is what i got :
test4.jpg


any ideas as to why?
 
  • #21
Code:
            PointPairList list = new PointPairList();
            PointPairList list2 = new PointPairList();
            byte[] buffer = e.Buffer;
            int bytesRecorded = e.BytesRecorded;
            points = new RollingPointPairList(32768 / 2);
            buffer1 = new double[(32768 / 2)];
            int tempint = 0;
            for (int index = 0; index < 32768; index += 2)
            {

                buffer1[tempint] = ((buffer[index + 1] << 8) |
                                        buffer[index + 0]);
                tempint++;

            }

            DSP = new DSPclass(buffer1, 44100);
            DSP.FFT1();
is it a 16 bit sample and I break into one double
 
  • #22
ok
here is my code to print out the fft as a frequency
N ( the number of samples) = 16384
Fs ( the sampling frequency) = 44100 Hz
R( R is a int) = 16384



Code:
        public int frequencies(double[] freq, double [] Ctemp)
        {
            
            int counter = 0;
            for (int i = 0; i < R; i++)
                    {
                        if (((i / N) * Fs) >= (Fs / 2)) // nyquist 
                        {
                            return counter;

                        }
                        if (Math.Abs(F[i].Magnitude) > 100)
                        {
                            freq[counter] = (i / N) * Fs;
                            Ctemp[counter] = F[i].Magnitude;
                            counter++;

                        }
                    }
            return counter;  
        }
is that right ?
Frequency = (bin / N) * Fs?
and I should be using the Magnitude right ?
oh this is all c#
 
  • #23
If the magnitude is less than 100, you skip the frequency value?
I'm guessing that you are trying to treat all small magnitudes as noise. If that's the case, you should set Ctemp[counter] to 0.

Since both i and N are integers and i<N, i/N will always be zero. So freq[counter] is always zero.
 
  • #24
yes i am treating all the small magnitudes as Noise .
should it be higher than 100?

no , I get values for my counter
but is Frequency = (bin / N) * Fs?
is that right ?
 
  • #25
so I just tried this :
Code:
 for (int index = 0; index < 32768; index++)
            {
                buffer1[tempint] = buffer[index]; 
                tempint++;
            }
and the fft is off
so maybe it really is 16bits

do anyone know anything that might help me?
 
  • #26
ok if I just do * 2 to my out put it works...
I just do not know why...
 
  • #27
It's okay to filter noise, but this is how you would do it:

Code:
    public int frequencies(double[] freq, double [] Ctemp)
    {
        int counter = 0;
        for (int i = 0; i < R; i++)
        {
            freq[counter] = (i / N) * Fs;
            if (Math.Abs(F[i].Magnitude) > 100)
            {
                Ctemp[counter] = F[i].Magnitude;
            } else {
                Ctemp[counter] = 0;
            }
            counter++;
        }
        return counter;
    }
 
  • #28
the way I am going is...
I do not keep the once with a magnitude > 100
but I am thinking about making it 1000
 
  • #29
btb4198 said:
I also did 10,000
but this is what i got :
View attachment 66066


btb4198 said:
Code:
            int tempint = 0;
            for (int index = 0; index < 32768; index += 2)
            {

                buffer1[tempint] = ((buffer[index + 1] << 8) |
                                        buffer[index + 0]);
                tempint++;

            }

I think the problem is that the audio data is signed 16 bit integers (between -32768 and +32767) but your code is converting them to unsigned integers between 0 and 65535.

Try this:
Code:
            int tempint = 0;
            for (int index = 0; index < 32768; index += 2)
            {

                buffer1[tempint] = ((buffer[index + 1] << 8) |
                                        buffer[index + 0]);
                if (buffer1[tempint] > 32767)
                    buffer1[tempint] = buffer1[tempint] - 65536;
                tempint++;

            }

If would be better just to declare buffer as an array of 16-bit signed ints instead of unsigned 8-bit bytes, then you can just copy the data from buffer to your double array buffer1.
 
  • #30
ok you where right about between -32768 and +32767
the ftt is a lot less noisy...
and the print out of the samples look a lot better ...

however, I am still getting half the Frequencies...
I can just do * by 2 at the very end and get the right Frequencies but I really want to know why it is doing this
 
  • #31
btb4198 said:
however, I am still getting half the Frequencies...
I can just do * by 2 at the very end and get the right Frequencies but I really want to know why it is doing this
Are you looking at stereo information?
 
  • #32
I do not know... how can I find out ?
I am using the default microphone on my computer..
what is the different between stereo and mono for a microphone ?
mono is one.. so one mic
so it stereo more that one mic?

how would did affect the input samples ?
 
  • #33
btb4198 said:
I do not know... how can I find out ?
I am using the default microphone on my computer..
what is the different between stereo and mono for a microphone ?
mono is one.. so one mic
so it stereo more that one mic?

how would did affect the input samples ?
I don't know how you are grabbing the information. At some point you must have specified 44100Hz, 16 bits per sample. When you did that, the same data structure should have included whether the signal would be stereo or mono.
 
  • #34
AlephZero
this code:
Code:
    int tempint = 0;
            for (int index = 0; index < 32768; index += 2)
            {

                buffer1[tempint] = ((buffer[index + 1] << 8) |
                                        buffer[index + 0]);
                if (buffer1[tempint] > 32767)
                    buffer1[tempint] = buffer1[tempint] - 65536;
                tempint++;

            }
I am really reading in 44100 bytes at a time from the Microphone and not 32768
I am sending 16384 samples to the FFT because I am 2^N sample for the FFT

anynow so should the code really be
Code:
 int tempint = 0;
            for (int index = 0; index < 32768; index += 2)
            {

                buffer1[tempint] = ((buffer[index + 1] << 8) |
                                        buffer[index + 0]);
                if (buffer1[tempint] > 44100)
                    buffer1[tempint] = buffer1[tempint] - 88200;
                tempint++;
because the Microphone is sending 44100 bytes
I am not sure about this
so i maybe thinking of this all wrong
 
Back
Top