1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <fcntl.h>
7 #include <dirent.h>
8 #include <sys/types.h>
9
10 #ifdef linux
11 #include <endian.h>
12 #elif defined (__FreeBSD__)
13 #include <machine/endian.h>
14 #elif defined (sgi)
15 #include <sys/endian.h>
16 #elif defined (sun)
17 #include <sys/byteorder.h>
18 #endif
19
20
21 #include "types.h"
22 #include "audio_file.h"
23 #include "ieee/ieee.h"
24 #include "aifc.h"
25 #include "endian.h"
26
27 static int aifc_new(Audio_File *af);
28
is_aifc(int fd)29 bool is_aifc(int fd)
30 {
31 Aif_Form form;
32
33 if ((read(fd,&form,sizeof(Aif_Form)))==-1) return(False);
34 if ((lseek(fd,0,SEEK_SET))==-1) return(False);
35
36 #ifdef little_endian
37 M_32_SWAP(form.form);
38 M_32_SWAP(form.length);
39 M_32_SWAP(form.type);
40 #endif
41 if (form.form!=FORM) return(False);
42 if ((form.type!=AIFF)&&(form.type!=AIFC)) return(False);
43 return(True);
44 }
45
46
aifc_open(Audio_File * af,int mode)47 int aifc_open(Audio_File *af,int mode)
48 {
49 int i,count;
50 Aif_Form form;
51 Aif_Chunk chunk;
52 ulong frames,stamp,block_size,offset;
53 short channels,bps;
54 ID comp_typ;
55 unsigned char freq[10],plength,*pstring;
56 bool com_found=False;
57 bool snd_found=False;
58 bool ver_found=False;
59
60 if (mode==AF_NEW) return(aifc_new(af));
61
62 if (read(af->fd,&form,sizeof(Aif_Form))!=sizeof(Aif_Form))
63 return(AF_ERROR);
64
65 #ifdef little_endianN
66 M_32_SWAP(form.form);
67 M_32_SWAP(form.length);
68 M_32_SWAP(form.type);
69 #endif
70
71 if (form.form!=FORM) return(AF_ERROR);
72
73 if ((form.type!=AIFF)&&(form.type!=AIFC)) return(AF_ERROR);
74
75 while(1) {
76 if ((i=read(af->fd,&chunk,sizeof(Aif_Chunk)))!=sizeof(Aif_Chunk))
77 return(AF_ERROR);
78
79 #ifdef little_endianN
80 M_32_SWAP(chunk.type);
81 M_32_SWAP(chunk.length);
82 #endif
83
84 if (chunk.type==FVER) {
85 ver_found=True;
86 if ((i=read(af->fd,&stamp,sizeof(stamp)))!=sizeof(stamp))
87 return(AF_ERROR);
88 if ((lseek(af->fd,-i,SEEK_CUR))==-1) return(AF_ERROR);
89 }
90
91 if (chunk.type==COMM) {
92 com_found=True;
93 count=0;
94 i=read(af->fd,&channels,sizeof(channels));count+=i;
95 i=read(af->fd,&frames,sizeof(frames));count+=i;
96 i=read(af->fd,&bps,sizeof(bps));count+=i;
97 i=read(af->fd,&freq,sizeof(freq));count+=i;
98 if (form.type==AIFC) {
99 i=read(af->fd,&comp_typ,sizeof(comp_typ));count+=i;
100
101 #ifdef little_endianN
102 M_32_SWAP(comp_typ);
103 #endif
104
105 i=read(af->fd,&plength,sizeof(plength));count+=i;
106 pstring=malloc(plength);
107 if ((i!=-1)&&(pstring!=NULL))
108 i=read(af->fd,pstring,plength);count+=i;
109 } else comp_typ=AIFF;
110
111 if (i<=0) return(AF_ERROR);
112
113 /* SSND Chunk was above, read COMM Chunk and jump to begin */
114 if (snd_found) {
115 if ((lseek(af->fd,sizeof(Aif_Form),SEEK_SET))==-1)
116 return(AF_ERROR);
117 } else {
118 /* seek to begin of comm chunk (below we seek to chunk.length) */
119 if ((lseek(af->fd,-count,SEEK_CUR))==-1) return(AF_ERROR);
120 }
121
122 #ifdef little_endianN
123 M_16_SWAP(channels);
124 M_32_SWAP(frames);
125 M_16_SWAP(bps);
126 #endif
127 }
128
129 /* pad byte */
130 if (chunk.length % 2) {
131 chunk.length++;
132 }
133
134 if (chunk.type==SSND) {
135 snd_found=True;
136 count=chunk.length;
137
138 /* COMM Chunk was above -> break, else search for */
139 if (com_found) {
140 /* offset and block_size following after chunk length */
141 if ((i=read(af->fd,&offset,sizeof(offset)))!=sizeof(offset))
142 return(AF_ERROR);
143 if ((i=read(af->fd,&block_size,sizeof(block_size)))
144 !=sizeof(block_size)) return(AF_ERROR);
145 if ((i=lseek(af->fd,0,SEEK_CUR))==-1) return(AF_ERROR);
146 af->headoffs=i;
147 break;
148 }
149 }
150 if ((lseek(af->fd,chunk.length,SEEK_CUR))==-1) return(AF_ERROR);
151 }
152
153 af->freq=(int) ConvertFromIeeeExtended(freq);
154 af->bps=bps;
155 af->channels=channels;
156 af->comp=comp_typ;
157 af->type=AF_AIFC;
158 /* offset+block_size=8 */
159 af->length=count-8;
160
161 switch (comp_typ) {
162 case AIFF:
163 case CNONE:
164 af->comp=AF_PCM;
165 break;
166 default:
167 return(AF_NOTSUPPORTED);
168 }
169
170 return(AF_AIFC);
171 }
172
aifc_new(Audio_File * af)173 int aifc_new(Audio_File *af)
174 {
175 Aif_Form form;
176 Aif_Chunk chunk;
177 Com_Chunk com;
178 int headoffs=0;
179 char freq[10];
180 ulong stamp,offset,block_size;
181 int i;
182
183 com.channels=af->channels;
184 com.s_frames=af->length/(af->bps/8)/af->channels;
185 com.bps=af->bps;
186 com.freq=af->freq;
187 com.comp_typ=af->comp;
188 com.pstring=NULL;
189
190 form.form=FORM;
191 form.type=AIFC;
192 /* FORM and length are not in chunk length, but AIFC is */
193 form.length=sizeof(form.type);
194
195 if ((i=write(af->fd,&form,sizeof(form)))!=sizeof(form))
196 return(AF_ERROR);
197 headoffs+=i;
198
199 /* FVER chunk */
200 chunk.type=FVER;
201 stamp=AIFCVERSION_1;
202 chunk.length=sizeof(stamp);
203 #ifdef little_endianN
204 M_32_SWAP(chunk.type);
205 M_32_SWAP(chunk.length);
206 M_32_SWAP(stamp);
207 #endif
208 if ((i=write(af->fd,&chunk,sizeof(chunk)))!=sizeof(chunk))
209 return(AF_ERROR);
210 headoffs+=i;
211 if ((i=write(af->fd,&stamp,sizeof(stamp)))!=sizeof(stamp))
212 return(AF_ERROR);
213 headoffs+=i;
214
215 /* COMM chunk */
216 chunk.type=COMM;
217 chunk.length=COMMLENGTH+sizeof(com.comp_typ);
218 switch (com.comp_typ) {
219 case AF_PCM:
220 if ((com.pstring=malloc(strlen(CNONESTR)))==NULL) return(AF_ERROR);
221 strcpy(com.pstring,CNONESTR);
222 com.plength=strlen(com.pstring);
223 com.comp_typ=CNONE;
224 chunk.length+=sizeof(com.plength)+com.plength;
225 chunk.length+=(chunk.length % 2);
226 break;
227 default:
228 return(AF_ERROR);
229 }
230
231 #ifdef little_endianN
232 M_32_SWAP(chunk.type);
233 M_32_SWAP(chunk.length);
234 M_16_SWAP(com.channels);
235 M_32_SWAP(com.s_frames);
236 M_16_SWAP(com.bps);
237 M_32_SWAP(com.comp_typ);
238 #endif
239 ConvertToIeeeExtended(com.freq,freq);
240
241 i=write(af->fd,&chunk,sizeof(chunk));headoffs+=i;
242 i=write(af->fd,&com.channels,sizeof(com.channels));headoffs+=i;
243 i=write(af->fd,&com.s_frames,sizeof(com.s_frames));headoffs+=i;
244 i=write(af->fd,&com.bps,sizeof(com.bps));headoffs+=i;
245 i=write(af->fd,&freq,sizeof(freq));headoffs+=i;
246 i=write(af->fd,&com.comp_typ,sizeof(com.comp_typ));headoffs+=i;
247 i=write(af->fd,&com.plength,sizeof(com.plength));headoffs+=i;
248 i=write(af->fd,com.pstring,com.plength);headoffs+=i;
249
250 /* pad byte, odd because com.plength is 1 byte */
251 if (!(com.plength % 2)) {
252 unsigned char pad=0;
253 i=write(af->fd,&pad,sizeof(pad));headoffs+=i;
254 }
255
256 if (i==-1) {
257 if (com.pstring!=NULL) free(com.pstring);
258 return(AF_ERROR);
259 }
260
261 /* Pad byte if write chunk again, after some sound data is written */
262 if (af->length>0) if (af->length % 2) af->length++;
263
264 /* SSND chunk */
265
266 chunk.type=SSND;
267 chunk.length=af->length+sizeof(offset)+sizeof(block_size);
268 offset=0;
269 block_size=0;
270
271 #ifdef little_endianN
272 M_32_SWAP(chunk.type);
273 M_32_SWAP(chunk.length);
274 M_32_SWAP(offset);
275 M_32_SWAP(block_size);
276 #endif
277
278 i=write(af->fd,&chunk,sizeof(chunk));headoffs+=i;
279 i=write(af->fd,&offset,sizeof(offset));headoffs+=i;
280 i=write(af->fd,&block_size,sizeof(block_size));headoffs+=i;
281 if (i==-1) {
282 if (com.pstring!=NULL) free(com.pstring);
283 return(AF_ERROR);
284 }
285
286 form.length=headoffs+af->length-sizeof(form.form)-sizeof(form.length);
287
288 #ifdef little_endianN
289 M_32_SWAP(form.form);
290 M_32_SWAP(form.length);
291 M_32_SWAP(form.type);
292 #endif
293
294 if (aifc_seek(*af,0,SEEK_SET)==AF_ERROR) {
295 if (com.pstring!=NULL) free(com.pstring);
296 return(AF_ERROR);
297 }
298
299 if ((write(af->fd,&form,sizeof(form)))!=sizeof(form)) {
300 if (com.pstring!=NULL) free(com.pstring);
301 return(AF_ERROR);
302 }
303
304 if (aifc_seek(*af,headoffs,SEEK_SET)==AF_ERROR) {
305 if (com.pstring!=NULL) free(com.pstring);
306 return(AF_ERROR);
307 }
308
309 af->headoffs=headoffs;
310 return(AF_AIFC);
311 }
312
aifc_read(Audio_File af,char * buffer,int size)313 int aifc_read(Audio_File af,char *buffer,int size)
314 {
315 if ((size=read(af.fd,buffer,size))==-1) return (AF_ERROR);
316 #ifdef little_endianN
317 /* swap byte order in 16bit sample */
318 if (af.bps==16) {
319 register int _tmp,i;
320 for (i=0;i<size;i+=2) {
321 _tmp=buffer[i+1];
322 buffer[i+1]=buffer[i];
323 buffer[i]=_tmp;
324 }
325 }
326 #endif
327 return(size);
328 }
329
aifc_write(Audio_File af,char * buffer,int size)330 int aifc_write(Audio_File af,char *buffer,int size)
331 {
332 #ifdef little_endianN
333 /* swap byte order in 16bit sample */
334 if (af.bps==16) {
335 register int _tmp,i;
336 for (i=0;i<size;i+=2) {
337 _tmp=buffer[i+1];
338 buffer[i+1]=buffer[i];
339 buffer[i]=_tmp;
340 }
341 }
342 #endif
343 if ((size=write(af.fd,buffer,size))==-1) return (AF_ERROR);
344 return(size);
345 }
346
aifc_seek(Audio_File af,int pos,int mode)347 int aifc_seek(Audio_File af,int pos,int mode)
348 {
349 switch (af.comp) {
350 case AF_PCM:
351 return(lseek(af.fd,pos,mode));
352 }
353 return(AF_ERROR);
354 }
355
aifc_close(Audio_File af)356 int aifc_close(Audio_File af)
357 {
358 if (aifc_seek(af,0,SEEK_SET)==AF_ERROR) return(AF_ERROR);
359 if (aifc_new (&af)==AF_ERROR) return(AF_ERROR);
360 return(close(af.fd));
361 }
362
363
364
365