Tengo una colección de archivos WAV cortos que me gustaría procesar en Java usando varios algoritmos de procesamiento de señales digitales. Necesito obtener una matriz de muestras con valores int para este propósito, codificadas a la velocidad de cuadro de 11025 Hz.Convertir la frecuencia de muestreo sobre la marcha al leer un archivo WAV en una matriz de muestras con Java
Los archivos de origen tienen varias frecuencias de muestreo diferentes, que incluyen 11025 Hz y 44100 Hz. Aquí está el código que estoy tratando de utilizar para leerlos:
// 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
El problema es que el código no maneja adecuadamente diferentes frecuencias de muestreo. Por lo tanto, para la velocidad de cuadro de 44100 Hz, recibo cuatro veces más muestras que para la velocidad de cuadro de 11025 Hz. Me gustaría que la matriz de muestra resultante utilizara la velocidad de cuadro de 11025 Hz, independientemente de la velocidad de cuadro del archivo de origen. Traté de forzar Java para convertir la velocidad de fotogramas para mí al leer el AudioInputStream, pero me da una excepción similar a la siguiente:
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)
leí la API de Java tutorial de sonido: http://java.sun.com/docs/books/tutorial/sound/converters.html. Parece que Java Sound API no admite este tipo de conversión de mi sistema operativo (Windows 7). Y me gustaría evitar dependencias en cualquier biblioteca externa. ¿Hay alguna manera de hacer la conversión de tasa de muestreo por mi cuenta?
¿Cómo calculo la frecuencia de corte? ¿Y por qué es este paso necesario? – pako
El filtrado es neccisario debido al efecto nyquist. En resumen: si su sr es 11025 hz y su entrada tiene un tono de 5572.5 hz, se podría reproducir como un tono de 60 hz. Nyquist wrap es totalmente no armónico (traducción: suena realmente feo y malo). Es necesario filtrar todas las entradas por encima de la mitad de su nuevo sr para eliminar el ruido nyquist. –
y por "filtrar todas las entradas por encima de la mitad de su nueva sr" Me refiero a asegurarse de que no haya contenido por encima de esa frecuencia, y la cantidad de filtrado y donde la cortó puede variar en función de su material fuente; escuche el resultado, será obvio por el ruido agregado si su filtro necesita ser más empinado o necesita una frecuencia de corte más baja. –