Mam zbiór krótkich plików WAV, które chciałbym przetwarzać w Javie przy użyciu różnych algorytmów cyfrowego przetwarzania sygnałów. Muszę uzyskać w tym celu zestaw próbek o wartości int, zakodowanych z częstotliwością klatek na sekundę 11025 Hz.Konwersja częstotliwości próbkowania w locie podczas odczytu pliku WAV do tablicy próbek przy użyciu Javy
Pliki źródłowe mają kilka różnych częstotliwości próbkowania, w tym 11025 Hz i 44100 Hz. Oto kod, którego próbuję użyć, aby je odczytać:
// 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
Problem polega na tym, że kod nie obsługuje poprawnie różnych częstotliwości próbkowania. Tak więc dla częstotliwości klatek 44100 Hz otrzymuję cztery razy więcej próbek niż dla częstotliwości ramki 11025 Hz. Chciałbym, aby wynikowa tablica wykorzystała częstotliwość ramek 11025 Hz, bez względu na szybkość klatek pliku źródłowego. Próbowałem zmusić Java do konwersji klatek dla mnie podczas czytania AudioInputStream, ale pojawia się wyjątek podobny do następującego:
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)
Czytałem tutorial Java API dźwięku: http://java.sun.com/docs/books/tutorial/sound/converters.html. Wygląda na to, że Java Sound API nie obsługuje tego rodzaju konwersji mojego systemu operacyjnego (Windows 7). I chciałbym uniknąć zależności od zewnętrznych bibliotek. Czy jest jakiś sposób, aby zrobić konwersję częstotliwości próbkowania na własną rękę?
Jak obliczyć częstotliwość odcięcia? I dlaczego ten krok jest konieczny? – pako
Filtrowanie jest konieczne ze względu na efekt NIquist. W skrócie: jeśli twój sr jest 11025 hz, a twój sygnał wejściowy miał ton 552,5.5 hz, byłby odtworzony jako dźwięk 60 hz. Nyquist wrap jest całkowicie nieharmonijny (tłumaczenie: brzmi naprawdę brzydko i źle). Musisz odfiltrować wszystkie dane wejściowe powyżej połowy nowego sr, aby wyeliminować hałas nyquista. –
i przez "filtrowanie wszystkich danych wejściowych powyżej połowy nowego sr", tzn. Upewnij się, że jest zero treści powyżej tej częstotliwości - a ilość filtrowania i miejsca, w którym je odciąłeś, może się różnić w zależności od materiału źródłowego - słuchaj wyniku, będzie to oczywiste po dodaniu szumu, jeśli filtr musi być bardziej stromy lub wymaga niższej częstotliwości granicznej. –