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