ok, du bekommst dein Signal mit 44Khz gesampelt. Bei einer Frequenz von 1800Hz, Rechteck, müsst du also eine Variable von -1 auf +1 alle 44000/1800 Samples negieren. So einfach und fertig ist unser Referenztakt von 1.8Khz. Nun das um 90Grad Phasenverschobene Signal: das wäre 1/4 an Takten verzögert, also 44000/1800 = 24.4 / 4 = 6.1 Samples verzögert.
Nun machst du folgendes: Eine Variable die -1 oder +1 enthalten kann. Du multiplizierst dein aktuelles Sample mit dieser Variablen und addierst diesen Wert zu einem Akkumulator = Variable = X. Nach exakt 24 Samples negierst du diese Variable. Nach 48 Samples haben wir ja eine komplette Welle der 1.8KHz durch und führestens zu diesem Zeitpunkt können wir den Akkumulator auswerten. Normalerweise macht man dies aber so das man auf merheren Wellen ausrichtet, also zb. nach 48*10 Samples, was dann 10 Schwingungen a 1.8KHz wären. Das gleiche machst du mit einem Akumulator Y für die Phase. Wieder eine Variable mit -1,+1 aber diesesmal 6 Samples später negiert. Nun wieder Akkumulator Y die Summe aus -1,+1 * Sample addiert. Nach zb. 48*10 Samples werden die Akkumulatoren ausgewertet. r := Sqrt(X^2 + Y^2). R ist dann ein Wert der die Abhängigeit=Übereinstimung unserer Refernezfrequenz zum Inputsignal darstellt. Je höher dieser Wert ist desto mehr Anteile der 1.8Khz sind im Signal.
Gut, Nachteil dabei ist das wir immer erst nach zb. 48*10 Samples einen Wert ermiteln und dieser NICHT fließend ist. Aber auch das ist möglich. Wir nehmen einen Filter wie bei Durschnittsberechnungen möglich. Denn im Grunde genommen berehcnen wir ja nur den Durchschnitt von 480 Samples die aber im Takt von 1.8Khz ständig negiert werden.
Stelle es dir vor wie ein Gleichrichter der enen Sinus gleichrichtet. Nur das unser Gleichrichter exakt im Takt von 1.8KHz gleichrichtet. Ist das Input-Rechecksignal exakt synchron zu 1.8Khz so entsteht eine Gleichspannung, da ja nun alle negativen Halbwellen des Sinus negiert wurden. Sieht dann aus wie ein Pulsirendes Signal, aber immer im positiven Bereich.
Nun verschieden wir unseren 1.8Khz Takt um 90 Grad. Das dadurch entstehende Signal zeigt uns ob wir in der Phase synchron sind. Je geringer dieser Wert also ist um so synchroner gleichrichten wir das Sgnal, um so exakter sind wir Phasensynchron mit unserem Refernezsignal zum Inputsignal.
Je länger deine Samplingphase ist (48 * 10) um so kleinere Signal kannst du detektieren. Denn diese Methode hat den Vorteil das du selbst aus einem Rauschsignal das unser Nutzsignal enthält dieses detektieren kanst. Du kanst davon ausgehen das alle heutigen Hochfrequenzverfahren auf dieser Idee basieren, GPS, GSM usw. wären ohne garnicht denkbar.
Damit du dein Signal fließend auswerten kannst benutzt man einen Ring-Buffer. In unserem Falle zb. 48*10=480 Werte groß. Über diese 480 Werte berechnet du die Summe zu unserem 1.8Khz Takt. Diese Summe in einer Variablen gespeichert, sie ist ja Akkumulator X. Bei einem neuen Sample subtrahierst du das älteste Sample im Ringbuffer vom Akkumulator und addierst das bearbeite Sample dazu. Dieses Speicherst du im Ringbuffer als letzten Wert.
Der Akkumulator reprsentiert also die summme der letzten 480 Samples, kontinuierlich und im RingBuffer stehen die letzten 480 Werte die im Akkumulator addiert wurden. In unserem Falle also die Samples multipliziert mit (-1,+1) im Takt unserer 1.8Khz.
Da du aber sowieso ein WAV als Input hast benötigst du keinen RingBuffer mehr. Stattdessen wissen wir ja das das 480'te letzte Sample exakt synchon zu unseren 1.8KHz sind. Wir müssen also nur dieses Sample ebenfalls mit unsere Refernezfrequenzvariablen die alle 48 Samples negiert wird ausrechnen un vom Akkumulator X subtrahieren (rausrechnen). Das aktuelle Sample wird danach ebenfalls mit (-1,+1) multpiliziert und auf den Akkumulator addiert.
Pseudcode
Delphi-Quellcode:
var
Samples: array of SmallInt;
ProcessSample;
var
r: Double;
aX,aY: Double;
rX,rY: Integer;
cX,cY: Integer;
begin
aX := 0;
aY := 0;
rX := -1;
rY := -1;
cX := 0;
cY := 11;
for I := 44 to High(Samples) do
begin
aX := aX - Samples[I - 44] * rX;
aY := aY - Samples[I - 44] * rY;
aX := aX + Samples[I] * rX;
aY := aY + Samples[I] * rY;
Inc(cX);
if cX >= 22 then
begin
cX := 0;
rX := -rX;
end;
Inc(cY);
if cY >= 22 then
begin
cY := 0;
rY := -rY;
end;
r := Sqrt(Sqr(aX) + Sqr(aY));
end;
end;
Mit obigem Code würde man auf 44000/44 = 1Khz filtern. Die Phasenverschiebung unseres Referenztaktes wird durch die 90 Grad Verschiebung und der Formel r = Sqrt(x^2 + y^2) beseitigt. Es ist also unwichtig wann du anfängst deine Samples auszuwerten (bei welchen Inxdex) bzw. wie die Phasenverschiebung des Inputsignales ist. Und wie man sieht hat dieser Code zwei Vorteile
1.) kontinuierliche Auswertung ist möglich, maximal eine Welle später als unsere Referenzfrequenz
2.) die Laufzeit sollte wesentlich höher sein als eine FFT
Statt wie oben mit einem Rechtecksignal zu arbeiten kannst du auch ein Sinus als Referenz benutzen, ist aber nicht notwendig, erhöht nur die Genauigkeit wenn unser Signal ebenfalls mit Sinus FSK moduliert wurde.
Gruß Hagen
PS: Tippfehler gehören euch, ich hasse Laptop Tastaturen.