Bonjour
je voudrais savoir de quoi j'ai besoin dans un fichier WAV afin de trouver, par l'intermédiaire d'une transformé de fourier, la fréquence du signal.
merci de votre aide
Bonjour
je voudrais savoir de quoi j'ai besoin dans un fichier WAV afin de trouver, par l'intermédiaire d'une transformé de fourier, la fréquence du signal.
merci de votre aide
Salut,
Pourquoi utiliser la Transformée de Fourier pour trouver la frequence ?
XXiemeciel
Connais tu un autre moyen de trouver la fréquence d'un son?
si oui je suis prenneur!!!
merci
Ton signal n'a qu'une seule fréquence ? C'est nouveau, surtout dans un fichier wav !
j'enregistre une note le LA par exemple et je voudrais connaitre la frequence de ce son afin de le comparer au LA "idéal" (440Hz)
http://sub0.developpez.com/FormatWAV/FormatWAV.htm
sur ce site on montre dans le script du fichier WAV une fréquence (24..27 et 28..31) pouvez vous me dire à quoi elle correspond?
merci
Le premier est la fréquence d'échantillonage, le second est le débit en octets par seconde.
d'accord!!! merci beaucoup
et de quoi ais je besoin pour trouver la fréquence de mon son .
le son que je souhaite étudier est une note de music produit par une guitare par exemple
Pour utiliser la FFT à partir de data d'1 fichier wave il faut le lire correctement.
Il est constitué de blocs "Header" et blocs "data"
le bloc Header à la structure suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 struct Wave_File_Header { char RIFF[4]; //"RIFF" in ASCII form long Data_Size_plus_36; // filesize-8 = nbr data * bitsperdata+ 36 char WAVE[4]; // letters "WAVE" char fmt[4]; // letters "fmt " long Remain_in_Chunk1; // 16 for PCM. // rest of the Subchunk which follows this number. // = audioformat+numchanel+samplerate+byterate+blockalign+bitpersample // =2+2+4+4+2+2 = 16 short AudioFormat; // PCM = 1 (i.e. Linear quantization) Values other than 1 indicate some form of compression. short NumChannels; // Mono = 1, Stereo = 2, etc. long SampleRate;// 8000, 44100, etc. long ByteRate; // SampleRate * NumChannels * BitsPerSample/8 short BlockAlign; // NumChannels * BitsPerSample/8 short BitsPerSample; // 8 bits = 8, 16 bits = 16, etc. // maintenant The "data" subchunk contains the size of the data and the actual sound: char data[4];// "data" long Data_Size; // taille des data = NumSamples * NumChannels * BitsPerSample/8 // ici commence les data dans le fichier wave };
les data, pour un fichier mono, sont alignés les uns derrières les autres sur 8 ou 16 bits chacuns suivant ce que l'on lit dans le header ( NumChannels, BitsRate ). Si le fichier est stéréo, les cannaux sont entrelacés - je ne sais plus si ils sont mis G-D-G-D -... ou D-G-D-G-...
les entiers lus sont signés -128..127 ou -2^15..2^15-1
il est IMPERATIF de lire correctement SampleRate pour connaître la fréquence d'échantillonage (Hz) .
Evidemmment si votre nombre de points pour le calcul de la FFT est limité, pour voir les basses fréquences il vous faudra sous-echantilloner( un la à 440 Hz echantilloné à 44kHz represente 100 pts. avec une FFT sur 512 pts, on a 5 longueurs d'ondes donc on accède le la (+ ou - car il n'y a probablement aucun point de la FFT pour f=440 exactement ) mais avec assez peu de précision si on devait en trouver la justesse) .
ATTENTION sous-échantilloner ne signifie pas prendre 1 échantillon sur n!!! il y aurrait là un risque de repliment de spectre ( phénomène analogue à de la stroboscopie ) qui pourrait dans certains cas conduire à des erreurs IMPORTANTES!!!
Il existe de nombreux algorithmes de sous-échantillonages mais cela est déjà 1 autre problème.
Alors je m'interesse et rajoute ma petite question : vu le forum, quel est l'algorithme de calcul d'une FFT? (par curiosité)
L'algorithme de FFT le plus utilisé est celui de Cooley-Tukey. Il evolue en n.log(n) alors que la transformée de fourier evolue en n^2. Il exige un nombre de point qui soit du type 2^n. Il cyclise le signal => il peut y avoir des artefacts sur les bords si y pour n petit ( 1er points) diffère semsiblement de y ( derniers points ~2^n-1)
Pour une formation de base je pense que se site est pas mal
http://www.ecole.ensicaen.fr/~furon/_traitementsignal/_cours_tns/_PlanCoursTNS.htm
Un algo simple en VB (même si tu programmes en c, la conversion n'est pas compliquée) sur cette page. Sur ce site, tu as même accès à l'IFT qui est la fonction inverse de la FFT (et qui en fait est le même algo !)
Remarque : sinon, pour avoir la fréquence d'une note (qui doit être constante dans le temps) tu prends la fréquence de la FFT qui à l'amplitude max (enfin, pas la première, qui correspond à la fréquence 0Hz, soit la valeur moyenne du son).
En wav y a que peu de fréquences d'échantillonage :
8000Hz, 11025Hz, 12000Hz, 16000Hz, 22050Hz, 24000Hz, 32000Hz, 44100Hz, 48000Hz
Cet algo marche avec du 22050Hz 8bits mono. I faut changer en fonction de ce que tu voeux.
Pour plus d'aide, laisses un message sur le forum
Ceci n’est que partiellement vrai…
Si le signal est digitalisé à Fd et que l’on analyse N = 2^n points, la durée T de la tranche analysée est
T = N/Fd
Le pas df de l’analyse FFT sera donc Fd/N et les points calculés par la FFT se situeront à
Fi = i * Fd/N i=0..2^(n-1)
Prenons le cas Fd = 44KHz et une analyse su 2048 points
df = 44100 / 2048 = 21.53 Hz.
20*df = 430.66
21.df = 452.19
Un La à 440 Hz ne peut donc être atteint. On mesure un max à 10 Hz de sa valeur nominale soit environ 2.7% ce qui représente environ ¼ de ton ( ½ ton <-> 2^(1/12 ))
Suivant la précision souhaitée, il faut prendre un nombre de points plus grand pour le calcul de la FFT. < surtout si on a du vibrato et que les raies présentent une certaine distribution>. Cela peut parfoi être rédibitoir si on considère taille mémoire, temps de calcul, ...
On peut aussi, suivant le domaine de fréquence que l’on souhaite analyser réduire Fd afin d’accroître T donc diminuer df pour un nombre N de points donné ( prix à payer : perte de l’info HF pour 1 analyse donnée. On calcul le même nombre de points mais on densifie la quantité de points aux BF en abandonnant les HF ).
Pour diminuer Fd il ne suffit pas de prendre 1 point sur p dans le fichier. On s’exposerais alors au repliement de spectre ( 1 peu analogue à la stroboscopie ) : Il faut réellement appliquer un filtre qui videra le signal de toute énergie au dessus de F’d / 2 < Nyquist>.
Si les raies sont suffisement pures, on peut aussi ne pas accroître la bande passante de l'analyse mais faire une analyse avec une digitalisation 'modeste' et savoir que la/les raies détectées doivent être corrigées par un facteur multiplicatif correspondant à l'effet stroboscopique utilisé. Cela est très fréquent comme ananalyse pour des antennes HF assez pure comme téléphonie, ...
Oui,
C'est vrai que j'avais omis ce point. Il est vrai que lorsqu'on applique la FFT sur un signal de moins d'une seconde, la première 'fréquence' correspond à une fréquence de période 'la durée de ce signal'. Donc si le signal étudié dure 0,1 sec, la fréquence 1 sera 10hz, la 2 sera 20Hz, etc...
Il faut trouver un compromis entre :
+ Nombre de FFT par seconde (qui permet d'avoir l'évolution des fréquences dans le temps (au moins 10FFT/sec = évolution fluide))
+ Visibilité des basses fréquences (pour voir du 2Hz par ex, il faudrait faire au plus 2FFT/sec (Mais bon, on n'entend pas le 2Hz)), qui rime avec précision des fréquences (1FFT/sec = précision à 1Hz, 3FFT/sec = précision à 3Hz...)
Il est hélas impossible d'avoir à la fois une bonne fluidité dans le temps et une bonne précision des fréquences, et ce, quelle que soit la vitesse d'échantillonage
Voilà, et je rajoute aussi que sur le tableau comtenant les fréquences obtenues par la FFT, seule la première moitié est à exploiter, la 2ième partie étant la première vue dans un mirroir.
Salut
Heisenberg quand tu nous tiens...
Autre solution, faire une transformée en Z du type chirp transform, l'inconvénient étant que ça ne fait qu'interpoler les valeurs de la FFT classique, et que selon la fenêtre utilisée, on aura plus ou moins d'aliasing
Je me demande pourquoi j'ai choisi un sujet sur l'accordeur d'instrument de musique pour mon projet en C.Je suis perdu dans toutes les réponses ...
merci de votre aide à tous en tout cas
Salut,
J'ai fait un algo qui répond exactement à ton problème. En plus l'algo de la FFT est plus simple que celui que je t'avais donné avant. Précision de la fréquence fondamentale de ton son à 0,7Hz près (ça devrait suffire, sauf si tu t'appelles Mozart et que tu as une ouie très très fine). Pour voir le resultat :
+ downloades ce repertoire sur ton pc (sous windows sinon ça marche po),
+ ensuite enregistre un son wav en 22050Hz 8Bits Mono de 1,5 secondes au moins.
+ Mets ce fichier dans le repertoire 'Fichiers' du programme
+ Allumes le programme, cliques sur le bouton, saisit le nom du fichier (sans l'extension)
+ Et regardes le résultat...
Voilà, en espérant que cela t'aidera. Normalement y a plus qu'a convertir en C.
PS : au cas ou, le code vb :
Dans un module standard :
Dans la form :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 Public Const Pi = 3.14159265358979 'Structure d'1 complexe Public Type Complexe Re As Single Im As Single End Type 'Module d'1 complexe Public Function Module(C As Complexe) As Single Module = Sqr(C.Re * C.Re + C.Im * C.Im) End Function 'Multiplication de 2 complexes Public Function MulC(C1 As Complexe, C2 As Complexe) As Complexe MulC.Re = C1.Re * C2.Re - C1.Im * C2.Im MulC.Im = C1.Re * C2.Im + C1.Im * C2.Re End Function 'FFT (X = entrée, Y = sortie) Public Sub FFT(N As Long, X() As Complexe, Res() As Complexe) Dim Paire() As Complexe, Impaire() As Complexe, U() As Complexe, V() As Complexe Dim I As Long, I1 As Long Dim AlphaI As Single, Alpha As Single Dim Tau As Complexe If N = 1 Then Res(0) = X(0) Else ReDim Paire(0 To N / 2) ReDim Impaire(0 To N / 2) ReDim U(0 To N / 2) ReDim V(0 To N / 2) For I = 0 To N / 2 - 1 Paire(I) = X(2 * I) Impaire(I) = X(2 * I + 1) Next I FFT N / 2, Paire(), U() FFT N / 2, Impaire(), V() Alpha = 2 * Pi / N For I = 0 To N - 1 AlphaI = Alpha * I I1 = I Mod (N / 2) Tau.Re = Cos(AlphaI) Tau.Im = Sin(AlphaI) Res(I) = U(I1) Res(I).Re = Res(I).Re + MulC(Tau, V(I1)).Re Res(I).Im = Res(I).Im + MulC(Tau, V(I1)).Im Next I End If End Sub
La partie form, je l'ai faite à l'arache alors j'éspère qu'elle est bonne. Voilà
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 Private Sub Bo_Decomposer_Click() Const Taille = 32768 '2^N obligatoirement Dim NomFichier As String, Fichier() As Byte Dim DataC(0 To Taille) As Complexe, Freq(0 To Taille) As Complexe, Ampli(0 To Taille) As Single Dim Ampl As Long, B As Long, X As Long Dim Amax(1 To 20) As Single, IAmax As Long, IFmin As Long, Fondam As Single NomFichier = InputBox("Quel fichier voulez vous tester :") ReDim Fichier(0 To Taille) Open "Fichiers\" & NomFichier & ".wav" For Binary As #1 Get #1, 59, Fichier() Close #1 For B = 0 To Taille DataC(B).Re = Fichier(B) DataC(B).Im = 0 Next B FFT Taille, DataC(), Freq() Im_Spectre.Cls For B = 0 To Taille Ampli(B) = Module(Freq(B)) / 1024 Im_Spectre.Line (B, 512)-(B, 512 - Ampl) Next B 'Freq 1 = 1 * 22050/32768 'Freq 2 = 2 * 22050/32768 'cherche les 20 frequence dont les ampli sont les plus importantes For X = 1 To 20 IAmax = 1 For B = 2 To Taille If Ampli(B) > Ampli(IAmax) Then IAmax = B Next B Amax(X) = IAmax Ampli(IAmax) = 0 Next X 'trouve la freq mini parmis elles IFmin = 1 For X = 2 To 20 If Amax(X) < Amax(IFmin) Then IFmin = X Next X 'fondamentale Fondam = Amax(IFmin) * 22050 / Taille MsgBox "La fondamentale de votre signal a pour fréquence : " & Fondam End Sub
Ci-joint un code C qui calcul la FFT suivant l'algorithme de C&T.
Il suppose des signaux réels. ( Y = 0 dans l'espace temporel, X Symétrique et Y AntiSymétique dans l'espace fréquentiel )
Il faut tout de même faire attentions aux remarques qui ont été citées dans les precedents messages.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156 //--------------------------------------------------------------------------- #define power 14 /* mettre une autre valeur si souhaité. A partir de 15 il faut changer short en integer car un short ne peut pas aller audela de 2^15 - 1 */ #define FFT_Pts (1<<power) /* 2^14 = 16384 */ #define Norme 1.0/(double)FFT_Pts #define N2 (1<<(power-1)) /* nombre de points pour FFT */ short Swp[FFT_Pts]; /* Swap d'index pour algorithme de Cooley-Tukey */ double _c[FFT_Pts], _s[FFT_Pts]; /* Cos et Sin */ void swap_ ( short *r1, short *r2 ) /* routine de swap */ { short r = *r1; *r1 = *r2; *r2 = r; } void Initialize(void) /* à appeler en 1er pour créer les sin / cos et initialiser Swap */ { /* evidement si on fait 1 seulle FFT dans 1 soft, il n'est pas */ double R = FFT_Pts; /* necessaire de buffuriser sin , cos et swap */ R = 2.0/R * M_PI; for ( int i=0; i <FFT_Pts; i++) { _c[i] = cos(R*i); _s[i] = sin(R*i); } short j = 0; for ( short i = 0 ; i < FFT_Pts-1; i++) Swp[i] = i; for ( short i = 0 ; i < FFT_Pts-1; i++) { if ( i < j ) swap_(&Swp[i],&Swp[j]); short k = N2; while (k <= j) { j -= k; k = k >> 1; } j += k; } } // FFT et IFFT peuvent se mettre dans une seule routine mais alors quelques tests // aditifs aont necessaire ( sin -> -sin, Norme change, ... // cela est + rapide de séparer si on peut se le permettre void IFFT(double xreal[] ,double yimag[] ) // X, Y parties reelle et imaginaires du signal { // X est symetrique, Y AS pour 1 signal reel double X,Y; short a,b,i,k,pnt0,pnt1,arg; double Buffx[FFT_Pts],Buffy[FFT_Pts]; memmove(Buffx,xreal,sizeof(double)*FFT_Pts); memmove(Buffy,yimag,sizeof(double)*FFT_Pts); for ( i = 0 ; i < FFT_Pts; i++ ) // swap index et norme { xreal[i] = Buffx[Swp[i]] * Norme; yimag[i] = Buffy[Swp[i]] * Norme; } a = 1 ; pnt0 = FFT_Pts; while ( pnt0 > 1 ) { b = a; a = a << 1; pnt0 = pnt0 >> 1; // (FFT_Pts/a); i = 0; arg = b; while ( i < FFT_Pts ) { X = xreal[arg]; Y = yimag[arg]; xreal[arg] = xreal[i] - X; yimag[arg] = yimag[i] - Y; xreal[i] += X; yimag[i] += Y; i += a; arg += a; } pnt1 = pnt0; k = 1; while ( k < b ) { i = k; arg = i + b; while ( i < FFT_Pts ) { X = xreal[arg] * _c[pnt1] - yimag[arg] * _s[pnt1]; Y = xreal[arg] * _s[pnt1] + yimag[arg] * _c[pnt1]; xreal[arg] = xreal[i] - X; yimag[arg] = yimag[i] - Y; xreal[i] += X; yimag[i] += Y; i += a; arg += a; } pnt1 += pnt0; ++k; } } } void FFT(double xreal[] ,double yimag[] ) { double X,Y; short a,b,i,k,pnt0,pnt1,arg; memmove(yimag,xreal,sizeof(double)*FFT_Pts); for ( i = 0 ; i < FFT_Pts-1; i++) xreal[i] = yimag[Swp[i]]; memset(yimag,0,sizeof(double)*FFT_Pts); // signal reel => Y est nul a = 1 ; pnt0 = FFT_Pts; while ( pnt0 > 1 ) { b = a; a = a << 1; pnt0 = pnt0 >> 1; // (FFT_Pts/a); i = 0; arg = b; while ( i < FFT_Pts ) { X = xreal[arg]; Y = yimag[arg]; xreal[arg] = xreal[i] - X; yimag[arg] = yimag[i] - Y; xreal[i] += X; yimag[i] += Y; i += a; arg += a; } pnt1 = pnt0; k = 1; while ( k < b ) { i = k; arg = i + b; while ( i < FFT_Pts ) { X = xreal[arg] * _c[pnt1] + yimag[arg] * _s[pnt1]; Y = yimag[arg] * _c[pnt1] - xreal[arg] * _s[pnt1]; xreal[arg] = xreal[i] - X; yimag[arg] = yimag[i] - Y; xreal[i] += X; yimag[i] += Y; i += a; arg += a; } pnt1 += pnt0; ++k; } } // pour 1 signal reel, la FFT est symétrique en X et Anti-Symetrique en Y for (i=N2+1; i < FFT_Pts; i++ ) { xreal[i] = xreal[FFT_Pts-i]; yimag[i] = -yimag[N2 - i] } }
Pour avoir une image de la densitée spectrale d'énergie, utilise le module de la FFT pour i=0.. N/2.
Il est en général présenté en décibel ( 20 * log ( PS ) PS = Power Spectrum ). Numeriquement faire attention si PS = 0 en certain(s) point(s)
Bonjour tout le monde,
avec beaucoup de temps j'ai enfin réussi a mettre les octets de mon fichier WAV dans un tableau...
maintenant il faut que je fasse la FFT de se signal pr en retirer la fréquence principale
Comment puis je faire?
merci de votre aide depuis le début
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager