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?
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
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. –
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. –