Ich habe eine Sammlung kurzer WAV-Dateien, die ich in Java mit verschiedenen digitalen Signalverarbeitungsalgorithmen verarbeiten möchte. Ich muss zu diesem Zweck eine Reihe int-bewerteter Samples erhalten, die mit der Framerate von 11025 Hz kodiert sind.Konvertieren der Abtastrate während des Einlesens einer WAV-Datei in ein Samples-Array mit Java
Die Quelldateien haben verschiedene Abtastraten, einschließlich 11025 Hz und 44100 Hz. Hier ist der Code, den ich zu verwenden, ich versuche, sie zu lesen:
// 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
Das Problem ist, dass der Code nicht Raten unterschiedliche Probe richtig umgehen kann. Für die Framerate von 44100 Hz bekomme ich also viermal so viele Samples wie für die Framerate von 11025 Hz. Ich möchte, dass das resultierende Sample-Array die Framerate von 11025 Hz verwendet, unabhängig von der Framerate der Quelldatei. Ich habe versucht, Java zu zwingen, die Frame-Rate für mich zu konvertieren, wenn die AudioInputStream lesen, aber ich habe eine ähnliche Ausnahme der folgenden ein:
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)
ich die Java-Sound-API-Tutorial lesen: http://java.sun.com/docs/books/tutorial/sound/converters.html. Es scheint, dass die Java Sound API diese Art der Konvertierung meines Betriebssystems (Windows 7) nicht unterstützt. Und ich möchte Abhängigkeiten von irgendwelchen externen Bibliotheken vermeiden. Gibt es eine Möglichkeit, die Abtastratenkonversion selbst durchzuführen?
Wie berechne ich die Grenzfrequenz? Und warum ist dieser Schritt notwendig? – pako
Die Filterung ist aufgrund des Nyquist-Effekts notwendig. Kurz gesagt: Wenn Ihr sr 11025 Hz ist und Ihr Eingang einen 5572,5 Hz-Ton hat, würde das als 60 Hz-Ton wiedergegeben werden. Nyquist Wrap ist völlig harmonisch (Übersetzung: klingt wirklich hässlich und schlecht). Sie müssen alle Eingaben oberhalb der Hälfte Ihres neuen sr filtern, um Nyquist-Rauschen zu eliminieren. –
und durch "filter alle Eingabe über die Hälfte Ihrer neuen sr" Ich meine, stellen Sie sicher, dass es keine Inhalte über dieser Frequenz ist - und die Menge der Filterung und wo Sie es ausschneiden können basierend auf Ihrem Ausgangsmaterial variieren - hören Sie das Ergebnis, Aus dem hinzugefügten Geräusch wird es deutlich, wenn Ihr Filter steiler sein muss oder eine niedrigere Grenzfrequenz benötigt. –