PRSDK-4807 Fix klocwork issue
[processor-sdk/audio-preprocessing.git] / common / components / fil.c
1 /*
2  * Copyright (c) 2016 - 2018, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33 \r
34 /*=================================================================\r
35  *  fil.c: File related functions.\r
36  *=================================================================*/\r
37 \r
38 #define HIGH_LEVEL 1      /* Use Low level file I/O */\r
39 \r
40 #if HIGH_LEVEL\r
41 # include <stdio.h>       /* needs high level file I/O */\r
42 #else\r
43 # include <file.h>        /* needs low level file I/O */\r
44 #endif\r
45 \r
46 /* The infamous xdc/std.h must come before any header file which uses XDC symbols */\r
47 #include <xdc/std.h>\r
48 #include <types.h>\r
49 \r
50 #include "sys.h"\r
51 #include "fil.h"\r
52 \r
53 /* Globals */\r
54 \r
55 #pragma DATA_ALIGN(filOutBuf0,8)\r
56 tuint filOutBuf0[FIL_OUTLEN_MAX];     /* Output buf/file #0 samples */\r
57 \r
58 #pragma DATA_ALIGN(filBuf0,8)\r
59 tuint filBuf0[FIL_LENGTH_MAX];    /* File #0 samples */\r
60 \r
61 #pragma DATA_ALIGN(filBuf1,8)\r
62 tuint filBuf1[FIL_LENGTH_MAX];    /* File #1 samples */\r
63 \r
64 #pragma DATA_ALIGN(filBuf2,8)\r
65 tuint filBuf2[FIL_LENGTH_MAX];    /* File #2 samples */\r
66 \r
67 #pragma DATA_ALIGN(filBuf3,8)\r
68 tuint filBuf3[FIL_LENGTH_MAX];    /* File #3 samples */\r
69 \r
70 #pragma DATA_ALIGN(filBuf4,8)\r
71 tuint filBuf4[FIL_LENGTH_MAX];    /* File #4 samples */\r
72 \r
73 #pragma DATA_ALIGN(filBuf5,8)\r
74 tuint filBuf5[FIL_LENGTH_MAX];    /* File #5 samples */\r
75 \r
76 #pragma DATA_ALIGN(filBuf6,8)\r
77 tuint filBuf6[FIL_LENGTH_MAX];    /* File #6 samples */\r
78 \r
79 #pragma DATA_ALIGN(filBuf7,8)\r
80 tuint filBuf7[FIL_LENGTH_MAX];    /* File #7 samples */\r
81 \r
82 filDescriptor_t  filDescriptor;   /* Global File Descriptor structure */\r
83 \r
84 /*=============================\r
85  * Functions\r
86  *=============================*/\r
87 \r
88 /*=================================================================\r
89  *  void *filCreate(      Create mic input file(s) descriptor\r
90  *    void **fid,         - File ID pointer\r
91  *    filConfig_t cfg);   - File configuration (see fil.h)\r
92  *=================================================================*/\r
93 \r
94 int filCreate(void **fid, filConfig_t *cfg)\r
95 {\r
96   tint nfiles;\r
97 \r
98   /* Check the input arguments consistency */\r
99   if (fid == (void*)NULL ||\r
100       cfg->nfiles < 1 || cfg->nfiles > FIL_MAX ||\r
101       cfg->length < 1 || cfg->length > FIL_LENGTH_MAX ||\r
102       cfg->outlen < 1 || cfg->length > FIL_OUTLEN_MAX ||\r
103       (cfg->big != TRUE && cfg->big != FALSE) ||\r
104       (cfg->wrap != TRUE && cfg->wrap != FALSE)) {\r
105     return(SYS_ERR_BADCONFIG);\r
106   }\r
107   filDescriptor.r_idx = 0L;                     /* reset to start of "file" */\r
108   filDescriptor.w_idx = 0L;                     /* reset to start of output "file" */\r
109   filDescriptor.length = cfg->length;           /* record to total file length in samples */\r
110   nfiles = filDescriptor.nfiles = cfg->nfiles;  /* how many files do we have */\r
111   filDescriptor.big = cfg->big;                 /* is it big endian byte order */\r
112   filDescriptor.wrap = cfg->wrap;               /* should we wrap around at EOF? */\r
113   filDescriptor.outlen = cfg->outlen;           /* output buf/file length in samples */\r
114 \r
115   /* Initialize base addresses for file buffers */\r
116 \r
117   filDescriptor.filbase[0] = (void*)&filBuf0[0];    /* we must use at least one file */\r
118   filDescriptor.filbase[1] = (void*)(nfiles > 1 ? &filBuf1[0]:NULL);\r
119   filDescriptor.filbase[2] = (void*)(nfiles > 2 ? &filBuf2[0]:NULL);\r
120   filDescriptor.filbase[3] = (void*)(nfiles > 3 ? &filBuf3[0]:NULL);\r
121   filDescriptor.filbase[4] = (void*)(nfiles > 4 ? &filBuf4[0]:NULL);\r
122   filDescriptor.filbase[5] = (void*)(nfiles > 5 ? &filBuf5[0]:NULL);\r
123   filDescriptor.filbase[6] = (void*)(nfiles > 6 ? &filBuf6[0]:NULL);\r
124 #if FIL_MAX==8\r
125   filDescriptor.filbase[7] = (void*)(nfiles > 7 ? &filBuf7[0]:NULL);\r
126 #endif\r
127 \r
128 # if FIL_MAX > 8\r
129 #   error need to implement support for more than 8 files\r
130 # endif\r
131 \r
132   filDescriptor.outbuf = &filOutBuf0[0];        /* point to output buffer */\r
133 \r
134   *fid = (void*)&filDescriptor;    /* Return a pointer to file descriptor */\r
135 \r
136   return(SYS_ERR_SUCCESS);\r
137 } /* filCreate */\r
138 \r
139 /*=================================================================\r
140  *  void *filGetHandle(void)      - get input file(s) descriptor\r
141  *=================================================================*/\r
142 \r
143 void *filGetHandle(void)\r
144 {\r
145   return((void*)&filDescriptor);\r
146 } /* filGetHandle */\r
147 \r
148 /*=================================================================\r
149  *  int filLoad(       - Load input file(s) to memory\r
150  *    char *filpath,        - file path\r
151  *    tlong n,              - number of samples to read\r
152  *    int bufnum)           - buffer number to receive data\r
153  *  \r
154  *    Return: Number of samples read.\r
155  *=================================================================*/\r
156 \r
157 tlong filLoad(char *filpath, tlong n, int bufnum)\r
158 {\r
159   int nread;\r
160   tuint *buf;\r
161 # if HIGH_LEVEL\r
162     FILE *fid;\r
163 # else\r
164     int fid;\r
165 # endif\r
166 \r
167   if (bufnum >= FIL_MAX) {   /* Make sure we have appropriate buffer to store data */\r
168     return(SYS_ERR_FMAXBUF);\r
169   }\r
170   nread = 0;\r
171 # if HIGH_LEVEL\r
172     fid = fopen(filpath, "rb");   /* Open file */\r
173     if (fid == NULL) {\r
174       return(SYS_ERR_FOPEN);\r
175     }\r
176 # else\r
177     fid = open(filpath, O_RDONLY|O_BINARY,0);\r
178     if (fid < 0) {\r
179       return(SYS_ERR_FOPEN);\r
180     }\r
181 # endif\r
182 \r
183   buf = filDescriptor.filbase[bufnum];    /* Fetch the buffer address to receive data */\r
184   if (buf == NULL) {\r
185 #   if HIGH_LEVEL\r
186       fclose(fid);\r
187 #   else\r
188       close(fid);\r
189 #   endif\r
190     return(SYS_ERR_FLOAD);\r
191   }\r
192 # if HIGH_LEVEL\r
193     nread = fread(buf, sizeof(linSample), n, fid);\r
194 # else\r
195   {\r
196     tlong nsamp, nleft_w, nread_w;\r
197 \r
198     nleft_w = n*sizeof(linSample);\r
199     nread_w = 0;\r
200     while (nleft_w > 0) {\r
201       nread_w = read(fid,(char*)buf,nleft_w);\r
202       if (nread_w > 0) {\r
203         nleft_w -= nread_w;                     /* reduce #-words left */\r
204         nsamp    = nread_w/sizeof(linSample);   /* this many samples fetched */\r
205         buf      = &buf[nsamp];                 /* move the buffer pointer */\r
206         nread   += nsamp;                       /* count how many read */\r
207       }\r
208       else if (nread_w == 0) {\r
209         break;\r
210       }\r
211       else {  /* nread_w < 0 indicating error */\r
212         nread = nread_w;\r
213         break;\r
214       }\r
215     }\r
216   }\r
217 # endif\r
218 \r
219 # if HIGH_LEVEL\r
220     fclose(fid);\r
221 # else\r
222     close(fid);\r
223 # endif\r
224 \r
225   if (nread < 0) {\r
226     nread = SYS_ERR_FREAD;\r
227   }\r
228 \r
229   return(nread);\r
230 } /* filLoad */\r
231 \r
232 /*=================================================================\r
233  *  int filRead(        - Read a frame from input files in memory\r
234  *    void *fid,            - a pointer to file descriptor\r
235  *    int n,                - number of samples to read\r
236  *    linSample inbuf[],    - input buffer to receive samples\r
237  *    int buflen)           - input buffer capacity in number of samples\r
238  *=================================================================*/\r
239 \r
240 int filRead(void *fid, int n, linSample inbuf[], int buflen)\r
241 {\r
242   int       k, ch, r_idx, nfiles, length, ncopy, overflow;
243   int       r_idx_new = 0;\r
244   tuint     *in_p, *in_base_p, value;\r
245   linSample *out_p;\r
246   tbool     wrap, big, write_zeros;\r
247 \r
248   filDescriptor_t *fd = (filDescriptor_t*)fid;\r
249 \r
250   if (fid == (void*)NULL) {\r
251     return(SYS_INV_HANDLE);\r
252   }\r
253   if (n > buflen) {\r
254     return(SYS_ERR_BUFLENGTH);\r
255   }\r
256 \r
257   /* Fetch the file descriptor parameters */\r
258   r_idx   = fd->r_idx;      /* current read index */\r
259   nfiles  = fd->nfiles;     /* # of active files */\r
260   length  = fd->length;     /* actual file length in samples */\r
261   wrap    = fd->wrap;\r
262   big     = fd->big;\r
263 \r
264   /* Test read index */\r
265   if (r_idx >= length) {\r
266     write_zeros = !wrap;    /* If past the end write zeros */\r
267     if (wrap) {\r
268       return(SYS_INV_LOGIC);    /* Cannot be past the end in this case! */\r
269     }\r
270   }\r
271   else {\r
272     write_zeros = FALSE;\r
273   }\r
274 \r
275   out_p = &inbuf[0];      /* start from the beginning of a buffer */\r
276   if (!write_zeros) {\r
277     for (ch = 0; ch < nfiles; ch++) {\r
278       in_base_p = (tuint*)fd->filbase[ch];\r
279       in_p = &in_base_p[r_idx];\r
280 \r
281       r_idx_new = r_idx + n;\r
282       overflow = r_idx_new - length;\r
283       if (overflow >= 0) {\r
284         ncopy = n - overflow;\r
285       }\r
286       else {\r
287         overflow = 0;     /* overflow did not occur */\r
288         ncopy = n;\r
289       }\r
290 \r
291       /* Copy frame of samples (before wrap) */\r
292       for (k = 0; k < ncopy; k++) {\r
293         value = *in_p++;\r
294         if (big) {\r
295           *out_p++ = (linSample)FIL_SWAP_BYTES(value);\r
296         }\r
297         else {\r
298           *out_p++ = (linSample)value;\r
299         }\r
300       }\r
301 \r
302       if (!wrap) {\r
303         for (k = 0; k < overflow; k++) {    /* pad zeros if no-wrap */\r
304           *out_p++ = 0;\r
305         }\r
306       }\r
307       else {  /* wrap part */\r
308         if (overflow > 0) {\r
309           in_p = &in_base_p[0];     /* Wrap around the pointer */\r
310           for (k = 0; k < overflow; k++) {  /* copy wrapped samples */\r
311             value = *in_p++;\r
312             if (big) {\r
313               *out_p++ = (linSample)FIL_SWAP_BYTES(value);\r
314             }\r
315             else {\r
316               *out_p++ = (linSample)value;\r
317             }\r
318           }\r
319         }\r
320         r_idx_new = overflow;     /* Reset read index if wrap required */\r
321       } /* wrap */\r
322     } /* ch loop */\r
323 \r
324     fd->r_idx = r_idx_new;        /* Update the read index for next time */\r
325 \r
326   } /* do not write zeros */\r
327   else {  /* write zeros */\r
328     for (k = 0; k < n; k++) {\r
329       *out_p++ = 0;\r
330     }\r
331   }\r
332 \r
333   return(SYS_ERR_SUCCESS);\r
334 } /* filRead */\r
335 \r
336 /*===============================================================================*/\r
337 /* This is the WRITE Part */\r
338 /*===============================================================================*/\r
339 \r
340 /*=================================================================\r
341  *  int filWrite(         - Write a frame into output file in memory\r
342  *    void *fid,            - a pointer to file descriptor\r
343  *    int n,                - number of samples to write\r
344  *    linSample outbuf[])   - output buffer that contains samples\r
345  *=================================================================*/\r
346 \r
347 int filWrite(void *fid, int n, linSample outbuf[])\r
348 {\r
349   int       k, w_idx, w_idx_new, ncopy, overflow, err;\r
350   tuint     *out_p, *out_base_p, value;\r
351   tlong     outlen;\r
352   linSample *in_p;\r
353   tbool     big;\r
354 \r
355   filDescriptor_t *fd = (filDescriptor_t*)fid;\r
356   outlen = fd->outlen;        /* Total output buffer length */\r
357 \r
358   if (fid == (void*)NULL) {\r
359     return(SYS_INV_HANDLE);\r
360   }\r
361   if (n > outlen) {\r
362     return(SYS_ERR_BUFLENGTH);\r
363   }\r
364 \r
365   /* Fetch the file descriptor parameters */\r
366   w_idx   = fd->w_idx;          /* current write index */\r
367   big     = fd->big;\r
368 \r
369   /* Test write index */\r
370   if (w_idx >= outlen) {\r
371     return(SYS_ERR_EOF);        /* Indicate end of file */\r
372   }\r
373 \r
374   in_p = &outbuf[0];        /* start from the beginning of a buffer (our input) */\r
375 \r
376   out_base_p = (tuint*)fd->outbuf;\r
377   out_p = &out_base_p[w_idx];         /* Find where to write samples */\r
378 \r
379   w_idx_new = w_idx + n;\r
380   overflow = w_idx_new - outlen;\r
381   if (overflow >= 0) {\r
382     ncopy = n - overflow;\r
383     err = SYS_ERR_EOF;\r
384   }\r
385   else {\r
386     overflow = 0;     /* overflow did not occur */\r
387     ncopy = n;\r
388     err = SYS_ERR_SUCCESS;\r
389   }\r
390 \r
391   /* Copy frame of samples (before end of file) */\r
392   for (k = 0; k < ncopy; k++) {\r
393     value = *in_p++;\r
394     if (big) {\r
395       *out_p++ = (linSample)FIL_SWAP_BYTES(value);\r
396     }\r
397     else {\r
398       *out_p++ = (linSample)value;\r
399     }\r
400   }\r
401 \r
402   fd->w_idx = w_idx_new;        /* Update the write index for next time */\r
403 \r
404   return(err);\r
405 \r
406 } /* filWrite */\r
407 \r
408 /* nothing past this point */\r
409 \r