Hey I'm trying to open .c3d files by the means of the fread function The problem I have is when searching the first frame and the last frame of the file with fread(fid,1,'int16') with fid = 8; If I do it with some non heavy files, I got a startframe = 1 and a endframe =~ 26000 and the script works but if I do it with more heavy files, then I got an enframe =~ -12000 which makes the script wrong and me angry ;) Sure someone has an idea... Thanks in advance!
No products are associated with this question.
When the C3D file format has been invented, large measurement files have been rare and int16 seemed to be a valid range for the number of frames. Many modern software packages use uint16 instead, because a negative number of frames is not valid at all.
I use this to import the header of C3Ds:
I8 = 'int8'; I16 = 'int16'; U16 = 'uint16'; % Signed is not meaningful! F32 = 'float32';
% Spool to the beginning: fseek(FID, 0, 'bof');
% Reading record number of parameter section: Head.ParamRec = fread(FID, 1, I8); MagicKey = fread(FID, 1, I8); if isequal(MagicKey, 80) == 0 error(['JSimon:', mfilename, ':BadMagicKey'], 'Bad magic key: %d', MagicKey); end
% Getting all the necessary parameters from the header record Head.nCoor = fread(FID, 1, U16); % number of trajectories Head.AnalogChunk = fread(FID, 1, U16); % analog values per video frame Head.iFrame = fread(FID, 1, U16); % index of first video frame Head.fFrame = fread(FID, 1, U16); % index of last video frame Head.MaxGap = fread(FID, 1, U16); % max allowed interpolation gaps Scale = fread(FID, 1, F32); % scale integers to ref. units Head.DataRec = fread(FID, 1, U16); % 1st record of data section Head.AnalogRate = fread(FID, 1, U16); % analog samples per video frame Head.VideoFreq = fread(FID, 1, F32); % frequency of video data
% If scale is negative, the data is stored in float format: Head.FloatMode = (Scale < 0.0); Head.Scale = abs(Scale);
% Number of frames: Head.nFrame = Head.fFrame - Head.iFrame + 1;
% Number of analog channels (FRC + EMG + ?): if Head.AnalogRate % Avoid division by zero: Head.nAnalog = round(Head.AnalogChunk / Head.AnalogRate); else Head.nAnalog = 0; end
But note, that today even the range of UINT16 is small and e.g. Vicon software write the actual number of frames to the parameter section as TRIAL.ACTUAL_START_FIELD and TRIAL.ACTUAL_END_FIELD. Then we need to modify the values:
End_Field2 = TRIAL.ACTUAL_END_FIELD; % Or how ever you obtain parameters Start_Field2 = TRIAL.ACTUAL_START_FIELD;
End_Field = End_Field2(1) + 65536 * End_Field2(2); if ~isequal(End_Field, Head.fFrame) if Head.fFrame ~= 65535 warning(['GetC3D:', mfilename, ':Unexpected_nFrame'], ... 'Long C3D, but [Head.fFrame] is not 65535?!'); end
Start_Field = Start_Field2(1) + 65536 * Start_Field2(2); Head.iFrame = Start_Field; Head.fFrame = End_Field; Head.nFrame = End_Field - Start_Field + 1; end