java - terminale - timbre d'un son définition




Représentation graphique de la hauteur(fréquence) d'un son (2)

Il y a several other questions sur stackoverflow propos de ce problème. Peut-être que cela aidera.

Au lieu de cela, vous pourriez essayer de trouver une copie de Digital Audio avec Java par Craig Lindley. Je ne pense pas que ce soit imprimé, mais la copie sur mon bureau a une section sur la FFT et aussi un exemple d'application d'un accordeur de guitare.

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 j'ai besoin de montrer la hauteur de l'audio, pas l'amplitude. La transformée de Fourier rapide semble obtenir la hauteur, mais elle doit connaître plus de variables que les octets bruts que j'ai, et elle est très complexe et mathématique.

Y a-t-il un moyen de le faire?


La transformation de Fourier rapide n'a pas besoin d'en savoir plus que les octets d'entrée que vous avez. Ne soyez pas effrayés par l'article de Wikipédia. Un algorithme FFT prendra votre signal d'entrée (avec les algorithmes FFT communs le nombre d'échantillons doit être une puissance de 2, par exemple 256, 512, 1024) et retourner un vecteur de nombres complexes de la même taille. Parce que votre entrée est réelle, pas complexe, (partie imaginaire mise à zéro) le vecteur retourné sera symétrique. La moitié seulement contiendra des données. Puisque vous ne vous souciez pas de la phase, vous pouvez simplement prendre la magnitude des nombres complexes, qui est sqrt (a ^ 2 + b ^ 2). Le simple fait de prendre la valeur absurde d'un nombre complexe peut également fonctionner, dans certaines langues, cela équivaut à l'expression précédente.

Il existe des implémentations Java de FFT, par exemple: http://www.cs.princeton.edu/introcs/97data/FFT.java.html

Pseudo code ressemblera à quelque chose comme:

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 adresses pour des fréquences comprises entre zéro et la moitié de votre fréquence d'échantillonnage.

Comme FFT suppose un signal répétitif, vous pouvez appliquer une window à votre signal d'entrée. Mais ne vous inquiétez pas à ce sujet au début.

Vous pouvez trouver plus d'informations sur le web, par exemple: FFT pour les débutants

De même, comme le remarque Oli lorsque plusieurs fréquences sont présentes, la hauteur perçue est un phenomenon plus complexe.





pitch