1function outStruct = parse_delay_file(file)
2
3fid = fopen(file, 'rb');
4if fid == -1
5    error('Cannot open file %s', file);
6end
7
8textline = fgetl(fid);
9if ~strncmp(textline, '#!NetEQ_Delay_Logging', 21)
10    error('Wrong file format');
11end
12
13ver = sscanf(textline, '#!NetEQ_Delay_Logging%d.%d');
14if ~all(ver == [2; 0])
15    error('Wrong version of delay logging function')
16end
17
18
19start_pos = ftell(fid);
20fseek(fid, -12, 'eof');
21textline = fgetl(fid);
22if ~strncmp(textline, 'End of file', 21)
23    error('File ending is not correct. Seems like the simulation ended abnormally.');
24end
25
26fseek(fid,-12-4, 'eof');
27Npackets = fread(fid, 1, 'int32');
28fseek(fid, start_pos, 'bof');
29
30rtpts = zeros(Npackets, 1);
31seqno = zeros(Npackets, 1);
32pt = zeros(Npackets, 1);
33plen = zeros(Npackets, 1);
34recin_t = nan*ones(Npackets, 1);
35decode_t = nan*ones(Npackets, 1);
36playout_delay = zeros(Npackets, 1);
37optbuf = zeros(Npackets, 1);
38
39fs_ix = 1;
40clock = 0;
41ts_ix = 1;
42ended = 0;
43late_packets = 0;
44fs_now = 8000;
45last_decode_k = 0;
46tot_expand = 0;
47tot_accelerate = 0;
48tot_preemptive = 0;
49
50while not(ended)
51    signal = fread(fid, 1, '*int32');
52    
53    switch signal
54        case 3 % NETEQ_DELAY_LOGGING_SIGNAL_CLOCK
55            clock = fread(fid, 1, '*float32');
56            
57            % keep on reading batches of M until the signal is no longer "3"
58            % read int32 + float32 in one go
59            % this is to save execution time
60            temp = [3; 0];
61            M = 120;
62            while all(temp(1,:) == 3)
63                fp = ftell(fid);
64                temp = fread(fid, [2 M], '*int32');
65            end
66            
67            % back up to last clock event
68            fseek(fid, fp - ftell(fid) + ...
69                (find(temp(1,:) ~= 3, 1 ) - 2) * 2 * 4 + 4, 'cof');
70            % read the last clock value
71            clock = fread(fid, 1, '*float32');
72            
73        case 1 % NETEQ_DELAY_LOGGING_SIGNAL_RECIN
74            temp_ts = fread(fid, 1, 'uint32');
75            
76            if late_packets > 0
77                temp_ix = ts_ix - 1;
78                while (temp_ix >= 1) && (rtpts(temp_ix) ~= temp_ts)
79                    % TODO(hlundin): use matlab vector search instead?
80                    temp_ix = temp_ix - 1;
81                end
82                
83                if temp_ix >= 1
84                    % the ts was found in the vector
85                    late_packets = late_packets - 1;
86                else
87                    temp_ix = ts_ix;
88                    ts_ix = ts_ix + 1;
89                end
90            else
91                temp_ix = ts_ix;
92                ts_ix = ts_ix + 1;
93            end
94            
95            rtpts(temp_ix) = temp_ts;
96            seqno(temp_ix) = fread(fid, 1, 'uint16');
97            pt(temp_ix) = fread(fid, 1, 'int32');
98            plen(temp_ix) = fread(fid, 1, 'int16');
99            recin_t(temp_ix) = clock;
100            
101        case 2 % NETEQ_DELAY_LOGGING_SIGNAL_FLUSH
102            % do nothing
103            
104        case 4 % NETEQ_DELAY_LOGGING_SIGNAL_EOF
105            ended = 1;
106            
107        case 5 % NETEQ_DELAY_LOGGING_SIGNAL_DECODE
108            last_decode_ts = fread(fid, 1, 'uint32');
109            temp_delay = fread(fid, 1, 'uint16');
110            
111            k = find(rtpts(1:(ts_ix - 1))==last_decode_ts,1,'last');
112            if ~isempty(k)
113                decode_t(k) = clock;
114                playout_delay(k) = temp_delay + ...
115                    5 *  fs_now / 8000; % add overlap length
116                last_decode_k = k;
117            end
118            
119        case 6 % NETEQ_DELAY_LOGGING_SIGNAL_CHANGE_FS
120            fsvec(fs_ix) = fread(fid, 1, 'uint16');
121            fschange_ts(fs_ix) = last_decode_ts;
122            fs_now = fsvec(fs_ix);
123            fs_ix = fs_ix + 1;
124            
125        case 7 % NETEQ_DELAY_LOGGING_SIGNAL_MERGE_INFO
126            playout_delay(last_decode_k) = playout_delay(last_decode_k) ...
127                + fread(fid, 1, 'int32');
128            
129        case 8 % NETEQ_DELAY_LOGGING_SIGNAL_EXPAND_INFO
130            temp = fread(fid, 1, 'int32');
131            if last_decode_k ~= 0
132                tot_expand = tot_expand + temp / (fs_now / 1000);
133            end                
134            
135        case 9 % NETEQ_DELAY_LOGGING_SIGNAL_ACCELERATE_INFO
136            temp = fread(fid, 1, 'int32');
137            if last_decode_k ~= 0
138                tot_accelerate = tot_accelerate + temp / (fs_now / 1000);
139            end                
140
141        case 10 % NETEQ_DELAY_LOGGING_SIGNAL_PREEMPTIVE_INFO
142            temp = fread(fid, 1, 'int32');
143            if last_decode_k ~= 0
144                tot_preemptive = tot_preemptive + temp / (fs_now / 1000);
145            end                
146            
147        case 11 % NETEQ_DELAY_LOGGING_SIGNAL_OPTBUF
148            optbuf(last_decode_k) = fread(fid, 1, 'int32');
149            
150        case 12 % NETEQ_DELAY_LOGGING_SIGNAL_DECODE_ONE_DESC
151            last_decode_ts = fread(fid, 1, 'uint32');
152            k = ts_ix - 1;
153            
154            while (k >= 1) && (rtpts(k) ~= last_decode_ts)
155                % TODO(hlundin): use matlab vector search instead?
156                k = k - 1;
157            end
158            
159            if k < 1
160                % packet not received yet
161                k = ts_ix;
162                rtpts(ts_ix) = last_decode_ts;
163                late_packets = late_packets + 1;
164            end
165            
166            decode_t(k) = clock;
167            playout_delay(k) = fread(fid, 1, 'uint16') + ...
168                5 *  fs_now / 8000; % add overlap length
169            last_decode_k = k;
170             
171    end
172    
173end
174
175
176fclose(fid);
177
178outStruct = struct(...
179    'ts', rtpts, ...
180    'sn', seqno, ...
181    'pt', pt,...
182    'plen', plen,...
183    'arrival', recin_t,...
184    'decode', decode_t,...
185    'fs', fsvec(:),...
186    'fschange_ts', fschange_ts(:),...
187    'playout_delay', playout_delay,...
188    'tot_expand', tot_expand,...
189    'tot_accelerate', tot_accelerate,...
190    'tot_preemptive', tot_preemptive,...
191    'optbuf', optbuf);
192