마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

소스활용 질문..(FFT,주석등..)

0 추천
package fft;

import java.io.*;

import android.util.Log;

import dsp.AudioProcessing;

public class FFTHelper
{
 private double mPeakFreq;
 private int mPeakPos;
 private double mSampleRateInHz;
 private int mNumberOfFFTPoints;
 private double mMaxFFTSample;
  
 public FFTHelper(double sampleRate, int numberOfFFTPoints)
 {
  mSampleRateInHz = sampleRate;
  mNumberOfFFTPoints = numberOfFFTPoints;
 }
 //FFT 계산 부분 (이곳에서 아날로그 신호값을 디지털로 변환시켜준다.(아마도..)
 public double[] calculateFFT(byte[] signal)
 {   
  double temp;
  Complex[] y;
  Complex[] complexSignal = new Complex[mNumberOfFFTPoints];
  double[] absSignal = new double[mNumberOfFFTPoints/2];  
  
  for(int i = 0; i < mNumberOfFFTPoints; i++) //FFT포인트 개수만큼 반복 
  {
   temp = (double)((signal[2*i] & 0xFF) | (signal[2*i+1] << 8)) / 32768.0F; 
   //-127~127을 0~256 으로 바꿔주는 부분 (unsigned 만드는 과정)
   //signal 배열을 통해 왼쪽 으로 8바이트 홀수배열 오른쪽 8 바이트 짝수 배열
   //byte형 배열 signal의 홀수 인덱스[]값을 왼쪽으로 8 bit shift.
   //아마도 샘플링된 값을 signal[]에 넣어주게되면 짝수 홀수 배열로 나누어 
   
   complexSignal[i] = new Complex(temp,0.0);   //temp 값을 복소수 형태로 변형시켜준다. 
   //Log.d("tag",""+complexSignal[i]);
   
  }

  y = FFT.fft(complexSignal); 
  //이 복소수 신호값을 fft식에 대입하여 계산해준다.  
  //y배열에는 실수부와 허수부로 나눠져있다.
  
  mMaxFFTSample = 0.0; //초기화
  mPeakPos = 0; //초기화 
  
  
  for(int i = 0; i < (mNumberOfFFTPoints/2); i++)
  {
   //re - 실수 im - 허수 sqrt (제곱근)
    absSignal[i] = Math.sqrt(Math.pow(y[i].re(), 2) + Math.pow(y[i].im(), 2));  //크기 구하는 식 
    //이 부분을 실행하면 실수 허수 complex 계산을 통해 abs signal 값을 얻을 수있다.
    //제곱근(y[i].re()  *  y[i].re()     +     y[i].im()  *  y[i].im() )  
    
    Log.d("tag",""+absSignal[i]);
    if(absSignal[i] > mMaxFFTSample) //max값보다 주파수 크기가 크다면 max변수에 넣어준다. 
    {
     
     mMaxFFTSample = absSignal[i];
     mPeakPos = i; //x축 포지션 0~ 쭉 
    }
  }
  
  return absSignal;
 }
 
 public double getPeakFrequency() //최고 주파수를 찾아준다. 
 {
  mPeakFreq = mPeakPos*(mSampleRateInHz/mNumberOfFFTPoints);
  return mPeakFreq;
 }
 
 public double getPeakFrequency(int[] absSignal)
 {
  
  int peakPos = 0, max = absSignal[0];
  
  for(int i=1; i < (mNumberOfFFTPoints/2); i++)
  {
    if(absSignal[i] > max)
    {
     max = absSignal[i];
     peakPos = i;
    }
  }
  
  return peakPos*(mSampleRateInHz/mNumberOfFFTPoints);
 }
 
 public double getMaxFFTSample(){
  return mMaxFFTSample;
 }
}

해당 소스는 FFT 소스입니다.. (고속 푸리에 트랜스폼)

 

여기서 아날로그 신호값을 디지털로 변환하여 주파수 크기에 대한 그래프를 그려주려고 하는데요..

 

아날로그 신호값을 어디에 무슨변수 형태로 넣어줘야 그에 해당하는 디지털 신호값을 얻을 수 있는건가요..

 

최종적으로 사용하게되는 코드는 absSignal[] 에 있는 값들을 이용하여 그래프를 그려주게되는것을 확인했습니다.

 

그래서 이걸 역으로 탐지해서 올라가면 나오겠지 했는데 도대체 원래 어디에서 온 값인지 찾을 수가 없었습니다..

 

코드가 너무 영어와 주석이 붙어있지않아서 최대한 제가 이해하면서 한글로 붙인건데.. 아직도 모르는 부분이 많아서..

 

이렇게 질문을 남겨드립니다..

 

제 추측으로는 signal[]배열에 넣어야하는거같지만.. 오류가나길래; 혹여나 다른 곳에  넣어야하는건지 몰라서....

도와주세요 ㅠㅠ 1주일째 고민중이다가 이제 서야 손들고 질문드립니다..

 

백돈 (220 포인트) 님이 2013년 12월 2일 질문

1개의 답변

0 추천
Fft는 아날로그 신호를 디지털형태오 변환하는것이 아니라 시간 도메인에서 보던 신호를 주파수 도메인으로 변경 해쥬는 변환 기법 입니다. 위에 칼큘레이트에프에프티 메소드에 보시면 바이트 배열을 받아들이죠? 디지털형태로 샘플링 된 데이터를 입력 받아서 계산하는겁니다. 여담으로말씀드리면 샘플수는 2의 승수개가 되어야 합니다. 음악파일 분석하시나요? 그렇다면 pcm raw data를 뽑아서 이를 2의 승수만큼 모아서 Fft 계산을 수행하게 되겠지요
익명사용자 님이 2013년 12월 3일 답변
그럼 저signal[] 배열이 이미 디지털화 된 샘플링 값인건가요??

그렇다면 이미 adc되어버린 값을 저 signal배열에 집어넣게되면 원하는 동작을 행해 줄 수 있는건가요??:: 너무 모르는것 투성이 입니다.

음악소스 분석은아니구요. 다른 모듈에서 가져오는 디지털 신호를 분석하려고 합니다.
아날로그 신호에서 signal 배열이 이미 샘플링된 값이죠 ㅇㅇ

일단 요 사이트를 참고하셔서 푸리에변환에 대해 좀 공부해보시는 편이 좋을거 같네요. 저도 많이 참고한 홈페이지구요.

http://dmusiclab.com/rb/?c=4/14&p=2&uid=13
간단하게 정리를 해서 말씀드리명

샘플링된 데이터 받음 > 복소수형태로 바꿈 (허수부는 0으로 맞추겠죠) > 오메가 데이터셋 생성 > 이 둘을 이용해서 지지고 볶고 해서 fft > 최종 결과 데이터 생성 > 원하시는 처리 작업
감사합니다 그런데 이미 디지털 샘플링된 signal[i]바이트 배열이 디지털화 되어있나 해서 로그 로 찍어봤는데 13 55 -23 이런식으로 정수가 나오더라구요.. 이게 정상적인건가요??: 제가알기론 디지털값은 010101 2진수로 나오는거로 알고있지만;;
정확히 말씀드리면 디지털 데이터라기보단 아날로그 신호에서 샘플링된 데이터를 의미합니다. 이렇게 샘플링된 데이터를 이용해서 디지털신호로 바꾸게 되죠. 일단 fft같은 경우는 찍어보신 샘플들을 모아서 fft를 수행하시면  되겠습니다.
안녕하세요 혹시 위의 코드의 전체 코드를 파일로 좀 받아볼 수 있을 까요??
youngunyoung@naver.com 으로 확인 좀 부탁드립니다.
...