74a97213cb9a151805dcda6c1bb50cfc284a3f9a
[processor-sdk/audio-preprocessing.git] / common / components / fil.c
1 /*
2  * Copyright (c) 2016, 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, r_idx_new, nfiles, length, ncopy, overflow;\r
243   tuint     *in_p, *in_base_p, value;\r
244   linSample *out_p;\r
245   tbool     wrap, big, write_zeros;\r
246 \r
247   filDescriptor_t *fd = (filDescriptor_t*)fid;\r
248 \r
249   if (fid == (void*)NULL) {\r
250     return(SYS_INV_HANDLE);\r
251   }\r
252   if (n > buflen) {\r
253     return(SYS_ERR_BUFLENGTH);\r
254   }\r
255 \r
256   /* Fetch the file descriptor parameters */\r
257   r_idx   = fd->r_idx;      /* current read index */\r
258   nfiles  = fd->nfiles;     /* # of active files */\r
259   length  = fd->length;     /* actual file length in samples */\r
260   wrap    = fd->wrap;\r
261   big     = fd->big;\r
262 \r
263   /* Test read index */\r
264   if (r_idx >= length) {\r
265     write_zeros = !wrap;    /* If past the end write zeros */\r
266     if (wrap) {\r
267       return(SYS_INV_LOGIC);    /* Cannot be past the end in this case! */\r
268     }\r
269   }\r
270   else {\r
271     write_zeros = FALSE;\r
272   }\r
273 \r
274   out_p = &inbuf[0];      /* start from the beginning of a buffer */\r
275   if (!write_zeros) {\r
276     for (ch = 0; ch < nfiles; ch++) {\r
277       in_base_p = (tuint*)fd->filbase[ch];\r
278       in_p = &in_base_p[r_idx];\r
279 \r
280       r_idx_new = r_idx + n;\r
281       overflow = r_idx_new - length;\r
282       if (overflow >= 0) {\r
283         ncopy = n - overflow;\r
284       }\r
285       else {\r
286         overflow = 0;     /* overflow did not occur */\r
287         ncopy = n;\r
288       }\r
289 \r
290       /* Copy frame of samples (before wrap) */\r
291       for (k = 0; k < ncopy; k++) {\r
292         value = *in_p++;\r
293         if (big) {\r
294           *out_p++ = (linSample)FIL_SWAP_BYTES(value);\r
295         }\r
296         else {\r
297           *out_p++ = (linSample)value;\r
298         }\r
299       }\r
300 \r
301       if (!wrap) {\r
302         for (k = 0; k < overflow; k++) {    /* pad zeros if no-wrap */\r
303           *out_p++ = 0;\r
304         }\r
305       }\r
306       else {  /* wrap part */\r
307         if (overflow > 0) {\r
308           in_p = &in_base_p[0];     /* Wrap around the pointer */\r
309           for (k = 0; k < overflow; k++) {  /* copy wrapped samples */\r
310             value = *in_p++;\r
311             if (big) {\r
312               *out_p++ = (linSample)FIL_SWAP_BYTES(value);\r
313             }\r
314             else {\r
315               *out_p++ = (linSample)value;\r
316             }\r
317           }\r
318         }\r
319         r_idx_new = overflow;     /* Reset read index if wrap required */\r
320       } /* wrap */\r
321     } /* ch loop */\r
322 \r
323     fd->r_idx = r_idx_new;        /* Update the read index for next time */\r
324 \r
325   } /* do not write zeros */\r
326   else {  /* write zeros */\r
327     for (k = 0; k < n; k++) {\r
328       *out_p++ = 0;\r
329     }\r
330   }\r
331 \r
332   return(SYS_ERR_SUCCESS);\r
333 } /* filRead */\r
334 \r
335 /*===============================================================================*/\r
336 /* This is the WRITE Part */\r
337 /*===============================================================================*/\r
338 \r
339 /*=================================================================\r
340  *  int filWrite(         - Write a frame into output file in memory\r
341  *    void *fid,            - a pointer to file descriptor\r
342  *    int n,                - number of samples to write\r
343  *    linSample outbuf[])   - output buffer that contains samples\r
344  *=================================================================*/\r
345 \r
346 int filWrite(void *fid, int n, linSample outbuf[])\r
347 {\r
348   int       k, w_idx, w_idx_new, ncopy, overflow, err;\r
349   tuint     *out_p, *out_base_p, value;\r
350   tlong     outlen;\r
351   linSample *in_p;\r
352   tbool     big;\r
353 \r
354   filDescriptor_t *fd = (filDescriptor_t*)fid;\r
355   outlen = fd->outlen;        /* Total output buffer length */\r
356 \r
357   if (fid == (void*)NULL) {\r
358     return(SYS_INV_HANDLE);\r
359   }\r
360   if (n > outlen) {\r
361     return(SYS_ERR_BUFLENGTH);\r
362   }\r
363 \r
364   /* Fetch the file descriptor parameters */\r
365   w_idx   = fd->w_idx;          /* current write index */\r
366   big     = fd->big;\r
367 \r
368   /* Test write index */\r
369   if (w_idx >= outlen) {\r
370     return(SYS_ERR_EOF);        /* Indicate end of file */\r
371   }\r
372 \r
373   in_p = &outbuf[0];        /* start from the beginning of a buffer (our input) */\r
374 \r
375   out_base_p = (tuint*)fd->outbuf;\r
376   out_p = &out_base_p[w_idx];         /* Find where to write samples */\r
377 \r
378   w_idx_new = w_idx + n;\r
379   overflow = w_idx_new - outlen;\r
380   if (overflow >= 0) {\r
381     ncopy = n - overflow;\r
382     err = SYS_ERR_EOF;\r
383   }\r
384   else {\r
385     overflow = 0;     /* overflow did not occur */\r
386     ncopy = n;\r
387     err = SYS_ERR_SUCCESS;\r
388   }\r
389 \r
390   /* Copy frame of samples (before end of file) */\r
391   for (k = 0; k < ncopy; k++) {\r
392     value = *in_p++;\r
393     if (big) {\r
394       *out_p++ = (linSample)FIL_SWAP_BYTES(value);\r
395     }\r
396     else {\r
397       *out_p++ = (linSample)value;\r
398     }\r
399   }\r
400 \r
401   fd->w_idx = w_idx_new;        /* Update the write index for next time */\r
402 \r
403   return(err);\r
404 \r
405 } /* filWrite */\r
406 \r
407 /* nothing past this point */\r
408 \r