Tristan Matthews | 0a329cc | 2013-07-17 13:20:14 -0400 | [diff] [blame] | 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 > N2/2 |
| 45 | b1 = b1-N2; |
| 46 | end |
| 47 | [a,b2] = max(corr2); |
| 48 | if b2 > N2/2 |
| 49 | b2 = b2-N2; |
| 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); |