java - propiedades - Graficando el tono(frecuencia) de un sonido
propiedades del sonido pdf (3)
Quiero trazar el tono de un sonido en un gráfico.
Actualmente puedo trazar la amplitud. El siguiente gráfico se crea con los datos devueltos por getUnscaledAmplitude()
:
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new BufferedInputStream(new FileInputStream(file)));
byte[] bytes = new byte[(int) (audioInputStream.getFrameLength()) * (audioInputStream.getFormat().getFrameSize())];
audioInputStream.read(bytes);
// Get amplitude values for each audio channel in an array.
graphData = type.getUnscaledAmplitude(bytes, 1);
public int[][] getUnscaledAmplitude(byte[] eightBitByteArray, int nbChannels)
{
int[][] toReturn = new int[nbChannels][eightBitByteArray.length / (2 * nbChannels)];
int index = 0;
for (int audioByte = 0; audioByte < eightBitByteArray.length;)
{
for (int channel = 0; channel < nbChannels; channel++)
{
// Do the byte to sample conversion.
int low = (int) eightBitByteArray[audioByte];
audioByte++;
int high = (int) eightBitByteArray[audioByte];
audioByte++;
int sample = (high << 8) + (low & 0x00ff);
toReturn[channel][index] = sample;
}
index++;
}
return toReturn;
}
Pero necesito mostrar el tono del audio, no la amplitud. La transformación rápida de Fourier parece obtener el tono, pero necesita saber más variables que los bytes sin procesar que tengo, y es muy compleja y matemática.
¿Hay alguna manera de que pueda hacer esto?
Hay several other questions sobre sobre este problema. Quizás esto ayude.
En cambio, podría intentar encontrar una copia de Audio Digital con Java de Craig Lindley. No creo que ya esté impreso, pero la copia en mi escritorio tiene una sección sobre la FFT y también una aplicación de muestra de un afinador de guitarra.
La Transformada rápida de Fourier no necesita saber más que los bytes de entrada que tiene. No te asustes por el artículo de Wikipedia. Un algoritmo FFT tomará su señal de entrada (con los algoritmos de FFT comunes se requiere que el número de muestras sea una potencia de 2, por ejemplo, 256, 512, 1024) y devolverá un vector de números complejos con el mismo tamaño. Debido a que su entrada es real, no compleja, (porción imaginaria puesta a cero), el vector devuelto será simétrico. Solo la mitad contendrá datos. Como no te importa la fase, simplemente puedes tomar la magnitud de los números complejos, que es sqrt (a ^ 2 + b ^ 2). Solo tomar el valor de absoulte de un número complejo también puede funcionar, en algunos idiomas esto es equivalente a la expresión anterior.
Hay implementaciones Java de FFT disponibles, por ejemplo: http://www.cs.princeton.edu/introcs/97data/FFT.java.html
El pseudo código se verá algo así como:
Complex in[1024];
Complex out[1024];
Copy your signal into in
FFT(in, out)
for every member of out compute sqrt(a^2+b^2)
To find frequency with highest power scan for the maximum value in the first 512 points in out
La salida contendrá entradas para frecuencias entre cero y la mitad de su frecuencia de muestreo.
Como FFT asume una señal de repetición, puede aplicar una window a su señal de entrada. Pero no te preocupes por esto al principio.
Puede encontrar más información en la web, por ejemplo: FFT para principiantes
Además, como señala Oli cuando hay frecuencias múltiples, el tono percibido es un phenomenon más complejo.
La frecuencia (una métrica objetiva) no es lo mismo que el tono (una cantidad subjetiva). En general, la detección de tono es un problema muy complicado.
Suponiendo que solo quiera graficar la respuesta de frecuencia por el momento, no tiene más remedio que usar la FFT, ya que es el método para obtener la respuesta de frecuencia de los datos de dominio de tiempo. (Bueno, hay otros métodos, como la transformación discreta del coseno, pero son tan difíciles de implementar y más difíciles de interpretar).
Si está luchando con la implementación de la FFT, tenga en cuenta que en realidad es solo un algoritmo eficiente para calcular la transformada discreta de Fourier (DFT); ver en.wikipedia.org/wiki/Discrete_Fourier_transform . El algoritmo DFT básico es mucho más fácil (solo dos bucles anidados), pero se ejecuta mucho más lento (O (N ^ 2) en lugar de O (N log N)).
Si desea hacer algo más complejo que simplemente trazar el contenido de frecuencia (como la detección de tono, o la ventana (como otros han sugerido)), me temo que tendrá que aprender lo que significa la matemática.