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

안드로이드 PCM 파일 FFT 처리

0 추천

안녕하세요 이제 막 어플리케이션 제작을 하는 초보자입니다..

지금 하려는게 파일을 녹음하고 그 파일을 불러와 fft 처리를 해서 일정 크기 이상의 소리를 표시하고 싶은데 들려주는 주파수와 계산상에 나오는 주파수가 달라서 여쭤봅니다... 아래 코드처럼 PCM 타입으로 AudioRecord로 녹음해서 저장되어 있는 파일을 불러와서 처리하는데 뭐가 잘못됐는지 잘 모르겠네요 ㅠㅠ

도와주시면 정말 감사하겠습니다!!

public class RecordAudio extends AsyncTask<Void, double[], Void> {

    @Override
    protected Void doInBackground(Void... params) {
        //FileInputStream fis = null;
        InputStream in = null;
        BufferedInputStream bis = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        byte[] writeData = new byte[mBuffersize];
        short[] buffer = new short[blockSize]; //blockSize = 256
        double[] toTransform = new double[blockSize]; //blockSize = 256
        //double[] dataRecord = new double[blockSize];

        EditText editText = findViewById(R.id.editText_id);
        mFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + editText.getText().toString() + ".pcm";

        File file = new File(mFilePath);

        try {
            in = new FileInputStream(file);
            bis = new BufferedInputStream(in);
            int len = 0;
            while ((len = bis.read(writeData)) >= 0) {
                baos.write(writeData, 0, len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        for (int i = 0; i < blockSize; i++) {
            buffer[i] = (short) writeData[i];
            toTransform[i] = (double) buffer[i] / Short.MAX_VALUE; 
        }
        transformer.ft(toTransform);
        publishProgress(toTransform);
        return null;
    }
@Override
public void onProgressUpdate(double[]... toTransform) {
    
    int count = 0;
    for (int i = 0; i < toTransform[0].length; i++) {
        int x = i;
        double freq = (int) (x * 15.625);
        //Log.d("toTransform", Double.toString(toTransform[0][i]));

        if (toTransform[0][i] * 100 > 3.5) {
            //Log.d("toTransform compare", Double.toString(toTransform[0][i]));
            mFrequency1 = freq;

            Log.d("mFrequency toTransform", String.valueOf(mFrequency1));
        }
        imageview.invalidate();
    }
}
왕별 님이 2018년 9월 17일 질문

1개의 답변

0 추천
 
채택된 답변
writeData에 들어간 데이터가 맨마지막 read한 값만 들어갔을 듯 합니다.

baos 에 왜 write한지도 이해가 안가구요..

PCM을 8bit 로 저장하신게 맞다면,  아래와 같이 mBuffersize 만큼 read한 데이터를

퓨리에 변환하는 씩으로 바꿔보세요..

            int len = 0;
            while ((len = bis.read(writeData, 0, mBuffersize)) >= 0) {
                 for (int i = 0; i < len; i++) {
                    buffer[i] = (short) writeData[i];
                    toTransform[i] = (double) buffer[i] / Short.MAX_VALUE;
                }
                transformer.ft(toTransform);
                publishProgress(toTransform);
            }
익명사용자 님이 2018년 9월 18일 답변
감사합니다!!!
혹시 그런데 저렇게 하면 녹음된 순서대로 주파수 값이 출력이 되어야 하지 않나요...?? 제가 이해한게 맞다면 높은 주파수 소리부터 낮은 주파수 소리로 녹음을 시키면 출력도 그 순서대로 나와야 할 것 같은데 낮은 주파수부터 로그에 올라오네요... 혹시 여기도 도움을 좀 주실 수 있나요...? 감사합니다
필터 로직이 의심스럽습니다.
        if (toTransform[0][i] * 100 > 3.5) {
            mFrequency1 = freq;
        }
로 되어 있는게, 일정 주파수 이하는 무조건 freq 값으로 치환되서요..
우선  필터 변환하기 전의 데이터로 그래프를 그려, 그래프가 원하시는대로 나오는지 확인 해 보시는게 좋을 듯 합니다.
답변 감사합니다!!
그래프로 바꿔서 계산을 해봐야겠네요... 혹시 하나만 더 실례가 안된다면 여쭤봐도 될까요...? 저 계산이 FFT 계산인데 onProgressUpdate에서 1차원 배열을 왜 2차원 배열로 받아서 0값을 쓰는지 이해가 잘 안되는데 알려주실 수 있나요...?? 도움주셔서 감사합니다
...