2010-02-16 28 views
7

Tôi có một bộ sưu tập các tệp WAV ngắn mà tôi muốn xử lý trong Java bằng các thuật toán xử lý tín hiệu kỹ thuật số khác nhau. Tôi cần lấy một mảng các mẫu có giá trị int cho mục đích này, được mã hóa ở tốc độ khung hình 11025 Hz.Chuyển đổi tốc độ lấy mẫu khi đang đọc tệp WAV thành một mảng mẫu với Java

Tệp nguồn có một số tỷ lệ mẫu khác nhau, bao gồm 11025 Hz và 44100 Hz. Đây là mã tôi đang cố sử dụng để đọc chúng:

// 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 

Vấn đề là mã không xử lý các tỷ lệ mẫu khác nhau đúng cách. Vì vậy, đối với tốc độ khung hình 44100 Hz, tôi nhận được gấp bốn lần so với tốc độ khung hình 11025 Hz. Tôi muốn mảng mẫu kết quả để sử dụng tốc độ khung hình 11025 Hz, bất kể tốc độ khung hình của tệp nguồn. Tôi cố gắng để buộc Java để chuyển đổi tỷ lệ khung hình đối với tôi khi đọc AudioInputStream, nhưng tôi nhận được một ngoại lệ tương tự như sau:

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) 

tôi đọc API hướng dẫn Java Sound: http://java.sun.com/docs/books/tutorial/sound/converters.html. Có vẻ như Java Sound API không hỗ trợ loại chuyển đổi này của hệ điều hành của tôi (Windows 7). Và tôi muốn tránh sự phụ thuộc vào bất kỳ thư viện bên ngoài nào. Có cách nào để thực hiện chuyển đổi tỷ lệ lấy mẫu trên của riêng tôi không?

Trả lời

6

Đối với tỷ lệ mẫu> 11025 Hz, bạn cần phải giảm mẫu, đây là một quá trình hai giai đoạn. Trước tiên, bạn cần có bộ lọc thông thấp để đáp ứng tiêu chí Nyquist, và sau đó bạn có thể phân tích, ví dụ: đối với dữ liệu tỷ lệ mẫu 44,1 kHz, bạn sẽ cần bộ lọc thông thấp với tần số cắt là 5,5 kHz và sau đó bạn có thể vứt bỏ 3 trong số 4 mẫu cho tỷ lệ lấy mẫu 4: 1. Bạn sẽ cần một bộ lọc khác nhau cho mỗi tỷ lệ thu nhỏ mà bạn muốn hỗ trợ.

+0

Làm cách nào để tính tần suất cắt? Và tại sao bước này là cần thiết? – pako

+2

Việc lọc là neccissary vì hiệu ứng nyquist. Trong ngắn hạn: nếu sr của bạn là 11025 hz và đầu vào của bạn có một giai điệu 5572,5 hz trong nó, mà sẽ được sao chép như một giai điệu 60 hz. Nyquist bọc là hoàn toàn không hài hòa (dịch: âm thanh thực sự xấu xí và xấu). Bạn cần phải lọc tất cả các đầu vào trên một nửa sr mới của bạn để loại bỏ tiếng ồn nyquist. –

+2

và bằng cách "lọc tất cả đầu vào trên nửa sr mới của bạn", tôi đảm bảo rằng không có nội dung nào ở trên tần suất đó - và số lượng lọc và nơi bạn cắt nó có thể thay đổi tùy theo tài liệu nguồn của bạn - hãy nghe kết quả, nó sẽ được rõ ràng từ tiếng ồn thêm nếu bộ lọc của bạn cần phải được dốc hơn hoặc cần một tần số cắt thấp hơn. –

5

Tôi tin câu trả lời được chấp nhận trả lời một câu hỏi khác - nó giải quyết cùng một vấn đề (downsampling âm thanh) nhưng theo cách khác (bằng tay thay vì sử dụng API âm thanh java). Tôi đã có cùng một điều và đào sâu vào nó.

Cách đúng (hoặc cách java âm thanh API) để làm điều này thực sự là (như đề xuất trong 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); 

Vấn đề là java tiêu chuẩn không xuất xưởng với resampling (hoặc thậm chí chuyển đổi âm thanh stereo-mono) (hoặc ít nhất không nằm trong phần mã đó - xem http://www.jsresources.org/faq_audio.html#convert_sample_rate).

Các trang jsresources cũng chỉ ra các câu trả lời: chỉ cần cài đặt 2 trình bổ sung. Đơn giản nhất là cài đặt các plugin trong thư mục Extensions, trên OSX Lion này sẽ làm các trick (miễn là bạn có wget):

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 

Sau khi thêm những 2 file jar, tất cả mọi thứ đã làm việc (chỉ là một cảnh báo thêm: nếu bạn muốn thay đổi cả số lượng kênh và tỷ lệ mẫu, nó vẫn không được hỗ trợ như một bước).

Các vấn đề liên quan