2010-02-16 4 views
7

나는 다양한 디지털 신호 처리 알고리즘을 사용하여 Java에서 처리하고자하는 짧은 WAV 파일 모음을 가지고 있습니다. 이 목적을 위해 11025Hz 프레임 속도로 인코딩 된 정수 값 샘플의 배열을 가져와야합니다.WAV 파일을 Java로 샘플 배열로 읽을 때 즉석에서 샘플 속도 변환

소스 파일에는 11025 Hz 및 44100 Hz를 포함하여 여러 가지 샘플 속도가 있습니다. 다음은이를 읽으려는 코드입니다.

// read the WAV file 
FileInputStream fileInputStream = new FileInputStream(new File("test.wav")); 
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(fileInputStream); 

// copy the AudioInputStream to a byte array called buffer 
ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
byte[] data = new byte[4096]; 
int tempBytesRead = 0; 
int byteCounter = 0; 
while ((tempBytesRead = audioInputStream.read(data, 0, data.length)) != -1) { 
    bos.write(data, 0, tempBytesRead); 
      byteCounter += tempBytesRead; 
} 
bos.close(); 
byte[] buffer = bos.toByteArray(); 

AudioFileFormat audioFileFormat = new AudioFileFormat(AudioFileFormat.Type.WAVE, audioInputStream.getFormat(), (int)audioInputStream.getFrameLength()); 

// get the resulting sample array 
int[] samples = new int[audioFileFormat.getFrameLength()]; 
for (int i = 0; i < samples.length; i++) { 
    samples[i] = getSampleValue(i); // the getSampleValue method reads the sample values from the "buffer" array, handling different encoding types like PCM unsigned/signed, mono/stereo, 8 bit/16 bit 
} 

// RESULT: the "samples" array 

문제는 코드가 다른 샘플 속도를 올바르게 처리하지 못한다는 것입니다. 그래서 44100Hz 프레임 속도의 경우 11025Hz 프레임 속도의 4 배의 샘플을 얻습니다. 결과 샘플 배열에서 소스 파일의 프레임 속도에 관계없이 11025 Hz 프레임 속도를 사용하고 싶습니다. 나는 AudioInputStream를 읽을 때 나를 위해 프레임 레이트를 변환하는 자바를 강제로했지만, 나는 다음과 같은 하나의 예외가 비슷한 얻을 :

java.lang.IllegalArgumentException: Unsupported conversion: PCM_SIGNED 11025.0 Hz, 16 bit, mono, 2 bytes/frame, 44100.0 frames/second, little-endian from PCM_SIGNED 44100.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian 
    at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:955) 

나는 자바 사운드 API 튜토리얼을 읽어 http://java.sun.com/docs/books/tutorial/sound/converters.html합니다. 자바 사운드 API가 내 운영체제 (Windows 7)의 이러한 종류의 변환을 지원하지 않는 것 같습니다. 그리고 나는 외부 라이브러리에 대한 의존성을 피하고자한다. 자체적으로 샘플링 레이트 변환을 수행 할 수있는 방법이 있습니까?

답변

6

샘플 속도가 11025Hz 이상인 경우에는 2 단계 프로세스 인 다운 샘플링이 필요합니다. 먼저 Nyquist 기준을 만족하기 위해 로우 패스 필터가 필요합니다. 44.1 kHz 샘플 속도 데이터의 경우 5.5 kHz의 차단 주파수로 저역 통과 필터를 사용해야하며 4 : 1 다운 샘플링 비율에 대해 4 개 샘플 중 3 개를 버릴 수 있습니다. 지원하려는 다운 샘플링 비율마다 다른 필터가 필요합니다.

+0

컷오프 주파수는 어떻게 계산합니까? 그리고 왜이 단계가 필요합니까? – pako

+2

나이 퀴 스트 효과 때문에 필터링이 필요하지 않습니다. 간단히 말해서, 귀하의 SR이 11025 Hz이고 입력 신호가 5572.5 Hz 인 경우 60 hz 톤으로 재현됩니다. 나이 퀴 스트 랩 (Nyquist wrap)은 완전히 고조파가 아닙니다 (번역 : 정말로 추악하고 나쁜 소리). 나이 퀴 스트 노이즈를 제거하려면 새 SR의 반 이상에서 모든 입력을 필터링해야합니다. –

+2

그리고 "모든 입력을 필터링하여 새 sr의 절반 이상을 필터링하십시오."라는 말은 해당 빈도보다 제로의 콘텐츠가 있는지 확인하는 것입니다. 필터링의 양과 잘라내 기는 소스 자료에 따라 다를 수 있습니다. 필터가 더 가파르거나 더 낮은 컷오프 주파수를 필요로 할 경우 추가되는 노이즈로부터 분명합니다. –

5

나는 대답이 다른 질문에 답할 것이라고 믿는다 - 오디오를 다운 샘플링하는 것과 같은 문제를 해결하지만 다른 방법으로 (자바 사운드 API를 사용하지 않고 수동으로) 문제를 해결한다. 나는 똑같은 것을 가지고 그것을 파고 들었다. (http://docs.oracle.com/javase/tutorial/sound/converters.html에서 제안)

AudioFormat outDataFormat = new AudioFormat((float) 8000.0, (int) 8, (int) 1, true, false); 
AudioInputStream lowResAIS = AudioSystem.getAudioInputStream(outDataFormat, inFileAIS); 

문제는 표준 자바는 리샘플링와 함께 제공되지 않습니다이 작업을 수행하는 (또는 자바 사운드 API 방식은) 참으로 올바른 방법입니다

(또는 스테레오 - 모노 변환) 코드 (또는 최소한 코드의 해당 부분에 없으면 - http://www.jsresources.org/faq_audio.html#convert_sample_rate 참조).

jsresources 페이지도 대답을 가리 킵니다. 간단히 말해서 2 개의 플러그인을 설치하는 것이 트릭입니다. 가장 쉬운이 트릭 (당신이 wget을을 제공) 할 것 OSX 라이온에, 확장 디렉토리에이 플러그인을 설치하는 것입니다 :이 두 jar 파일을 추가 한 후

wget http://www.tritonus.org/tritonus_share-0.3.6.jar -O /Library/Java/Extensions/tritonus_share-0.3.6.jar 
wget http://www.tritonus.org/tritonus_remaining-0.3.6.jar -O /Library/Java/Extensions/tritonus_remaining-0.3.6.jar 

을, 모든 (한 추가 경고를했다 : 당신이 경우 채널 수와 샘플 속도를 모두 변경하려면 한 단계로 지원되지 않습니다.)

관련 문제