uses files instead of vars.
[speexdsp.git] / libspeex / echo_diagnostic.m
1 % Attempts to diagnose AEC problems from recorded samples
2 %
3 % out = echo_diagnostic(rec_file, play_file, out_file, tail_length)
4 %
5 % Computes the full matrix inversion to cancel echo from the 
6 % recording 'rec_file' using the far end signal 'play_file' using 
7 % a filter length of 'tail_length'. The output is saved to 'out_file'.
8 function out = echo_diagnostic(rec_file, play_file, out_file, tail_length)
9
10 F=fopen(rec_file,'rb');
11 rec=fread(F,Inf,'short');
12 fclose (F);
13 F=fopen(play_file,'rb');
14 play=fread(F,Inf,'short');
15 fclose (F);
16
17 rec = [rec; zeros(1024,1)];
18 play = [play; zeros(1024,1)];
19
20 N = length(rec);
21 corr = real(ifft(fft(rec).*conj(fft(play))));
22 acorr = real(ifft(fft(play).*conj(fft(play))));
23
24 [a,b] = max(corr);
25
26 if b > N/2
27       b = b-N;
28 end
29 printf ("Far end to near end delay is %d samples\n", b);
30 if (b > .3*tail_length)
31       printf ('This is too much delay, try delaying the far-end signal a bit\n');
32 else if (b < 0)
33       printf ('You have a negative delay, the echo canceller has no chance to cancel anything!\n');
34    else
35       printf ('Delay looks OK.\n');
36       end
37    end
38 end
39 N2 = round(N/2);
40 corr1 = real(ifft(fft(rec(1:N2)).*conj(fft(play(1:N2)))));
41 corr2 = real(ifft(fft(rec(N2+1:end)).*conj(fft(play(N2+1:end)))));
42
43 [a,b1] = max(corr1);
44 if b1 > N/2
45       b1 = b1-N;
46 end
47 [a,b2] = max(corr2);
48 if b2 > N/2
49       b2 = b2-N;
50 end
51 drift = (b1-b2)/N2;
52 printf ('Drift estimate is %f%% (%d samples)\n', 100*drift, b1-b2);
53 if abs(b1-b2) < 10
54    printf ('A drift of a few (+-10) samples is normal.\n');
55 else
56    if abs(b1-b2) < 30
57       printf ('There may be (not sure) excessive clock drift. Is the capture and playback done on the same soundcard?\n');
58    else
59       printf ('Your clock is drifting! No way the AEC will be able to do anything with that. Most likely, you''re doing capture and playback from two different cards.\n');
60       end
61    end
62 end
63 acorr(1) = .001+1.00001*acorr(1);
64 AtA = toeplitz(acorr(1:tail_length));
65 bb = corr(1:tail_length);
66 h = AtA\bb;
67
68 out = (rec - filter(h, 1, play));
69
70 F=fopen(out_file,'w');
71 fwrite(F,out,'short');
72 fclose (F);