1 /*-------------- Telecommunications & Signal Processing Lab ---------------
2 McGill University
3
4 Routine:
5 int AFposition (AFILE *AFp, long int offs)
6
7 Purpose:
8 Position an audio file to a given sample offset
9
10 Description:
11 This routine positions a file to a given position.
12
13 Parameters:
14 <- int AFposition
15 Error indication, zero for no error
16 -> AFILE *AFp
17 Audio file pointer for an audio file opened by AFopnRead
18 -> long int offs
19 Offset into the file in samples. If offs is negative or beyond the
20 end-of-file, no action is taken. If offs is beyond the current file
21 position, the position is moved to offs either by seeking (random access
22 binary file) or by reading (non-random access or text data). If offset
23 is before offs, move by seeking (random access binary file) or by
24 rewinding and reading (random access text file).
25
26 Author / revision:
27 P. Kabal Copyright (C) 2003
28 $Revision: 1.2 $ $Date: 2003/05/09 01:11:34 $
29
30 -------------------------------------------------------------------------*/
31
32 #include <string.h>
33
34 #include <libtsp.h>
35 #include <libtsp/nucleus.h>
36 #include <libtsp/AFdataio.h>
37 #include <libtsp/AFmsg.h>
38 #define AF_DATA_LENGTHS
39 #include <libtsp/AFpar.h>
40
41 #define MINV(a, b) (((a) < (b)) ? (a) : (b))
42
43 #define FREAD(buf,size,nv,fp) (int) fread ((char *) buf, (size_t) size, \
44 (size_t) nv, fp)
45 #define AFSEEK(AFp,boff) AFseek ((AFp)->fp, (AFp)->Start + (boff), NULL)
46
47 static int
48 AF_skipNRec (AFILE *AFp, long int N);
49 static int
50 AF_skipNVal (AFILE *AFp, long int N);
51
52
53 int
AFposition(AFILE * AFp,long int offs)54 AFposition (AFILE *AFp, long int offs)
55
56 {
57 int Lw, ErrCode;
58
59 /*
60 Notes:
61 offs < 0 Nop
62 < AFp->Isamp seek
63 == AFp->Isamp Nop
64 < AFp->Nsamp seek or read
65 >= AFp->Nsamp Nop
66 AFp->Nsamp == AF_NSAMP_UNDEF, the file is not random access
67 (on encountering EOF, the value of AFp->Nsamp is set)
68 == value, can be either random access or not
69 */
70 ErrCode = 0;
71
72 /* Quick exit */
73 if (offs == AFp->Isamp || offs < 0L ||
74 (AFp->Nsamp != AF_NSAMP_UNDEF && offs >= AFp->Nsamp))
75 return ErrCode;
76
77 Lw = AF_DL[AFp->Format];
78 if (Lw > 0) {
79
80 /* Fixed length records */
81 if (FLseekable (AFp->fp)) {
82 ErrCode = AFSEEK (AFp, Lw * offs);
83 if (! ErrCode)
84 AFp->Isamp = offs;
85 }
86 else if (offs < AFp->Isamp) {
87 UTwarn ("AFposition: %s", AFM_MoveBack);
88 ErrCode = AF_IOERR;
89 }
90 else
91 ErrCode = AF_skipNVal (AFp, offs - AFp->Isamp);
92 }
93
94 else {
95
96 /* Variable length (text) records */
97 if (offs < AFp->Isamp) {
98 if (FLseekable (AFp->fp)) {
99 ErrCode = AFSEEK (AFp, 0L); /* Rewinding to start of data */
100 if (! ErrCode)
101 AFp->Isamp = 0L;
102 }
103 else {
104 UTwarn ("AFposition: %s", AFM_MoveBack);
105 ErrCode = AF_IOERR;
106 }
107 }
108
109 /* Move forward to the desired position */
110 if (! ErrCode)
111 ErrCode = AF_skipNRec (AFp, offs - AFp->Isamp);
112 }
113
114 return ErrCode;
115 }
116
117 /* Skip N values */
118
119 #define NBUF 256
120
121
122 static int
AF_skipNVal(AFILE * AFp,long int N)123 AF_skipNVal (AFILE *AFp, long int N)
124
125 {
126 long int nl;
127 int Lw, Nv, Nreq, ErrCode;
128 double Buf[NBUF];
129
130 Lw = AF_DL[AFp->Format];
131
132 /* Read N values */
133 nl = 0L;
134 while (nl < N) {
135 Nreq = (int) MINV ((int) (sizeof Buf) / Lw, N - nl);
136 Nv = FREAD (Buf, Lw, Nreq, AFp->fp);
137 nl += Nv;
138 if (Nv < Nreq)
139 break;
140 }
141 AFp->Isamp += nl;
142
143 ErrCode = 0;
144 if (nl < N) {
145 if (ferror (AFp->fp)) {
146 UTsysMsg ("AFposition: %s %ld", AFM_ReadErrOffs, AFp->Isamp);
147 ErrCode = AF_IOERR;
148 }
149 else if (AFp->Nsamp != AF_NSAMP_UNDEF) {
150 UTwarn ("AFposition: %s %ld", AFM_UEoFOffs, AFp->Isamp);
151 ErrCode = AF_UEOF;
152 }
153 else
154 AFp->Nsamp = AFp->Isamp;
155 }
156
157 return ErrCode;
158 }
159
160 /* Skip N records */
161
162
163 static int
AF_skipNRec(AFILE * AFp,long int N)164 AF_skipNRec (AFILE *AFp, long int N)
165
166 {
167 char *p;
168 int ErrCode;
169 long int nl;
170
171 /* Read N lines of input */
172 ErrCode = 0;
173 for (nl = 0; nl < N; ++nl) {
174 p = AFgetLine (AFp->fp, &ErrCode);
175 if (p == NULL || AFp->Error)
176 break;
177 }
178 AFp->Isamp += nl;
179
180 if (nl < N) {
181 if (ErrCode)
182 UTwarn ("AFposition: %s %ld", AFM_ReadErrOffs, AFp->Isamp);
183 else if (AFp->Nsamp != AF_NSAMP_UNDEF) {
184 UTwarn ("AFposition: %s %ld", AFM_UEoFOffs, AFp->Isamp);
185 ErrCode = AF_UEOF;
186 }
187 else
188 AFp->Nsamp = AFp->Isamp;
189 }
190
191 return ErrCode;
192 }
193