#include #include #include #include #include #include #include "raw.h" static void RawReportError( const char *filename, const char *reason, int how_bad ); static FILE *RawOpenFile( const char *filename, const char *mode, off_t *size_rtn ); int RawIsFileRaw(const char *filename); int RawReadHeader(const char *filename, FILE *fp, raw_data_struct *rd); int RawReadPartialData( raw_data_struct *rd, long offset, long max_chunk_size, int read_opt ); #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define CLIP(a,l,h) (MIN(MAX((a),(l)),(h))) #define ABSOLUTE(x) (((x) < 0) ? ((x) * -1) : (x)) static void RawReportError( const char *filename, const char *reason, int how_bad ) { if(filename != NULL) fprintf(stderr, "%s: ", filename); if(reason != NULL) fprintf(stderr, "%s (Error level %i)", reason, how_bad); fprintf(stderr, "\n"); return; } void RawDestroyData(raw_data_struct *rd) { if(rd == NULL) return; free(rd->filename); rd->filename = NULL; if(rd->fp != NULL) { fclose(rd->fp); rd->fp = NULL; } rd->data_offset = 0; rd->data_length = 0; rd->block_align = 0; rd->sample_size = 0; rd->channels = 0; rd->sample_rate = 0; free(rd->data); rd->data = NULL; rd->data_len = 0; return; } static FILE *RawOpenFile( const char *filename, const char *mode, off_t *size_rtn ) { FILE *fp; struct stat stat_buf; if(filename == NULL) { fprintf(stderr, "Cannot open file with no name.\n"); *size_rtn = 0; return(NULL); } if(mode == NULL) { fprintf(stderr, "%s: Open mode not givin.\n", filename); *size_rtn = 0; return(NULL); } if(stat(filename, &stat_buf)) { fprintf(stderr, "%s: No such file.\n", filename); *size_rtn = 0; return(NULL); } *size_rtn = stat_buf.st_size; fp = fopen(filename, mode); if(fp == NULL) { fprintf(stderr, "%s: Cannot open.\n", filename); *size_rtn = 0; return(NULL); } return(fp); } int RawIsFileRaw(const char *filename) { FILE *fp; off_t filesize; /* Open file. */ fp = RawOpenFile(filename, "rb", &filesize); if(fp == NULL) return(RawErrorNoAccess); if(filesize == 0) return(RawErrorNoAccess); /* What do we check? */ /* Close file. */ fclose(fp); return(RawSuccess); } /* * Reads the header from the stream fp and initializes the given * rd structure if fp is valid and a raw file. * * The given filename is used only for referance purposes, it can be * NULL. * * If RawSuccess is returned then the given fp will be transfered * to the rd structure and should not be referanced again. For all * other return values, the calling function is responsible for * closing the given fp. */ int RawReadHeader(const char *filename, FILE *fp, raw_data_struct *rd) { off_t filesize; struct stat stat_buf; /* Error checks. */ if(rd == NULL) return(RawErrorNoBuffers); if(fp == NULL) return(RawErrorBadValue); /* Rewind to beginning of raw file. */ rewind(fp); /* Reset values. */ memset(rd, 0x00, sizeof(raw_data_struct)); /* Get size of file. */ if(fstat(fileno(fp), &stat_buf)) return(RawErrorNoAccess); filesize = stat_buf.st_size; if(filesize == 0) return(RawErrorNoAccess); /* Here we should be checking if this is a raw file, but there * really is no way to tell so just assume that it is a raw * file. */ /* Begin reading raw file header. */ /* Record file name. */ if(filename != NULL) rd->filename = strdup(filename); /* Check for offset? */ /* Get offset. */ rd->data_offset = 0; /* Get length of data. */ rd->data_length = (long)filesize - (long)rd->data_offset; if(rd->data_length < 0) rd->data_length = 0; /* Standard values. */ rd->block_align = 0; rd->sample_size = 8; rd->channels = 1; rd->sample_rate = 8000; /* Transfer given fp to the rd structure, the calling * function should not referance it again since we are returning * RawSuccess. */ rd->fp = fp; return(RawSuccess); } /* * Reads a segment of data from the raw file reffered to * by the filename member on the given wd structure (which * should have been initialized wuth a prior call to * RawReadHeader(). * * File will be opened as needed if the fp member is NULL. * * The member data and data_len will be reallocated as needed * if the requested max_chunk_size is different than data_len. */ int RawReadPartialData( raw_data_struct *rd, long offset, /* In bytes. */ long max_chunk_size, /* In bytes. */ int read_opt ) { int i; char *buf_ptr; if(rd == NULL) return(RawErrorNoBuffers); if(offset < 0) return(RawErrorBadValue); /* Read nothing? */ if(max_chunk_size <= 0) { free(rd->data); rd->data = NULL; rd->data_len = 0; return(RawSuccess); } /* Sanitize values. */ if(offset >= rd->data_length) { return(RawErrorEndOfData); } if((offset + max_chunk_size) > rd->data_length) { max_chunk_size = rd->data_length - offset; } if(max_chunk_size <= 0) { return(RawErrorEndOfData); } /* Open file as needed. */ if(rd->fp == NULL) { off_t filesize; if(rd->filename == NULL) return(RawErrorBadValue); rd->fp = RawOpenFile(rd->filename, "rb", &filesize); if(rd->fp == NULL) return(RawErrorNoAccess); if(filesize == 0) return(RawErrorNoAccess); } /* Reallocate buffer for data (as needed). */ if(rd->data_len != max_chunk_size) { rd->data_len = max_chunk_size; rd->data = (char *)realloc( rd->data, rd->data_len * sizeof(char) ); } if(rd->data == NULL) { rd->data_len = 0; fclose(rd->fp); rd->fp = NULL; return(RawErrorNoBuffers); } /* Position file pointer. */ fseek(rd->fp, rd->data_offset + offset, SEEK_SET); /* Read the data, raw file format stores DSP as signed 8. */ buf_ptr = rd->data; switch(read_opt) { /* Shift byte value by + 128. */ case RawReadUnsigned8: for(i = 0; i < max_chunk_size; i++) *buf_ptr++ = (char)(fgetc(rd->fp) + 128); break; /* Get data as is (signed 8). */ default: for(i = 0; i < max_chunk_size; i++) *buf_ptr++ = (char)fgetc(rd->fp); break; } return(RawSuccess); }