Hi,
I got stuck a bit in the following problem and I need an advice. You here in the forum seem to have more knowledge about these things. I would like compare two audio streams in order to check the latency. They do not have a unique PCR which means I have to compare them otherwise. They are also not made by the same encoder so I can not compare the byte stream. I probably have to write an FFT incl. a buffer for both streams and check for similarities. Are there some known algorithms or solutions how to handle this?
I did something like this, but this seem to be not correct:
unit UMainThread;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, SyncObjs, Bass;
const
BUFFER_SIZE = 4096; // Größe des Puffers für die Sample-Arrays
SAMPLE_COUNT = 16384; // Anzahl der Samples pro Aufzeichnung
type
TAutoCorrelation = array[0..SAMPLE_COUNT - 1] of single;
TStreamSyncThread = class(TThread)
private
FStream1, FStream2: HSTREAM; // Handles für die beiden Streams
FShift: integer; // Versatz zwischen den Streams in Samples
FLock: TCriticalSection;
function GetShift: integer;
protected
procedure Execute; override;
public
constructor Create(Stream1, Stream2: HSTREAM);
destructor Destroy; override;
property Shift: integer read GetShift;
end;
implementation
constructor TStreamSyncThread.Create(Stream1, Stream2: HSTREAM);
begin
inherited Create(False);
FStream1 := Stream1;
FStream2 := Stream2;
FLock := TCriticalSection.Create;
end;
destructor TStreamSyncThread.Destroy;
begin
Terminate;
WaitFor;
FLock.Leave;
inherited;
end;
procedure TStreamSyncThread.Execute;
var
i, j: integer;
Samples1, Samples2: array[0..BUFFER_SIZE - 1] of single; // Puffer für die Samples
AutoCorr: TAutoCorrelation; // Array zum Speichern des Autokorrelation-Ergebnisses
MaxCorr: single; // Maximale Korrelation
MaxCorrIndex: integer; // Index der maximalen Korrelation
SampleCount: DWord;
begin
while not Terminated do
begin
SampleCount := BASS_ChannelGetData(FStream1, @Samples1[0],
BUFFER_SIZE * SizeOf(single) or BASS_DATA_FLOAT) div sizeof(single);
BASS_ChannelGetData(FStream2, @Samples2[0], BUFFER_SIZE *
SizeOf(single) or BASS_DATA_FLOAT);
// Berechne die Autokorrelation der Samples
for i := 0 to High(AutoCorr) do
begin
AutoCorr := 0;
for j := 0 to SampleCount - 1 do
AutoCorr := AutoCorr + Samples1[j] * Samples2[(int64(j) + i) mod SampleCount];
end;
// Bestimme den Index mit der maximalen Korrelation
MaxCorr := 0;
MaxCorrIndex := 0;
for i := 0 to High(AutoCorr) do
begin
if Autocorr > MaxCorr then
begin
MaxCorr := Autocorr;
MaxCorrIndex := i;
end;
end;
FLock.Enter;
try
FShift := MaxCorrIndex;
finally
FLock.Leave;
end;
sleep(1000);
end;
end;
function TStreamSyncThread.GetShift: integer;
begin
FLock.Enter;
try
Result := FShift;
finally
FLock.Leave;
end;
end;
end.
Cheers
Peter