/* * Copyright (c) 2016, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ /*================================================================= * fil.c: File related functions. *=================================================================*/ #define HIGH_LEVEL 1 /* Use Low level file I/O */ #if HIGH_LEVEL # include /* needs high level file I/O */ #else # include /* needs low level file I/O */ #endif /* The infamous xdc/std.h must come before any header file which uses XDC symbols */ #include #include #include "sys.h" #include "fil.h" /* Globals */ #pragma DATA_ALIGN(filOutBuf0,8) tuint filOutBuf0[FIL_OUTLEN_MAX]; /* Output buf/file #0 samples */ #pragma DATA_ALIGN(filBuf0,8) tuint filBuf0[FIL_LENGTH_MAX]; /* File #0 samples */ #pragma DATA_ALIGN(filBuf1,8) tuint filBuf1[FIL_LENGTH_MAX]; /* File #1 samples */ #pragma DATA_ALIGN(filBuf2,8) tuint filBuf2[FIL_LENGTH_MAX]; /* File #2 samples */ #pragma DATA_ALIGN(filBuf3,8) tuint filBuf3[FIL_LENGTH_MAX]; /* File #3 samples */ #pragma DATA_ALIGN(filBuf4,8) tuint filBuf4[FIL_LENGTH_MAX]; /* File #4 samples */ #pragma DATA_ALIGN(filBuf5,8) tuint filBuf5[FIL_LENGTH_MAX]; /* File #5 samples */ #pragma DATA_ALIGN(filBuf6,8) tuint filBuf6[FIL_LENGTH_MAX]; /* File #6 samples */ #pragma DATA_ALIGN(filBuf7,8) tuint filBuf7[FIL_LENGTH_MAX]; /* File #7 samples */ filDescriptor_t filDescriptor; /* Global File Descriptor structure */ /*============================= * Functions *=============================*/ /*================================================================= * void *filCreate( Create mic input file(s) descriptor * void **fid, - File ID pointer * filConfig_t cfg); - File configuration (see fil.h) *=================================================================*/ int filCreate(void **fid, filConfig_t *cfg) { tint nfiles; /* Check the input arguments consistency */ if (fid == (void*)NULL || cfg->nfiles < 1 || cfg->nfiles > FIL_MAX || cfg->length < 1 || cfg->length > FIL_LENGTH_MAX || cfg->outlen < 1 || cfg->length > FIL_OUTLEN_MAX || (cfg->big != TRUE && cfg->big != FALSE) || (cfg->wrap != TRUE && cfg->wrap != FALSE)) { return(SYS_ERR_BADCONFIG); } filDescriptor.r_idx = 0L; /* reset to start of "file" */ filDescriptor.w_idx = 0L; /* reset to start of output "file" */ filDescriptor.length = cfg->length; /* record to total file length in samples */ nfiles = filDescriptor.nfiles = cfg->nfiles; /* how many files do we have */ filDescriptor.big = cfg->big; /* is it big endian byte order */ filDescriptor.wrap = cfg->wrap; /* should we wrap around at EOF? */ filDescriptor.outlen = cfg->outlen; /* output buf/file length in samples */ /* Initialize base addresses for file buffers */ filDescriptor.filbase[0] = (void*)&filBuf0[0]; /* we must use at least one file */ filDescriptor.filbase[1] = (void*)(nfiles > 1 ? &filBuf1[0]:NULL); filDescriptor.filbase[2] = (void*)(nfiles > 2 ? &filBuf2[0]:NULL); filDescriptor.filbase[3] = (void*)(nfiles > 3 ? &filBuf3[0]:NULL); filDescriptor.filbase[4] = (void*)(nfiles > 4 ? &filBuf4[0]:NULL); filDescriptor.filbase[5] = (void*)(nfiles > 5 ? &filBuf5[0]:NULL); filDescriptor.filbase[6] = (void*)(nfiles > 6 ? &filBuf6[0]:NULL); #if FIL_MAX==8 filDescriptor.filbase[7] = (void*)(nfiles > 7 ? &filBuf7[0]:NULL); #endif # if FIL_MAX > 8 # error need to implement support for more than 8 files # endif filDescriptor.outbuf = &filOutBuf0[0]; /* point to output buffer */ *fid = (void*)&filDescriptor; /* Return a pointer to file descriptor */ return(SYS_ERR_SUCCESS); } /* filCreate */ /*================================================================= * void *filGetHandle(void) - get input file(s) descriptor *=================================================================*/ void *filGetHandle(void) { return((void*)&filDescriptor); } /* filGetHandle */ /*================================================================= * int filLoad( - Load input file(s) to memory * char *filpath, - file path * tlong n, - number of samples to read * int bufnum) - buffer number to receive data * * Return: Number of samples read. *=================================================================*/ tlong filLoad(char *filpath, tlong n, int bufnum) { int nread; tuint *buf; # if HIGH_LEVEL FILE *fid; # else int fid; # endif if (bufnum > FIL_MAX) { /* Make sure we have appropriate buffer to store data */ return(SYS_ERR_FMAXBUF); } nread = 0; # if HIGH_LEVEL fid = fopen(filpath, "rb"); /* Open file */ if (fid == NULL) { return(SYS_ERR_FOPEN); } # else fid = open(filpath, O_RDONLY|O_BINARY,0); if (fid < 0) { return(SYS_ERR_FOPEN); } # endif buf = filDescriptor.filbase[bufnum]; /* Fetch the buffer address to receive data */ if (buf == NULL) { # if HIGH_LEVEL fclose(fid); # else close(fid); # endif return(SYS_ERR_FLOAD); } # if HIGH_LEVEL nread = fread(buf, sizeof(linSample), n, fid); # else { tlong nsamp, nleft_w, nread_w; nleft_w = n*sizeof(linSample); nread_w = 0; while (nleft_w > 0) { nread_w = read(fid,(char*)buf,nleft_w); if (nread_w > 0) { nleft_w -= nread_w; /* reduce #-words left */ nsamp = nread_w/sizeof(linSample); /* this many samples fetched */ buf = &buf[nsamp]; /* move the buffer pointer */ nread += nsamp; /* count how many read */ } else if (nread_w == 0) { break; } else { /* nread_w < 0 indicating error */ nread = nread_w; break; } } } # endif # if HIGH_LEVEL fclose(fid); # else close(fid); # endif if (nread < 0) { nread = SYS_ERR_FREAD; } return(nread); } /* filLoad */ /*================================================================= * int filRead( - Read a frame from input files in memory * void *fid, - a pointer to file descriptor * int n, - number of samples to read * linSample inbuf[], - input buffer to receive samples * int buflen) - input buffer capacity in number of samples *=================================================================*/ int filRead(void *fid, int n, linSample inbuf[], int buflen) { int k, ch, r_idx, r_idx_new, nfiles, length, ncopy, overflow; tuint *in_p, *in_base_p, value; linSample *out_p; tbool wrap, big, write_zeros; filDescriptor_t *fd = (filDescriptor_t*)fid; if (fid == (void*)NULL) { return(SYS_INV_HANDLE); } if (n > buflen) { return(SYS_ERR_BUFLENGTH); } /* Fetch the file descriptor parameters */ r_idx = fd->r_idx; /* current read index */ nfiles = fd->nfiles; /* # of active files */ length = fd->length; /* actual file length in samples */ wrap = fd->wrap; big = fd->big; /* Test read index */ if (r_idx >= length) { write_zeros = !wrap; /* If past the end write zeros */ if (wrap) { return(SYS_INV_LOGIC); /* Cannot be past the end in this case! */ } } else { write_zeros = FALSE; } out_p = &inbuf[0]; /* start from the beginning of a buffer */ if (!write_zeros) { for (ch = 0; ch < nfiles; ch++) { in_base_p = (tuint*)fd->filbase[ch]; in_p = &in_base_p[r_idx]; r_idx_new = r_idx + n; overflow = r_idx_new - length; if (overflow >= 0) { ncopy = n - overflow; } else { overflow = 0; /* overflow did not occur */ ncopy = n; } /* Copy frame of samples (before wrap) */ for (k = 0; k < ncopy; k++) { value = *in_p++; if (big) { *out_p++ = (linSample)FIL_SWAP_BYTES(value); } else { *out_p++ = (linSample)value; } } if (!wrap) { for (k = 0; k < overflow; k++) { /* pad zeros if no-wrap */ *out_p++ = 0; } } else { /* wrap part */ if (overflow > 0) { in_p = &in_base_p[0]; /* Wrap around the pointer */ for (k = 0; k < overflow; k++) { /* copy wrapped samples */ value = *in_p++; if (big) { *out_p++ = (linSample)FIL_SWAP_BYTES(value); } else { *out_p++ = (linSample)value; } } } r_idx_new = overflow; /* Reset read index if wrap required */ } /* wrap */ } /* ch loop */ fd->r_idx = r_idx_new; /* Update the read index for next time */ } /* do not write zeros */ else { /* write zeros */ for (k = 0; k < n; k++) { *out_p++ = 0; } } return(SYS_ERR_SUCCESS); } /* filRead */ /*===============================================================================*/ /* This is the WRITE Part */ /*===============================================================================*/ /*================================================================= * int filWrite( - Write a frame into output file in memory * void *fid, - a pointer to file descriptor * int n, - number of samples to write * linSample outbuf[]) - output buffer that contains samples *=================================================================*/ int filWrite(void *fid, int n, linSample outbuf[]) { int k, w_idx, w_idx_new, ncopy, overflow, err; tuint *out_p, *out_base_p, value; tlong outlen; linSample *in_p; tbool big; filDescriptor_t *fd = (filDescriptor_t*)fid; outlen = fd->outlen; /* Total output buffer length */ if (fid == (void*)NULL) { return(SYS_INV_HANDLE); } if (n > outlen) { return(SYS_ERR_BUFLENGTH); } /* Fetch the file descriptor parameters */ w_idx = fd->w_idx; /* current write index */ big = fd->big; /* Test write index */ if (w_idx >= outlen) { return(SYS_ERR_EOF); /* Indicate end of file */ } in_p = &outbuf[0]; /* start from the beginning of a buffer (our input) */ out_base_p = (tuint*)fd->outbuf; out_p = &out_base_p[w_idx]; /* Find where to write samples */ w_idx_new = w_idx + n; overflow = w_idx_new - outlen; if (overflow >= 0) { ncopy = n - overflow; err = SYS_ERR_EOF; } else { overflow = 0; /* overflow did not occur */ ncopy = n; err = SYS_ERR_SUCCESS; } /* Copy frame of samples (before end of file) */ for (k = 0; k < ncopy; k++) { value = *in_p++; if (big) { *out_p++ = (linSample)FIL_SWAP_BYTES(value); } else { *out_p++ = (linSample)value; } } fd->w_idx = w_idx_new; /* Update the write index for next time */ return(err); } /* filWrite */ /* nothing past this point */