3

FSK 信号の解析について、以前ここでいくつか質問をしてきました。サンプルレート44100のfsk信号を生成して記録しています。これには、「1」の場合は934Hz、「0」の場合は510Hzの2つの周波数が含まれています。エンコードされたメッセージは、バイナリ表現に変換する文字列であり、各ビットは2048 サンプル。データ自体を表すトーンの前に、周波数が 440Hz の予備トーンがあります。次のコードを使用してオーディオバイトをキャプチャしました。唯一の違いは、ByteArrayOutputStream https://stackoverflow.com/questions/23432398/audio-recorder-in-android-process-the-audio-bytes

以前は 8000 サンプル レートを使用していましたが、伝送レートを改善することにしたので、サンプル レートを変更しました。私のレコーダーと送信機が 8000 サンプル レートを使用していたとき、信号の開始点を見つけてデータを分析することができました。適切な周波数、8000 サンプル レートで作業したときに一度見た倍音さえ表示されません。このクラスのハン ウィンドウ関数を使用して、各ウィンドウを乗算します: https://github.com/jpatanooga/Canova/blob/ master/canova-data/canova-data-audio/src/main/java/org/canova/sound/musicg/dsp/WindowFunction.java .

今のところ、記録したデータを 2048 サンプルずつ進めて結果を確認します。fftが機能しない理由がよくわかりません。何かアイデアはありますか?

私が使用するいくつかの機能を添付しています:

オーディオ バイトを正規化された正弦波を表す doule 配列に変換する関数 (送信されるデータはリトル エンディアン形式です):

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;
    }

fft 関数:

    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;
        }

データ ビットを抽出する関数:

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--;
        }

    }
4

0 に答える 0