wolffd@0: function [data,Fs,nBits,formChunk] = aiffread(filePath,indexRange) wolffd@0: %AIFFREAD Read AIFF (Audio Interchange File Format) sound file. wolffd@0: % Y = AIFFREAD(FILE) reads an AIFF file specified by the string FILE, wolffd@0: % returning the sampled data in Y. The ".aif" extension is appended if no wolffd@0: % extension is given. wolffd@0: % wolffd@0: % [Y,FS,NBITS,CHUNKDATA] = AIFFREAD(FILE) returns the sample rate (FS) in wolffd@0: % Hertz, the number of bits per sample (NBITS) used to encode the data in wolffd@0: % the file, and a complete structure of the chunk data (CHUNKDATA) wolffd@0: % contained in the AIFF file (minus the actual audio data returned in Y). wolffd@0: % See below for a description of CHUNKDATA. wolffd@0: % wolffd@0: % [...] = AIFFREAD(FILE,N) returns only the first N samples from each wolffd@0: % channel in the file. wolffd@0: % wolffd@0: % [...] = AIFFREAD(FILE,[N1 N2]) returns only samples N1 through N2 from wolffd@0: % each channel in the file. wolffd@0: % wolffd@0: % [SIZ,...] = AIFFREAD(FILE,'size') returns the size of the audio data wolffd@0: % contained in the file in place of the actual audio data, where wolffd@0: % SIZ = [nSampleFrames nChannels]. wolffd@0: % wolffd@0: %-NOTES-------------------------------------------------------------------- wolffd@0: % wolffd@0: % A note on compressed files: wolffd@0: % wolffd@0: % Both AIFF and AIFC/AIFF-C (compressed) file types can be read by wolffd@0: % AIFFREAD, but the data returned for AIFC/AIFF-C files will be the wolffd@0: % raw, compressed data (i.e. AIFFREAD loads the data from the file wolffd@0: % without modification). Currently, since there are many compression wolffd@0: % formats, it is the responsibility of the user to uncompress the wolffd@0: % sound data using parameters defined in the COMM chunk (contained in wolffd@0: % the returned CHUNKDATA structure). When loading AIFC/AIFF-C files, wolffd@0: % any optional numerical subranges are ignored and the entire set of wolffd@0: % compressed data is returned as a column vector of signed bytes wolffd@0: % (INT8 type). wolffd@0: % wolffd@0: % A note on the CHUNKDATA structure: wolffd@0: % wolffd@0: % The CHUNKDATA structure has the following fields: wolffd@0: % wolffd@0: % -'chunkID': The 4-character ID for the chunk. This will always be wolffd@0: % the string 'FORM'. wolffd@0: % -'chunkSize': The size (in bytes) of the remaining data in the wolffd@0: % file. wolffd@0: % -'formType': A 4-character string for the file type that should wolffd@0: % be either 'AIFF' or 'AIFC'. wolffd@0: % -'chunkArray': An array of structures, one entry for every chunk wolffd@0: % that is in the file (not counting this parent FORM wolffd@0: % chunk). The fields of this structure are: wolffd@0: % -'chunkID': The 4-character ID for the chunk. wolffd@0: % -'chunkSize': The size (in bytes) of the wolffd@0: % remaining data in the chunk. wolffd@0: % -'chunkData': A structure of data for the wolffd@0: % chunk. The form of this data for wolffd@0: % a given chunkID can be found at wolffd@0: % the links given below for the wolffd@0: % file format standards. wolffd@0: % wolffd@0: % The data portion of certain chunks may not have a clearly defined wolffd@0: % format, or that format may be dependent on the implementation or wolffd@0: % application that will be using the data. In such cases, the data wolffd@0: % returned for that chunk in the CHUNKDATA structure will be in a raw wolffd@0: % format (vectors of signed or unsigned 8-bit integers) and it will be wolffd@0: % up to the user/application to parse and format this data correctly. wolffd@0: % The following is a list of such AIFF/AIFF-C chunks: wolffd@0: % wolffd@0: % -Audio Recording Chunk (chunkID = 'AESD'): The chunkData wolffd@0: % structure has one field 'aesChannelStatusData' that stores a wolffd@0: % column vector of 24 8-bit unsigned integers. wolffd@0: % -Application Specific Chunk (chunkID = 'APPL'): The chunkData wolffd@0: % structure has two fields. 'applicationSignature' stores a wolffd@0: % 4-character string identifying the application. 'data' stores a wolffd@0: % column vector of 8-bit signed integers. wolffd@0: % -MIDI Data Chunk (chunkID = 'MIDI'): The chunkData structure has wolffd@0: % one field 'midiData' that stores a column vector of 8-bit wolffd@0: % unsigned integers. wolffd@0: % -Sound Accelerator (SAXEL) Chunk (chunkID = 'SAXL'): There is no wolffd@0: % finalized format for Saxel chunks, so the chunkData structure wolffd@0: % follows the draft format given in Appendix D of the AIFF-C wolffd@0: % standard. wolffd@0: % wolffd@0: % Description for the AIFF standard can be found here: wolffd@0: % wolffd@0: % http://muratnkonar.com/aiff/index.html wolffd@0: % wolffd@0: % Descriptions for the AIFC/AIFF-C standard can be found here: wolffd@0: % wolffd@0: % http://www.cnpbagwell.com/aiff-c.txt wolffd@0: % http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/Docs/... wolffd@0: % AIFF-C.9.26.91.pdf wolffd@0: wolffd@0: % Author: Ken Eaton wolffd@0: % Last modified: 3/17/09 wolffd@0: %-------------------------------------------------------------------------- wolffd@0: wolffd@0: % Initializations: wolffd@0: wolffd@0: aiffChunkPrecedence = {'COMM' 'SSND' 'MARK' 'INST' 'COMT' 'NAME' ... wolffd@0: 'AUTH' '[c] ' 'ANNO' 'AESD' 'MIDI' 'APPL'}; wolffd@0: aiffChunkLimits = [1 1 1 1 1 1 1 1 inf 1 inf inf]; wolffd@0: aifcChunkPrecedence = {'FVER' 'COMM' 'INST' 'SAXL' 'COMT' 'MARK' ... wolffd@0: 'SSND' 'NAME' 'AUTH' '[c] ' 'ANNO' 'AESD' ... wolffd@0: 'MIDI' 'APPL'}; wolffd@0: aifcChunkLimits = [1 1 1 inf 1 1 1 1 1 1 inf 1 inf inf]; wolffd@0: fid = -1; wolffd@0: wolffd@0: % Check the number of input arguments: wolffd@0: wolffd@0: switch nargin, wolffd@0: case 0, wolffd@0: error(error_message('notEnoughInputs')); wolffd@0: case 1, wolffd@0: indexRange = [1 inf]; wolffd@0: end wolffd@0: wolffd@0: % Check the file name input argument: wolffd@0: wolffd@0: if ~ischar(filePath), wolffd@0: error(error_message('badArgumentType','File name','char')); wolffd@0: end wolffd@0: [filePath,fileName,fileExtension] = fileparts(filePath); wolffd@0: if isempty(fileExtension), wolffd@0: fileExtension = '.aif'; wolffd@0: end wolffd@0: if ~any(strcmpi(fileExtension,{'.aif' '.afc' '.aiff' '.aifc'})), wolffd@0: error(error_message('unknownExtension',fileExtension)); wolffd@0: end wolffd@0: wolffd@0: % Check the optional input argument: wolffd@0: wolffd@0: if isnumeric(indexRange), % Numeric range specification wolffd@0: wolffd@0: indexRange = double(indexRange); wolffd@0: nRange = numel(indexRange); wolffd@0: if (nRange > 2) || any(indexRange < 1) || any(isnan(indexRange)), wolffd@0: error(error_message('badIndexValue')); wolffd@0: end wolffd@0: indexRange = [ones(nRange ~= 2) round(indexRange) inf(nRange == 0)]; wolffd@0: wolffd@0: elseif ischar(indexRange), % Specification for returning just the size wolffd@0: wolffd@0: if ~strncmpi(indexRange,'size',numel(indexRange)), wolffd@0: error(error_message('invalidString')); wolffd@0: end wolffd@0: indexRange = []; wolffd@0: wolffd@0: else % Invalid input wolffd@0: wolffd@0: error(error_message('badArgumentType','Optional argument',... wolffd@0: 'numeric or char')); wolffd@0: wolffd@0: end wolffd@0: wolffd@0: % Check that the file exists and can be opened: wolffd@0: wolffd@0: fid = fopen(fullfile(filePath,[fileName fileExtension]),'r','b'); wolffd@0: if fid == -1, wolffd@0: error(error_message('invalidFile',[fileName fileExtension])); wolffd@0: end wolffd@0: wolffd@0: % Initialize formChunk structure: wolffd@0: wolffd@0: formChunk = struct('chunkID',[],'chunkSize',[],'formType',[],... wolffd@0: 'chunkArray',[]); wolffd@0: wolffd@0: % Read FORM chunk data: wolffd@0: wolffd@0: formChunk.chunkID = read_text(fid,4); wolffd@0: if ~strcmp(formChunk.chunkID,'FORM'), wolffd@0: error(error_message('invalidFileFormat',fileExtension)); wolffd@0: end wolffd@0: formChunk.chunkSize = fread(fid,1,'int32'); wolffd@0: formType = read_text(fid,4); wolffd@0: if ~any(strcmp(formType,{'AIFF' 'AIFC'})), wolffd@0: error(error_message('invalidFileFormat',fileExtension)); wolffd@0: end wolffd@0: formChunk.formType = formType; wolffd@0: wolffd@0: % Since the order of chunks is not guaranteed, first skip through the wolffd@0: % file and read just the chunkIDs and chunkSizes: wolffd@0: wolffd@0: iChunk = 0; wolffd@0: chunkIDArray = {}; wolffd@0: chunkSizeArray = {}; wolffd@0: chunkDataIndex = []; wolffd@0: nextChunkID = read_text(fid,4); wolffd@0: while ~feof(fid), wolffd@0: iChunk = iChunk+1; wolffd@0: chunkIDArray{iChunk} = nextChunkID; wolffd@0: chunkSize = fread(fid,1,'int32'); wolffd@0: chunkSizeArray{iChunk} = chunkSize; wolffd@0: chunkDataIndex(iChunk) = ftell(fid); wolffd@0: fseek(fid,chunkSize+rem(chunkSize,2),'cof'); wolffd@0: nextChunkID = read_text(fid,4); wolffd@0: end wolffd@0: wolffd@0: % Check for the presence of required chunks: wolffd@0: wolffd@0: if ~ismember('COMM',chunkIDArray), wolffd@0: error(error_message('missingChunk','COMM',formType)); wolffd@0: end wolffd@0: if strcmp(formType,'AIFC') && ~ismember('FVER',chunkIDArray), wolffd@0: error(error_message('missingChunk','FVER',formType)); wolffd@0: end wolffd@0: wolffd@0: % Check for unknown chunks and order chunks based on chunk precedence: wolffd@0: wolffd@0: if strcmp(formType,'AIFF'), wolffd@0: [isChunk,orderIndex] = ismember(chunkIDArray,aiffChunkPrecedence); wolffd@0: else wolffd@0: [isChunk,orderIndex] = ismember(chunkIDArray,aifcChunkPrecedence); wolffd@0: end wolffd@0: if ~all(isChunk), wolffd@0: unknownChunks = [chunkIDArray(~isChunk); ... wolffd@0: repmat({', '},1,sum(~isChunk)-1) {'.'}]; wolffd@0: orderIndex = orderIndex(isChunk); wolffd@0: chunkIDArray = chunkIDArray(isChunk); wolffd@0: chunkSizeArray = chunkSizeArray(isChunk); wolffd@0: chunkDataIndex = chunkDataIndex(isChunk); wolffd@0: warning('aiffread:unknownChunk',... wolffd@0: ['The following chunk IDs are unknown for an ' formType ... wolffd@0: ' file and will be ignored: ' unknownChunks{:}]); wolffd@0: end wolffd@0: [index,orderIndex] = sort(orderIndex); wolffd@0: chunkIDArray = chunkIDArray(orderIndex); wolffd@0: chunkSizeArray = chunkSizeArray(orderIndex); wolffd@0: chunkDataIndex = chunkDataIndex(orderIndex); wolffd@0: wolffd@0: % Check for chunks that should not appear more than once: wolffd@0: wolffd@0: index = unique(index(diff(index) < 1)); wolffd@0: if strcmp(formType,'AIFF'), wolffd@0: repeatChunks = aiffChunkPrecedence(aiffChunkLimits(index) == 1); wolffd@0: else wolffd@0: repeatChunks = aifcChunkPrecedence(aifcChunkLimits(index) == 1); wolffd@0: end wolffd@0: if ~isempty(repeatChunks), wolffd@0: repeatChunks = [repeatChunks; ... wolffd@0: repmat({', '},1,numel(repeatChunks)-1) {'.'}]; wolffd@0: error(error_message('repeatChunk',formType,[repeatChunks{:}])); wolffd@0: end wolffd@0: wolffd@0: % Initialize chunkArray data: wolffd@0: wolffd@0: formChunk.chunkArray = struct('chunkID',chunkIDArray,... wolffd@0: 'chunkSize',chunkSizeArray,... wolffd@0: 'chunkData',[]); wolffd@0: wolffd@0: % Read the data for each chunk: wolffd@0: wolffd@0: for iChunk = 1:numel(chunkIDArray), wolffd@0: chunkData = []; wolffd@0: fseek(fid,chunkDataIndex(iChunk),'bof'); wolffd@0: switch chunkIDArray{iChunk}, wolffd@0: wolffd@0: case '[c] ', % Copyright Chunk wolffd@0: wolffd@0: chunkData.text = read_text(fid,chunkSizeArray{iChunk}); wolffd@0: wolffd@0: case 'AESD', % Audio Recording Chunk wolffd@0: wolffd@0: chunkData.aesChannelStatusData = ... wolffd@0: fread(fid,[chunkSizeArray{iChunk} 1],'*uint8'); wolffd@0: wolffd@0: case 'ANNO', % Annotation Chunk wolffd@0: wolffd@0: chunkData.text = read_text(fid,chunkSizeArray{iChunk}); wolffd@0: wolffd@0: case 'APPL', % Application Specific Chunk wolffd@0: wolffd@0: chunkData.applicationSignature = read_text(fid,4); wolffd@0: chunkData.data = fread(fid,[chunkSizeArray{iChunk}-4 1],'*int8'); wolffd@0: wolffd@0: case 'AUTH', % Author Chunk wolffd@0: wolffd@0: chunkData.text = read_text(fid,chunkSizeArray{iChunk}); wolffd@0: wolffd@0: case 'COMM', % Common Chunk wolffd@0: wolffd@0: nChannels = fread(fid,1,'int16'); wolffd@0: chunkData.nChannels = nChannels; wolffd@0: nSampleFrames = fread(fid,1,'uint32'); wolffd@0: if (nSampleFrames > 0) && ~ismember('SSND',chunkIDArray), wolffd@0: error(error_message('missingChunk','SSND',formType)); wolffd@0: end wolffd@0: chunkData.nSampleFrames = nSampleFrames; wolffd@0: nBits = fread(fid,1,'int16'); wolffd@0: chunkData.sampleSize = nBits; wolffd@0: exponent = fread(fid,1,'uint16'); wolffd@0: highMantissa = fread(fid,1,'uint32'); wolffd@0: lowMantissa = fread(fid,1,'uint32'); wolffd@0: Fs = extended2double(exponent,highMantissa,lowMantissa); wolffd@0: chunkData.sampleRate = Fs; wolffd@0: if strcmp(formType,'AIFF'), wolffd@0: compressionType = 'NONE'; wolffd@0: else wolffd@0: compressionType = read_text(fid,4); wolffd@0: chunkData.compressionType = compressionType; wolffd@0: chunkData.compressionName = read_pstring(fid); wolffd@0: end wolffd@0: wolffd@0: case 'COMT', % Comments Chunk wolffd@0: wolffd@0: nComments = fread(fid,1,'uint16'); wolffd@0: chunkData.nComments = nComments; wolffd@0: chunkData.commentArray = struct('timeStamp',cell(nComments,1),... wolffd@0: 'marker',[],'count',[],'text',[]); wolffd@0: for iComment = 1:nComments, wolffd@0: chunkData.commentArray(iComment) = read_comment(fid); wolffd@0: end wolffd@0: wolffd@0: case 'FVER', % Format Version Chunk (AIFC/AIFF-C only) wolffd@0: wolffd@0: timeStamp = fread(fid,1,'uint32'); wolffd@0: if timeStamp ~= 2726318400, wolffd@0: warning('aiffread:unknownVersion',... wolffd@0: ['File contains an unrecognized version of the ' ... wolffd@0: 'AIFC/AIFF-C standard.']); wolffd@0: end wolffd@0: chunkData.timeStamp = timeStamp; wolffd@0: wolffd@0: case 'INST', % Instrument Chunk wolffd@0: wolffd@0: chunkData.baseNote = fread(fid,1,'int8'); wolffd@0: chunkData.detune = fread(fid,1,'int8'); wolffd@0: chunkData.lowNote = fread(fid,1,'int8'); wolffd@0: chunkData.highNote = fread(fid,1,'int8'); wolffd@0: chunkData.lowVelocity = fread(fid,1,'int8'); wolffd@0: chunkData.highVelocity = fread(fid,1,'int8'); wolffd@0: chunkData.gain = fread(fid,1,'int16'); wolffd@0: chunkData.sustainLoop = read_loop(fid); wolffd@0: chunkData.releaseLoop = read_loop(fid); wolffd@0: wolffd@0: case 'MARK', % Marker Chunk wolffd@0: wolffd@0: nMarkers = fread(fid,1,'uint16'); wolffd@0: chunkData.nMarkers = nMarkers; wolffd@0: chunkData.markerArray = struct('id',cell(nMarkers,1),... wolffd@0: 'position',[],'markerName',[]); wolffd@0: for iMarker = 1:nMarkers, wolffd@0: chunkData.markerArray(iMarker) = read_marker(fid); wolffd@0: end wolffd@0: markerIDs = [chunkData.markerArray.id]; wolffd@0: if any(markerIDs < 1) || (numel(unique(markerIDs)) < nMarkers), wolffd@0: warning('aiffread:invalidMarkers',... wolffd@0: 'Invalid or repeated marker IDs were detected.'); wolffd@0: end wolffd@0: wolffd@0: case 'MIDI', % MIDI Data Chunk wolffd@0: wolffd@0: chunkData.midiData = fread(fid,[chunkSizeArray{iChunk} 1],... wolffd@0: '*uint8'); wolffd@0: wolffd@0: case 'NAME', % Name Chunk wolffd@0: wolffd@0: chunkData.text = read_text(fid,chunkSizeArray{iChunk}); wolffd@0: wolffd@0: case 'SAXL', % Sound Accelerator (SAXEL) Chunk (AIFC/AIFF-C only) wolffd@0: wolffd@0: nSaxels = fread(fid,1,'uint16'); wolffd@0: chunkData.nSaxels = nSaxels; wolffd@0: chunkData.saxelArray = struct('id',cell(nSaxels,1),'size',[],... wolffd@0: 'saxelData',[]); wolffd@0: for iSaxel = 1:nSaxels, wolffd@0: chunkData.saxelArray(iSaxel) = read_saxel(fid); wolffd@0: end wolffd@0: wolffd@0: case 'SSND', % Sound Data Chunk wolffd@0: wolffd@0: nBytes = ceil(nBits/8); wolffd@0: chunkData.offset = fread(fid,1,'uint32'); wolffd@0: chunkData.blockSize = fread(fid,1,'uint32'); wolffd@0: if isempty(indexRange), wolffd@0: data = [nSampleFrames nChannels]; wolffd@0: elseif strcmp(compressionType,'NONE'), wolffd@0: if (chunkSizeArray{iChunk}-8 ~= nChannels*nSampleFrames*nBytes), wolffd@0: error(error_message('sizeMismatch')); wolffd@0: end wolffd@0: fseek(fid,nBytes*nChannels*(indexRange(1)-1),'cof'); wolffd@0: nRead = min(indexRange(2),nSampleFrames)-indexRange(1)+1; wolffd@0: data = fread(fid,[nChannels nRead],['*bit' int2str(nBytes*8)]).'; wolffd@0: if nBits < nBytes*8, wolffd@0: data = data./(2^(nBytes*8-nBits)); wolffd@0: end wolffd@0: else wolffd@0: data = fread(fid,[chunkSizeArray{iChunk}-8 1],'*int8'); wolffd@0: end wolffd@0: wolffd@0: end wolffd@0: formChunk.chunkArray(iChunk).chunkData = chunkData; wolffd@0: end wolffd@0: wolffd@0: % Close the file: wolffd@0: wolffd@0: fclose(fid); wolffd@0: wolffd@0: %~~~Begin nested functions~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ wolffd@0: wolffd@0: %------------------------------------------------------------------------ wolffd@0: function errorStruct = error_message(errorCode,varargin) wolffd@0: % wolffd@0: % Initialize an error message (and close open files, if necessary). wolffd@0: % wolffd@0: %------------------------------------------------------------------------ wolffd@0: wolffd@0: % Close open files, if necessary: wolffd@0: wolffd@0: if ~isempty(fopen(fid)), wolffd@0: fclose(fid); wolffd@0: end wolffd@0: wolffd@0: % Initialize error message text: wolffd@0: wolffd@0: switch errorCode, wolffd@0: case 'badArgumentType', wolffd@0: errorText = [varargin{1} ' should be of type ' varargin{2} '.']; wolffd@0: case 'badIndexValue', wolffd@0: errorText = ['Index range must be specified as a scalar or ' ... wolffd@0: '2-element vector of positive, non-zero, non-NaN ' ... wolffd@0: 'values.']; wolffd@0: case 'invalidFile', wolffd@0: errorText = ['Could not open file ''' varargin{1} '''.']; wolffd@0: case 'invalidFileFormat', wolffd@0: errorText = ['Not a valid ' varargin{1} ' file.']; wolffd@0: case 'invalidString', wolffd@0: errorText = '''size'' is the only valid string argument.'; wolffd@0: case 'missingChunk', wolffd@0: errorText = ['''' varargin{1} ''' chunk is required for a ' ... wolffd@0: varargin{2} ' file.']; wolffd@0: case 'notEnoughInputs', wolffd@0: errorText = 'Not enough input arguments.'; wolffd@0: case 'repeatChunk', wolffd@0: errorText = ['The following chunk IDs should not appear more ' ... wolffd@0: 'than once in an ' varargin{1} ' file: ' varargin{2}]; wolffd@0: case 'sizeMismatch', wolffd@0: errorText = 'Data size mismatch between COMM and SSND chunks.'; wolffd@0: case 'unknownExtension', wolffd@0: errorText = ['Unknown file extension ''' varargin{1} '''.']; wolffd@0: end wolffd@0: wolffd@0: % Create error structure: wolffd@0: wolffd@0: errorStruct = struct('message',errorText,... wolffd@0: 'identifier',['aiffread:' errorCode]); wolffd@0: wolffd@0: end wolffd@0: wolffd@0: %~~~End nested functions~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ wolffd@0: wolffd@0: end wolffd@0: wolffd@0: %~~~Begin subfunctions~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ wolffd@0: wolffd@0: %-------------------------------------------------------------------------- wolffd@0: function value = extended2double(exponent,highMantissa,lowMantissa) wolffd@0: % wolffd@0: % Converts an 80-bit extended floating-point type to a double. wolffd@0: % wolffd@0: %-------------------------------------------------------------------------- wolffd@0: wolffd@0: signBit = bitand(exponent,32768); wolffd@0: exponent = bitand(exponent,32767); wolffd@0: highMantissa = bitand(highMantissa,4294967295); wolffd@0: lowMantissa = bitand(lowMantissa,4294967295); wolffd@0: if (exponent == 0) && (highMantissa == 0) && (lowMantissa == 0), wolffd@0: value = 0; wolffd@0: elseif exponent == 32767, wolffd@0: if (highMantissa > 0) || (lowMantissa > 0), wolffd@0: value = nan; wolffd@0: else wolffd@0: value = inf; wolffd@0: end wolffd@0: else wolffd@0: value = highMantissa*2^(exponent-16414)+lowMantissa*2^(exponent-16446); wolffd@0: end wolffd@0: if signBit, wolffd@0: value = -value; wolffd@0: end wolffd@0: wolffd@0: end wolffd@0: wolffd@0: %-------------------------------------------------------------------------- wolffd@0: function commentStruct = read_comment(fid) wolffd@0: % wolffd@0: % Reads a structure of comment data from a file. wolffd@0: % wolffd@0: %-------------------------------------------------------------------------- wolffd@0: wolffd@0: commentStruct = struct('timeStamp',fread(fid,1,'uint32'),... wolffd@0: 'marker',fread(fid,1,'int16'),... wolffd@0: 'count',[],'text',[]); wolffd@0: charCount = fread(fid,1,'uint16'); wolffd@0: commentStruct.count = charCount; wolffd@0: commentStruct.text = read_text(fid,charCount); wolffd@0: wolffd@0: end wolffd@0: wolffd@0: %-------------------------------------------------------------------------- wolffd@0: function loopStruct = read_loop(fid) wolffd@0: % wolffd@0: % Reads a structure of loop data from a file. wolffd@0: % wolffd@0: %-------------------------------------------------------------------------- wolffd@0: wolffd@0: loopStruct = struct('playMode',fread(fid,1,'int16'),... wolffd@0: 'beginLoop',fread(fid,1,'int16'),... wolffd@0: 'endLoop',fread(fid,1,'int16')); wolffd@0: wolffd@0: end wolffd@0: wolffd@0: %-------------------------------------------------------------------------- wolffd@0: function markerStruct = read_marker(fid) wolffd@0: % wolffd@0: % Reads a structure of marker data from a file. wolffd@0: % wolffd@0: %-------------------------------------------------------------------------- wolffd@0: wolffd@0: markerStruct = struct('id',fread(fid,1,'int16'),... wolffd@0: 'position',fread(fid,1,'uint32'),... wolffd@0: 'markerName',read_pstring(fid)); wolffd@0: wolffd@0: end wolffd@0: wolffd@0: %-------------------------------------------------------------------------- wolffd@0: function pascalString = read_pstring(fid) wolffd@0: % wolffd@0: % Reads a Pascal-style string from a file, and afterwards shifts the file wolffd@0: % pointer ahead by one byte if necessary to make the total number of bytes wolffd@0: % read an even number. wolffd@0: % wolffd@0: %-------------------------------------------------------------------------- wolffd@0: wolffd@0: charCount = fread(fid,1,'uint8'); wolffd@0: pascalString = fread(fid,[1 charCount],'int8=>char'); wolffd@0: if rem(charCount+1,2), wolffd@0: fseek(fid,1,'cof'); wolffd@0: end wolffd@0: wolffd@0: end wolffd@0: wolffd@0: %-------------------------------------------------------------------------- wolffd@0: function saxelStruct = read_saxel(fid) wolffd@0: % wolffd@0: % Reads a structure of saxel data from a file. wolffd@0: % wolffd@0: %-------------------------------------------------------------------------- wolffd@0: wolffd@0: saxelStruct = struct('id',fread(fid,1,'int16'),'size',[],'saxelData',[]); wolffd@0: saxelBytes = fread(fid,1,'uint16'); wolffd@0: saxelStruct.size = saxelBytes; wolffd@0: saxelStruct.saxelData = fread(fid,[saxelBytes 1],'*int8'); wolffd@0: if rem(saxelBytes,2), wolffd@0: fseek(fid,1,'cof'); wolffd@0: end wolffd@0: wolffd@0: end wolffd@0: wolffd@0: %-------------------------------------------------------------------------- wolffd@0: function textString = read_text(fid,charCount) wolffd@0: % wolffd@0: % Reads ASCII text from a file, and afterwards shifts the file pointer wolffd@0: % ahead by one byte if necessary to make the total number of bytes read an wolffd@0: % even number. wolffd@0: % wolffd@0: %-------------------------------------------------------------------------- wolffd@0: wolffd@0: textString = fread(fid,[1 charCount],'int8=>char'); wolffd@0: if rem(charCount,2), wolffd@0: fseek(fid,1,'cof'); wolffd@0: end wolffd@0: wolffd@0: end wolffd@0: wolffd@0: %~~~End subfunctions~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~