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

안드로이드 이클립스로 오디오 신호처리 구현 중입니다.(PCM 파일 입출력 관련 질문입니다.)

0 추천
현재 PCM 파일 신호처리를 위해 파일 입출력 방법을 알아보고 있습니다.

FileInputStream/FileOutputStream

DataInputStream/DataOutputStream의 readShort, writeShort를 사용해서 구현하니

읽고 쓰는 속도가 너무 느려 사용할 수 없었습니다.

그래서 이번엔 모든 데이터를 ArrayList를 사용해 한번에 처리를 하고 나중에 한꺼번에 저장하려고 하였으나 더 느려진 현상이 생겼습니다.

현재 저희가 짜고 있는 코드입니다.

    private void fileread(DataInputStream IN, ArrayList<Short> DATA){
        for(int i=0;;i++){
            Log.d("TAG", "Reading"+i);
            try {
                DATA.add(IN.readShort());
            } catch (EOFException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                break;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                Toast toast = Toast.makeText(this, "먼저 해당 악기의 음원을 녹음하세요.", Toast.LENGTH_SHORT);
                toast.show();
                onBackPressed();
                e.printStackTrace();
            }
        }

    }
    private void filewrite(DataOutputStream OUT, ArrayList<Short> DATA){
        for(int i=0;;i++){
            Log.d("TAG", "Saving"+i);
            try {
                OUT.writeShort(DATA.get(i));
            } catch (IndexOutOfBoundsException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                break;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                Toast toast = Toast.makeText(this, "먼저 해당 악기의 음원을 녹음하세요.", Toast.LENGTH_SHORT);
                toast.show();
                onBackPressed();
                e.printStackTrace();
            }
        }
    }
    private void elec(DataInputStream IN){
        FileOutputStream fo1 = null;
        DataOutputStream do1 = null;
        ArrayList<Short> DATA = new ArrayList<Short>();
        
        try {
            fo1 = new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath()+"/KWIXElec_output.pcm");
            do1 = new DataOutputStream(fo1);
            fileread(IN, DATA);
        }
        catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            Toast toast = Toast.makeText(this, "먼저 해당 악기의 음원을 녹음하세요.", Toast.LENGTH_SHORT);
            toast.show();
            onBackPressed();
            e.printStackTrace();
        }
        finally{
            try{
                fo1.close();
                do1.close();
            }
            catch (Exception e){;}
        }
        
        Lowshelving(DATA, 100, -17);
        Highshelving(DATA, 2000, -27);
        Peakfilter(DATA, 1500, 1000, 35);
        filewrite(do1, DATA);
        Log.d("TAG", "completed");
    }
    private void Lowshelving(ArrayList<Short> DATA, int Fc, int G){
            double Fs = 48000;
            double PI = 3.1415926;
            
            double x, y;
            double V0 = Math.pow(10, G/20.0);

            double H0 = V0-1;
            double c;
            double xh=0, xh_new=0, ap_y=0;

            if(G>=0) c = (Math.tan(PI*Fc/Fs)-1) / (Math.tan(PI*Fc/Fs)+1);
            else c = (Math.tan(PI*Fc/Fs)-V0) / (Math.tan(PI*Fc/Fs)+V0);

            /**** 입력 샘플을 받기 시작 ****/
            int i=0;    
            while(true){
                if(i == DATA.size()) break;
                Log.d("TAG", "Lowshelving"+i);
                x = (double)DATA.get(i);
                x = 1;
                xh_new = x - c*xh;
                ap_y = c*xh_new + xh;
                xh = xh_new;
                y = (H0/2.0)*(x+ap_y)+x;
                DATA.add(i, (short)y);
                i++;
            }    
    }
    private void Highshelving(ArrayList<Short> DATA, int Fc, int G){        
            double Fs = 48000;
            double PI = 3.1415926;
            
            double x, y;
            double V0 = Math.pow(10, G/20.0);

            double H0 = V0-1;
            double c;
            double xh=0, xh_new=0, ap_y=0;

            if(G>=0) c = (Math.tan(PI*Fc/Fs)-1) / (Math.tan(PI*Fc/Fs)+1);
            else c = (V0*Math.tan(PI*Fc/Fs)-1) / (V0*Math.tan(PI*Fc/Fs)+1);

            /**** 입력 샘플을 받기 시작 ****/
            int i=0;    
            while(true){
                if(i == DATA.size()) break;
                Log.d("TAG", "Highshelving"+i);
                x = (double)DATA.get(i);
                xh_new = x - c*xh;
                ap_y = c*xh_new + xh;
                xh = xh_new;
                y = (H0/2.0)*(x-ap_y)+x;
                DATA.add(i, (short)y);
                i++;
            }    
    }
    private void Peakfilter(ArrayList<Short> DATA, int Fc, int Fb, int G){        
            double Fs = 48000;
            double PI = 3.1415926;
            
            double x, y;
            double V0 = Math.pow(10, G/20.0);

            double H0 = V0-1;
            double c, d;
            double xh[]={0, 0}, xh_new=0, ap_y=0;

            if(G>=0) c = (Math.tan(PI*Fb/Fs)-1) / (Math.tan(PI*Fb/Fs)+1);
            else c = (Math.tan(PI*Fb/Fs)-V0) / (Math.tan(PI*Fb/Fs)+V0);
            d = -Math.cos(2*PI*Fc/Fs);

            /**** 입력 샘플을 받기 시작 ****/
            int i=0;
            while(true){
                if(i == DATA.size()) break;
                Log.d("TAG", "Peakfilter"+i);
                x = (double)DATA.get(i);
                xh_new = x - d*(1-c)*xh[0] + c*xh[1];
                ap_y = -c * xh_new + d*(1-c)*xh[0] + xh[1];
                xh[1] = xh[0];
                xh[0] = xh_new;
                y = (H0/2.0)*(x-ap_y)+x;
                DATA.add((short)y);
            }        
        }

위 코드는 복잡해 보이실 수도 있지만 C로 구현했을 때 1초도 걸리지 않는 알고리즘입니다.

속도를 개선하기 위한 방법이 궁금합니다.

제발 도와주세요 ㅠㅠ
DSPLAB (120 포인트) 님이 2016년 7월 14일 질문

답변 달기

· 글에 소스 코드 보기 좋게 넣는 법
· 질문에 대해 추가적인 질문이나 의견이 있으면 답변이 아니라 댓글로 달아주시기 바랍니다.
표시할 이름 (옵션):
개인정보: 당신의 이메일은 이 알림을 보내는데만 사용됩니다.
스팸 차단 검사:
스팸 검사를 다시 받지 않으려면 로그인하거나 혹은 가입 하세요.
...