현재 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초도 걸리지 않는 알고리즘입니다.
속도를 개선하기 위한 방법이 궁금합니다.
제발 도와주세요 ㅠㅠ