3

I have been asking several questions here before about analyzing a FSK signal. I am generating and recording a fsk signal with sample rate of 44100, it contains two frequencies, 934Hz for '1' and 510Hz for '0', the encoded message is a string which I transform into its binary reprsentation and each bit is represented using 2048 samples. I have a preliminary tone with a frequency of 440Hz before the tone representing the data itself. I used the following code to capture the audio bytes, the only difference is that I am writing them to a ByteArrayOutputStream https://stackoverflow.com/questions/23432398/audio-recorder-in-android-process-the-audio-bytes

I was using 8000 sample rate before and decided to improve the transmission rate, so I changed the sample rate. When my recorder and transmitter used 8000 sample rate I managed to find the start point of the signal and analyze the data, for some reason when I use a sample rate of 44100 my fft doesn't seem to work well, I can't find the right frequencies, I don't even see the overtones I once saw when I worked with 8000 sample rate, I use hann window function from this class and multiply each window: https://github.com/jpatanooga/Canova/blob/master/canova-data/canova-data-audio/src/main/java/org/canova/sound/musicg/dsp/WindowFunction.java.

For now, I just advance every 2048 sample in my recorded data to see the results. I am not quite sure why the fft doesn't work, any ideas?

I am attaching some functions I use:

Function to convert the audio bytes to a doule array representing the normalised sine wave (the data sent is in little endian format):

private double[] convertBytes2SineWave(byte[] byteArray)
    {
        double[] doubleArray = new double[byteArray.length / 2];
        short temp;
        double normalizedVal;
        for (int i=0; i<doubleArray.length; i++)
        {   
            //The data send in little endian format - first byte is low order byte
            byte bLow = byteArray[2*i];
            byte bHigh = byteArray[2*i + 1];
            temp = (short)(((bHigh & 0x00FF) << 8) | (bLow & 0x00FF));
            normalizedVal = temp / 32767.0 ; 
            doubleArray[i] = normalizedVal;
        }
        return doubleArray;
    }

The fft function:

    public double[] calculateFFT(double[] signalChunk, int numFFTPoint)
        {           
            double mMaxFFTSample;
            double temp;
            Complex[] y;
            Complex[] complexSignal = new Complex[numFFTPoint];
            double[] absSignal = new double[numFFTPoint/2];

            for(int i = 0; i < numFFTPoint; i++)
            {
                temp = signalChunk[i];
                complexSignal[i] = new Complex(temp,0.0);
            }

            y = FFT.fft(complexSignal);

            mMaxFFTSample = 0.0;
            mPeakPos = 0;
            for(int i = 0; i < (numFFTPoint/2); i++)
            {
                 absSignal[i] = Math.sqrt(Math.pow(y[i].re(), 2) + Math.pow(y[i].im(), 2));
                 if(absSignal[i] > mMaxFFTSample)
                 {
                     mMaxFFTSample = absSignal[i];
                     mPeakPos = i;
                 } 
            }
             return absSignal;
        }

Function for extracting the data bits:

private void ExtractDataBits()
    {
        byte[] byteArrayData = ByteArrayAudioData.toByteArray();
        sExtractedBits= new StringBuilder();

        double binSize =((double)sampleRate/numberOfFFTPoints);
        int HighFreqPos =(int) (freqOfHighTone/binSize);
        int LowFreqPos =(int) (freqOfLowTone/binSize);
        double[] daOriginalSine = convertBytes2SineWave(byteArrayData);

        double[] smallArray;
        int NumOfRuns = daOriginalSine.length /numberOfFFTPoints;
        int startIndex = 0;
        while(NumOfRuns > 0)
        {
            if(daOriginalSine.length - startIndex < numberOfFFTPoints)
                break;
            smallArray = new double[numberOfFFTPoints];
            System.arraycopy(daOriginalSine, startIndex, smallArray, 0, numberOfFFTPoints);
            smallArray = applyHannWindow(smallArray, numberOfFFTPoints);
            double[]fftRes = calculateFFT(smallArray,numberOfFFTPoints);
            if(fftRes[HighFreqPos] > fftRes[LowFreqPos])
                sExtractedBits.append("1");
            else
                sExtractedBits.append("0");
            startIndex = startIndex + numberOfFFTPoints;
            NumOfRuns--;
        }

    }
Community
  • 1
  • 1
just_code_it
  • 41
  • 1
  • 5
  • As with any debugging problem, you should break this down - plot your data at strategic points throughput the program - often a problem will be immediately apparent when you see the data as a graph. Once you have identified the problem then you can narrow your focus to just the area where the bug is. – Paul R Apr 23 '15 at 13:19
  • How do you know you changed the sample rate from 8000 to 44100? – hotpaw2 Apr 23 '15 at 18:39
  • @hotpaw2, I have two different projects, the sender and the reciver, I changed in both of them the samplerate. – just_code_it Apr 23 '15 at 18:50
  • @PaulR I tried to export the data to a csv file, it didn't give me much information. I used Audacity to look at the results, they seem to be right, the frequencies and their corresponding overtones. This is very wierd, can't find my mistake. – just_code_it Apr 23 '15 at 18:54
  • Well there shouldn't even be any overtones, since you're dealing with sine waves - this was raised as a problem in the comments to your previous questions but you don't seem to have addressed it ? – Paul R Apr 23 '15 at 22:18
  • 2
    Why don't you try isolating the problem. For example you could generate a 440 Hz sine wave directly in doubles and then run the analysis. This would rule out any problems in conversion from bytes, data transmission, etc... – jaket Apr 24 '15 at 04:44
  • 1
    Do your sampleRate and numberOfFFTPoints variables match the actual sample rate and fft size? Does a count of the actual samples received in about 1 second seem to match the sample rate setting? – hotpaw2 Apr 24 '15 at 23:56

0 Answers0