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 <ti/mas/types/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