Je veux tracer la hauteur d'un son dans un graphique.
Actuellement, je peux tracer l'amplitude. Le graphique ci-dessous est créé par les données renvoyées par 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;
}
Mais je dois montrer la hauteur de l'audio, pas l'amplitude. transformée de Fourier rapide semble obtenir la hauteur, mais il a besoin de connaître plus de variables que les octets bruts que j'ai, et est très complexe et mathématique.
Existe-t-il un moyen de le faire?
La fréquence (une métrique objective) n'est pas la même chose que la hauteur (a quantité subjective). En général, la détection de hauteur est un problème très délicat.
En supposant que vous vouliez simplement représenter graphiquement la réponse en fréquence pour le moment, vous n'avez d'autre choix que d'utiliser la FFT, car elle est [~ # ~] la [~ # ~] méthode pour obtenir la réponse en fréquence des données du domaine temporel. (Eh bien, il existe d'autres méthodes, telles que la transformée en cosinus discrète, mais elles sont tout aussi difficiles à mettre en œuvre et plus difficiles à interpréter).
Si vous rencontrez des difficultés avec la mise en œuvre de la FFT, notez qu'il s'agit vraiment d'un algorithme efficace pour calculer la transformée de Fourier discrète (DFT); voir http://en.wikipedia.org/wiki/Discrete_Fourier_transform . L'algorithme DFT de base est beaucoup plus facile (seulement deux boucles imbriquées), mais exécute un lot plus lent (O (N ^ 2) plutôt que O (N log N)).
Si vous souhaitez faire quelque chose de plus complexe que de simplement tracer le contenu des fréquences (comme la détection de hauteur ou le fenêtrage (comme d'autres l'ont suggéré)), je crains que vous n'ayez à apprendre ce que les mathématiques signifient.
La transformation de Fourier rapide n'a pas besoin d'en savoir plus que les octets d'entrée dont vous disposez. Ne soyez pas effrayé par l'article de Wikipedia. Un algorithme FFT prendra votre signal d'entrée (avec les algorithmes FFT courants, le nombre d'échantillons doit être une puissance de 2, par exemple 256, 512, 1024) et retournera un vecteur de nombres complexes de la même taille. Parce que votre entrée est réelle et non complexe (portion imaginaire mise à zéro), le vecteur renvoyé sera symétrique. Seulement la moitié contiendra des données. Puisque vous ne vous souciez pas de la phase, vous pouvez simplement prendre la grandeur des nombres complexes, qui est sqrt (a ^ 2 + b ^ 2). La simple prise de la valeur absoulte d'un nombre complexe peut également fonctionner, dans certaines langues, cela équivaut à l'expression précédente.
Il existe Java implémentations de FFT disponibles, par exemple: http://www.cs.princeton.edu/introcs/97data/FFT.Java.html
Le pseudo-code ressemblera à ceci:
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 sortie contiendra des entrées pour des fréquences comprises entre zéro et la moitié de votre fréquence d'échantillonnage.
Comme la FFT suppose un signal répétitif, vous pouvez appliquer un fenêtre à votre signal d'entrée. Mais ne vous en faites pas au début.
Vous pouvez trouver plus d'informations sur le web, par exemple: FFT pour les débutants
Aussi, comme le note Oli lorsque plusieurs fréquences sont présentes, la hauteur perçue est plus complexe phénomène .
Il y a plusieursautrequestions sur stackoverflow à propos de ce problème. Peut-être que cela vous aidera.
Au lieu de cela, vous pouvez essayer de trouver une copie de Digital Audio with Java par Craig Lindley. Je ne pense pas que ce soit plus imprimé, mais la copie sur mon bureau a une section sur la FFT et aussi un exemple d'application d'un accordeur de guitare.