ok, je te prépare tout ça et je te le donne ce soir...
ok, je te prépare tout ça et je te le donne ce soir...
• D'après ma doc, il suffit de connecter directement le cable de ton signal sur une entrée du port série sans électronique suplémentaire. Il est dit qu'avec ce système, on peut mesurer simultannément 4 fréquences allant chacune jusqu'à 10kHz environ...
• Un autre système existe avec un ampli op et un condensateur (intégrateur); Plus la fréquence est élevée, plus le condensateur se charge et plus la tension de sortie est élevée. On récupère cette valeur analogique (proportionnelle à la fréquence) pour en déduire la fréquence du signal. Cependant, ce système nécessite un étalonnage du montage avec un oscilloscope si tu souhaites obtenir des mesures précises de la fréquence d'entrée... Je n'ai pas réussi à retrouver le schéma de ce montage à cause de mon déménagement (ma doc est quelque part dans un carton).
• Autrement, si tu décides d'utiliser l'entrée ligne ou micro de ta carte son, tu devras simplement bien veiller à ce que ton signal ne dépasse pas une certaine tension si tu ne veux pas cramer l'entrée de ta carte son. Tu devras (si nécessaire) ajouter un pont de résistances pour abaisser la tension d'entrée. En ce qui concerne la partie programmation et analyse des données pour déterminer la fréquence, sachant que tu utiliseras une fréquence d'échantillonnage constante de 44,1kHz (par exemple) en 8bits mono et que ton signal étant tout ou rien, il suffira de comptabiliser les états hauts et de diviser ce nombre par le nombre d'échantillons pour obtenir la fréquence. Par exemple, si tu as 600 états hauts dans un sample de 88200 octets (2 secondes) sachant qu'1 Hz c'est une impulsion par seconde, le résultat est 300 Hz. Ainsi, tu n'auras pas à utiliser de formule complexe de spectrogramme pour déterminer la fréquence de ton signal d'entrée. De plus, le résultat sera très certainement plus précis car plus longtemps tu enregistreras le signal, plus ta mesure sera précise. Bien entendu, ce procédé n'est valable que si il s'agit d'un signal d'entrée numérique (tout ou rien) ce qui est en général le cas si ce n'est pas un signal audio. Pour déterminer l'état haut, l'octet de donnée audio est supérieur à 128 et peut aller jusqu'à 255... et de 0 à 127 pour un état bas. Cela dit, en théorie, les valeurs de ces 2 états seront bien espacées (0 pour l'état bas et 255 pour l'état haut, ou l'inverse, à vérifier).
En bref, tu comptabilises le nombre de changement d'états en parcourant les octets des données audios. Tu le divises ensuite par le nombre de secondes du sample, ce temps étant obtenu avec la taille et la fréquence d'échantillonnage et le format du sample... Est-ce clair ? Maintenant, à partir du code du vumètre de mon article, c'est très facile à faire.
Si tu as d'autres questions, n"hésites pas, à+
pour ce qui est de l'utilisation du vumetre je ne suis pas trop moi ce que je pensai faire c'est mesurer la periode en gros relever a cahaque fois que l'oscillo change de signe et ensuite utiliser la formule toute simple f=1/T
je ne comprend toujours pas ce que tu ve dire pas le tout ou rin moi mon signal aura une infinité de valeur entre 300 et 3000 hz ce ne sera donc pas une valeur unique ??
pour ce qui est de la puissance d'entree aucun probleme car je sors d'un sortie ligne d'un recepteur radio donc le signal est deja adapté
Le signal peut avoir une fréquence variable, mais comment est réaliseé cette fréquence selon toi ?Envoyé par jmjmjm
Le numérique, c'est un signal tout ou rien, boolean (pour un développeur, ça m'étonne un peu que tu ne comprennes pas de quoi je parle). Par contre, le signal audio est un signal analogique, ça tension ou plutot son amplitude varie tout le temps (voir mon tuto sur le sample wav). T'as compris ?
oui ca je suis ok avec toi ya pas de pb la dessus mais moi ce que je ve recup c'est pas une information sur un bit (1 : ok 0 :rien) mais une valeur codé sur plusieur bite pour avoir une echelle de valeur en gros je ve recup en numerique ce qui rentre en analogique
Salut Sub0,
je n'es pas trouver comment adapter ton oscillo a fin d'extraire la periode des sinusoide ! Peut tu me donner les composants electronique dont tu parlais afin de le faire de facon electronique :
Je pense qu'il faut : convertir la Frequence en tension
puis Passer dans un CAN afin de coder le signal sur 8 bit par exemple pour rentrer sur un des ports du PC !!
Sinon pe tu me donner un coup de main pour faire un logiciel qui recup la frequence Directement a partir de la carte son car pour l'instant vous m'avez donner pas mal de piste (Merci Waskol) mais j'ai toujours mon probleme je n'arrive pas a adapter vos exemple a ce que je veux! Je ne suis pas tres doué
D'abord on va mettre au clair ce que tu ne comprends pas. Ton signal est composé de 2 paramètres : L'amplitude et la fréquence. Tu vois bien que le son est une courbe qui monte et descend (amplitude). Tu admettras alors que cette courbe peut avoir 65536 valeurs si c'est du 16bits et 256 en 8bits. Le son est converti en numérique avec le CAN de la carte son. Le signal que tu veux analyser possède-t-il la même caractèristique ? La fréquence est la vitesse à laquelle est modifiée l'amplitude... L'amplitude de ton signal est binaire ou non ? C'est-à-dire que l'amplitude de ton signal ne possède que 2 valeurs. Si elle est binaire (tout ou rien), tu pourras utiliser le port série ou parrallèle pour ce projet. Dans le cas contraire, il vaut mieux utiliser la carte son.Envoyé par jmjmjm
Je n'ai pas assez de temps libre, désolé. Je peux te mettre sur la voie, mais en aucun cas, mettre au point le projet à ta place... Commence donc par comprendre (en entier) ce qui est dit dans cette page :Envoyé par jmjmjm
http://sub0.developpez.com/FormatWAV/FormatWAV.htm
à+
l'amplitude de mon signal n'est pas binaire !! Je sais ce que sont l'amplitude et la frequence Sub0 car je travaille avec des emmeteur et recepteur radio a longueur de journée donc pas de probleme de ce coté je ne voyais juste pas ce que tu voulais dire pour le coup de l'amplitude binaire !!
Donc je dois bien utiliser la carte son !!!
Salut Waskol j'ai testé la fonction Goertzel que tu m'avais donner de cette facon :
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 CONST BufSize=($10000 DIV 4)*4; var Source:string; Res:integer; Fsour:File; Size:longint; BufS:array[0..BufSize-1]of byte; v300,v600,v900,v1200,v1500,v1800,v2100,v2400,v2700,v3000:double; begin if OpenWav.Execute then Source:=OpenWav.FileName; { TEST OUVERTURE FICHIER SOURCE } IF NOT(FileExists(Source))THEN BEGIN ShowMessage('Impossible d''ouvrir '+Source);EXIT;END; {$I-} AssignFile(Fsour,Source); Filemode:=2; Reset(Fsour,1); Size:=FileSize(Fsour); BlockRead(Fsour,BufS,44,res); CloseFile(Fsour); {$I+} IF(IOResult<>0)OR(Size<116)THEN {$I-} BEGIN ShowMessage('Impossible d''ouvrir '+Source);EXIT;END; {TEST Goertzel} Goertzel(BufS,300,44100); v300 := Goertzel(BufS,300,44100); v600 := Goertzel(BufS,600,44100); v900 := Goertzel(BufS,900,44100); v1200 :=Goertzel(BufS,1200,44100); v1500 := Goertzel(BufS,1500,44100); v1800 := Goertzel(BufS,1800,44100); v2100 := Goertzel(BufS,2100,44100); v2400 := Goertzel(BufS,2400,44100); v2700 := Goertzel(BufS,2700,44100); v3000 := Goertzel(BufS,3000,44100);
Mais helas lorsque j'affiche les resultat dans des Tedit j'obtient des resultat bidon !!
De plus ce n'est pas du temps reel, on ne voit pas les valeur changer je pense que c'est la moyenne ou la somme des resultat obtenu !!
Qu'en pense tu ai-je fais une erreur ??
Je galere vraiment si quelqu'un a une petite solution merci de m'aider !!
Ha oui, je crois que c'est pas bon là.Envoyé par jmjmjm
Bon, bon, bon...
P
- L'ouverture du fichier WAV :
lors de la lecture des données binaire, il faut séparer la partie En-tête de fichier (qui indique comment est construit ton fichier wav : mono ou stereo ? sur 8,16 ou 32 bits ? quel est son taux d'echantillonnage, etc... et qui t'indique comment les données sont organisées après l'en-tête.- Traitement des données :
après tu as la lecture des données et leur traitement. Il faut que tu y ailles petit bout de fichier par petit bout de fichier... pas tout d'un bloc sinon tu va effectivement obtenir une sorte de valeur moyenne sur l'ensemble du fichier. Après il faut boucler sur les données pour que ça change, hors là, tu ne prend à chaque fois que les 44 premières valeur
J'ai mis du code (2 unités) dans les 2 posts suivants
(Excuse moi de mon absence, j'ai eu une Rhinopaharyngite assortie d'une conjonctivite ces 2 derniers jours.)
Voici un exemple (une fiche, un bouton, un TOpenDialog (pour selectionner un fichier wav), et un stringgrid :
- J'ai renommé le TOpenDialog, il s'appelle OpenWav :
- l'unit2 est dans le post suivant
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 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Grids; type TForm1 = class(TForm) Button1: TButton; OpenWav: TOpenDialog; StringGrid1: TStringGrid; procedure Button1Click(Sender: TObject); private { Déclarations privées } public { Déclarations publiques } end; var Form1: TForm1; implementation {$R *.dfm} uses Unit2; function Goertzel(Buffer: array of double; frequency, samplerate: double):double; var Qkn, Qkn1, Qkn2, Wkn, Mk : double; i : integer; begin Qkn:=0; Qkn1:=0; Wkn:=2*PI*frequency/samplerate; //=44 si échantillonage à 44,1KHz Mk:=2*Cos(Wkn); for i:=0 to High(Buffer) do begin Qkn2 := Qkn1; Qkn1 := Qkn; Qkn := Buffer[i] + Mk*Qkn1 - Qkn2; end; Result := sqrt(Qkn*Qkn + Qkn1*Qkn1 - Mk*Qkn*Qkn1); end; //recherche l'index de la valeur maxi d'un tableau function ValMaxIndex(tab:array of double):Integer; var valmax:Double; index:Integer; i:Integer; begin valmax:=-1e50; index:=-1; if Length(tab)>0 then for i:=Low(tab) to High(tab) do if tab[i]>valmax then begin index:=i; valmax:=tab[i]; end; result:=index; end; procedure TForm1.Button1Click(Sender: TObject); CONST TimeInterval=1e-3; //durée des échantillons à analyser //en secondes (1e-3=1 milliseconde) var NumChannels,BitsPerSample,SampleRate,NumSamples:Cardinal; Donnees:TDDArray; Res:integer; Fsour:File; Size:longint; BuffSize:Integer; BufS:array of double; ResultatsGoetzel:array[0..9] of double; T,x,xx,i:Integer; Canal:Integer; begin //Préparation de l'affichage StringGrid1.RowCount:=12; StringGrid1.ColCount:=2; StringGrid1.DefaultColWidth:=130; for i:=1 to 10 do StringGrid1.Cells[0,i]:=IntToStr(i*300)+' Hz'; StringGrid1.Cells[0,11]:='Maxi pour'; Canal:=0; //chargement du fichier wav if not OpenWav.Execute then Exit; LoadWaveFile(OpenWav.FileName, Donnees, NumChannels,BitsPerSample,SampleRate,NumSamples); //Taille du buffer correspondant à à peu près "TimeInterval" secondes BuffSize:=Round(SampleRate*TimeInterval); SetLength(BufS,BuffSize); T:=0; x:=0; while x<NumSamples do begin xx:=x; while ((xx<NumSamples) and ((xx-x)<BuffSize)) do begin BufS[xx-x]:=Donnees[xx,Canal]; Inc(xx); end; {TEST Goertzel} for i:=0 to 9 do ResultatsGoetzel[i]:=Goertzel(BufS,(i+1)*300,SampleRate); //Affichage dans un stringgrid StringGrid1.ColCount:=T+2; StringGrid1.Cells[T+1,0]:=FormatFloat('0.000',x/SampleRate)+' s. <T'+IntToStr(T)+'<'+FormatFloat('0.000',xx/SampleRate)+' s.'; for i:=0 to 9 do StringGrid1.Cells[T+1,i+1]:=FloatToStr(ResultatsGoetzel[i]); StringGrid1.Cells[T+1,11]:=IntToStr((ValMaxIndex(ResultatsGoetzel)+1)*300)+' Hz'; Inc(x,buffsize); Inc(T); end; end; end.
La deuxième unité (pour le chargement du fichier wav)
Essaies et dis moi si tu obtiens quelque chose
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 unit Unit2; interface type TCCArray=array of array of cardinal; TBBArray=array of array of byte; TWWArray=array of array of Word; type TDDArray=array of array of double; function LoadWaveFile(WaveFileName:String;var Y:TDDArray;var NumChannels,BitsPerSample,SampleRate,NumSamples:Cardinal):Boolean; implementation uses mmsystem,windows,classes,sysutils,dialogs; type //Les différents headers que l'on trouve dans un fichier WAV THeaderRIFF = Packed Record ID : Array[1..4]Of Char; Taille: Cardinal; Format: Array[1..4]Of Char; end; THeaderFormat = Packed Record ID : Array[1..4]Of Char; Taille: Cardinal; Format: WORD; Mode : WORD; SRate : Cardinal; //=Fréquence d'échantillonnage BRate : Cardinal; //=Nombre d'octets pour une seconde (SRate * Mode * BPS/8) Align : WORD; BPS : WORD; //Bits Per Sample end; THeaderData = Packed Record ID : Array[1..4]Of Char; Taille: Cardinal; end; TWAVE = Packed Record RIFF: THeaderRIFF; Fmt : THeaderFormat; Data: THeaderData; end; // Reads file WaveFileName. Puts the normalized wave data in array Y and returns the sampling rate in SampleRate. // On return Y will hold a multidimensional array Y (sample,channel) of type Double, with the audio data. // Returns True, if the operation was successful, else False. function LoadWaveFile(WaveFileName:String;var Y:TDDArray;var NumChannels,BitsPerSample,SampleRate,NumSamples:Cardinal):Boolean; var WAVE:TWAVE; Stream: TFileStream; tmp : String; i,c,nn:Cardinal; ybyte:TBBArray; yword:TWWArray; begin Result:=false; Stream := TFileStream.Create(WaveFileName, fmOpenRead); Try //Lecture des trois headers Stream.Read(WAVE, 44); //Vérification de la validité du fichier. Il faut un WAVE PCM If (WAVE.RIFF.ID <> 'RIFF') or (WAVE.RIFF.Format <> 'WAVE') or (WAVE.Fmt .ID <> 'fmt ') or (WAVE.Fmt.Format <> 1) then Raise exception.Create('Le fichier choisi n''est pas un fichier WAVE PCM valide'); Result:=True; NumSamples:=Round(WAVE.Data.Taille/(WAVE.Fmt.BPS/8)/WAVE.Fmt.Mode); NumChannels:=WAVE.Fmt.Mode; SampleRate:=WAVE.Fmt.SRate; BitsPerSample:=WAVE.Fmt.BPS; SetLength(Y,NumSamples,NumChannels); //FillChar(Y,SizeOf(y),0); if BitsPerSample=8 then begin SetLength(ybyte,NumChannels,NumSamples); nn:=NumChannels*NumSamples*sizeof(byte); stream.Read(ybyte[0,0],nn); for i:= 0 to NumSamples - 1 do for c:= 0 to NumChannels - 1 do Y[i,c]:=(ybyte[c,i]-128)/128 //8 Bits/sample est non signé end else if BitsPerSample=16 then begin SetLength(yword,NumChannels,NumSamples); nn:=NumChannels*NumSamples*sizeof(Word); stream.Read(yword[0,0],nn); for i:= 0 to NumSamples - 1 do for c:= 0 to NumChannels - 1 do Y[i,c]:=(yword[c,i]/32768); end else ShowMessage(IntToStr(BitsPerSample)+' bits/sample non supporté'); finally Stream.Free; end; end; end.
Salut Waskol merci bien pour toute cette aide mais :
- j'ai des bug : je nai reussi qu'avec du 400hz ! il beug avec le 1000Hz il m'affiche du 300hz alors que c'est du1000hz
et c'est super long je ne pourrais jamais analyser en temp reel par la suite
Sinon moi je suis parti plus sur les sources de Sub0 (vuemetre) car c'est deja du temps reel et le code est plutot cour donc j'ai pu bien le comprendre maintenan ce qu'il me faut c'est reussir a trancformee la variable "MyRecData" en une frequence ce qui sera mieu que la fonction Goertzel qui fait des comparaisons donc perte de temps !
MERCI DE TON AIDE ET SOIGNE TOI BIEN !!
oui, si tu veux tester 1000Hz, il faut absolument que tu l'inclue dans les fréquences à tester... parceque là on teste 900,1200, mais pas 1000...Envoyé par jmjmjm
Oui, pendant le test, il faut à tout prix éviter d'afficher des résultats (comme je fait avec le stringgrid). La différence est flagrante !Envoyé par jmjmjm
Je pense effectivement que c'est la meilleure approche, il va falloir que tu passe par une Transformée de Fourrier Rapide (ou FFT); plus haut dans nos post, je t'ai mis du code avec le spectrogramme.Envoyé par jmjmjm
Merci à toi, si j'ai du neuf je te fait signeEnvoyé par jmjmjm
oui en effet c'est ce que j'ai commencer a regarder la FFT !!
Merci pour tout
Justement, c'est là que mon unité "spectre.pas" arrive !maintenan ce qu'il me faut c'est reussir a trancformee la variable "MyRecData" en une frequence ce qui sera mieu que la fonction Goertzel qui fait des comparaisons donc perte de temps !
En attendant que je la retrouve, regarde si ça fonctionne avec la démo suivante. Il s'agit d'un enregistreur Wav direct-to-disk avec un affichage des fréquences en temps réel (vumètre à barres). Note : Il n'y a pas besoin de lancer l'enregistrement pour voir le spectre :
http://sub0.developpez.com/delphi/exe/HDRec12.zip
ps: Je me suis servi de la formule donnée par Phuphus dans le sujet suivant (délesté hélas, je n'ai pu récupérer que cette page) :
http://sub0.developpez.com/delphi/topic.htm
Si cela fonctionne, je te donnerais mon unité, facile à intégrer à partir du projet du vumètre.
à+
si on peut extraire de ton vumetre les frequences qui ont la valeur la plus haute c'est ce qu'il me faudrai J'espere que tu vas retrouver ton unité
Tu as peut-être de la chance.
Voici mon unité "spectre.pas" qui permet de dessiner un vumètre à barres dans le canvas d'un grand TLabel en utilisant le buffer de données du vumètre. J'espère que tu ne galèreras pas trop pour l'intégrer. Cela dit, j'ai vraiment optimisé ce code, c'est super simple à utiliser, ya que 3 fonctions. Voici la source, 90 lignes de code :
http://sub0.developpez.com/delphi/Spectre.pas
Tu verras que tu peux choisir la plage des fréquences à afficher (tableau de constantes Rfreq).
• createapod sert à initialiser la fonction.
• GetSpectreRec retourne l'intensité de la fréquence se trouvant dans le tableau Rfreq indéxée par xfi
• OscilloscopeRec est un exemple d'utilisation de la fonction GetSpectreRec.
Le paramètre Data correspond aux données du vumètre au format 8bits mono 10kHz (constante FreqBufSize).
à+
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