Imported Upstream version 1.0.25
[platform/upstream/libsndfile.git] / src / au.c
1 /*
2 ** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
3 **
4 ** This program is free software; you can redistribute it and/or modify
5 ** it under the terms of the GNU Lesser General Public License as published by
6 ** the Free Software Foundation; either version 2.1 of the License, or
7 ** (at your option) any later version.
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 ** GNU Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public License
15 ** along with this program; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include        "sfconfig.h"
20
21 #include        <stdio.h>
22 #include        <fcntl.h>
23 #include        <string.h>
24 #include        <ctype.h>
25
26 #include        "sndfile.h"
27 #include        "sfendian.h"
28 #include        "common.h"
29
30 /*------------------------------------------------------------------------------
31 ** Macros to handle big/little endian issues.
32 */
33
34 #define DOTSND_MARKER   (MAKE_MARKER ('.', 's', 'n', 'd'))
35 #define DNSDOT_MARKER   (MAKE_MARKER ('d', 'n', 's', '.'))
36
37 #define AU_DATA_OFFSET  24
38
39 /*------------------------------------------------------------------------------
40 ** Known AU file encoding types.
41 */
42
43 enum
44 {       AU_ENCODING_ULAW_8                                      = 1,    /* 8-bit u-law samples */
45         AU_ENCODING_PCM_8                                       = 2,    /* 8-bit linear samples */
46         AU_ENCODING_PCM_16                                      = 3,    /* 16-bit linear samples */
47         AU_ENCODING_PCM_24                                      = 4,    /* 24-bit linear samples */
48         AU_ENCODING_PCM_32                                      = 5,    /* 32-bit linear samples */
49
50         AU_ENCODING_FLOAT                                       = 6,    /* floating-point samples */
51         AU_ENCODING_DOUBLE                                      = 7,    /* double-precision float samples */
52         AU_ENCODING_INDIRECT                            = 8,    /* fragmented sampled data */
53         AU_ENCODING_NESTED                                      = 9,    /* ? */
54         AU_ENCODING_DSP_CORE                            = 10,   /* DSP program */
55         AU_ENCODING_DSP_DATA_8                          = 11,   /* 8-bit fixed-point samples */
56         AU_ENCODING_DSP_DATA_16                         = 12,   /* 16-bit fixed-point samples */
57         AU_ENCODING_DSP_DATA_24                         = 13,   /* 24-bit fixed-point samples */
58         AU_ENCODING_DSP_DATA_32                         = 14,   /* 32-bit fixed-point samples */
59
60         AU_ENCODING_DISPLAY                                     = 16,   /* non-audio display data */
61         AU_ENCODING_MULAW_SQUELCH                       = 17,   /* ? */
62         AU_ENCODING_EMPHASIZED                          = 18,   /* 16-bit linear with emphasis */
63         AU_ENCODING_NEXT                                        = 19,   /* 16-bit linear with compression (NEXT) */
64         AU_ENCODING_COMPRESSED_EMPHASIZED       = 20,   /* A combination of the two above */
65         AU_ENCODING_DSP_COMMANDS                        = 21,   /* Music Kit DSP commands */
66         AU_ENCODING_DSP_COMMANDS_SAMPLES        = 22,   /* ? */
67
68         AU_ENCODING_ADPCM_G721_32                       = 23,   /* G721 32 kbs ADPCM - 4 bits per sample. */
69         AU_ENCODING_ADPCM_G722                          = 24,   /* G722 64 kbs ADPCM */
70         AU_ENCODING_ADPCM_G723_24                       = 25,   /* G723 24 kbs ADPCM - 3 bits per sample. */
71         AU_ENCODING_ADPCM_G723_40                       = 26,   /* G723 40 kbs ADPCM - 5 bits per sample. */
72
73         AU_ENCODING_ALAW_8                                      = 27
74 } ;
75
76 /*------------------------------------------------------------------------------
77 ** Typedefs.
78 */
79
80 typedef struct
81 {       int             dataoffset ;
82         int             datasize ;
83         int             encoding ;
84     int         samplerate ;
85     int         channels ;
86 } AU_FMT ;
87
88
89 /*------------------------------------------------------------------------------
90 ** Private static functions.
91 */
92
93 static  int             au_close                (SF_PRIVATE *psf) ;
94
95 static  int     au_format_to_encoding   (int format) ;
96
97 static int              au_write_header (SF_PRIVATE *psf, int calc_length) ;
98 static int              au_read_header (SF_PRIVATE *psf) ;
99
100 /*------------------------------------------------------------------------------
101 ** Public function.
102 */
103
104 int
105 au_open (SF_PRIVATE *psf)
106 {       int             subformat ;
107         int             error = 0 ;
108
109         if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
110         {       if ((error = au_read_header (psf)))
111                         return error ;
112                 } ;
113
114         if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_AU)
115                 return  SFE_BAD_OPEN_FORMAT ;
116
117         subformat = SF_CODEC (psf->sf.format) ;
118
119         if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
120         {       psf->endian = SF_ENDIAN (psf->sf.format) ;
121                 if (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU)
122                         psf->endian = SF_ENDIAN_LITTLE ;
123                 else if (psf->endian != SF_ENDIAN_LITTLE)
124                         psf->endian = SF_ENDIAN_BIG ;
125
126                 if (au_write_header (psf, SF_FALSE))
127                         return psf->error ;
128
129                 psf->write_header = au_write_header ;
130                 } ;
131
132         psf->container_close = au_close ;
133
134         psf->blockwidth = psf->bytewidth * psf->sf.channels ;
135
136         switch (subformat)
137         {       case SF_FORMAT_ULAW :   /* 8-bit Ulaw encoding. */
138                                 ulaw_init (psf) ;
139                                 break ;
140
141                 case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */
142                                 error = pcm_init (psf) ;
143                                 break ;
144
145                 case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
146                 case SF_FORMAT_PCM_24 : /* 24-bit linear PCM */
147                 case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */
148                                 error = pcm_init (psf) ;
149                                 break ;
150
151                 case SF_FORMAT_ALAW :   /* 8-bit Alaw encoding. */
152                                 alaw_init (psf) ;
153                                 break ;
154
155                 /* Lite remove start */
156                 case SF_FORMAT_FLOAT :  /* 32-bit floats. */
157                                 error = float32_init (psf) ;
158                                 break ;
159
160                 case SF_FORMAT_DOUBLE : /* 64-bit double precision floats. */
161                                 error = double64_init (psf) ;
162                                 break ;
163
164                 case SF_FORMAT_G721_32 :
165                                 error = g72x_init (psf) ;
166                                 psf->sf.seekable = SF_FALSE ;
167                                 break ;
168
169                 case SF_FORMAT_G723_24 :
170                                 error = g72x_init (psf) ;
171                                 psf->sf.seekable = SF_FALSE ;
172                                 break ;
173
174                 case SF_FORMAT_G723_40 :
175                                 error = g72x_init (psf) ;
176                                 psf->sf.seekable = SF_FALSE ;
177                                 break ;
178                 /* Lite remove end */
179
180                 default :       break ;
181                 } ;
182
183         return error ;
184 } /* au_open */
185
186 /*------------------------------------------------------------------------------
187 */
188
189 static int
190 au_close        (SF_PRIVATE *psf)
191 {
192         if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
193                 au_write_header (psf, SF_TRUE) ;
194
195         return 0 ;
196 } /* au_close */
197
198 static int
199 au_write_header (SF_PRIVATE *psf, int calc_length)
200 {       sf_count_t      current ;
201         int                     encoding, datalength ;
202
203         if (psf->pipeoffset > 0)
204                 return 0 ;
205
206         current = psf_ftell (psf) ;
207
208         if (calc_length)
209         {       psf->filelength = psf_get_filelen (psf) ;
210
211                 psf->datalength = psf->filelength - psf->dataoffset ;
212                 if (psf->dataend)
213                         psf->datalength -= psf->filelength - psf->dataend ;
214
215                 psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
216                 } ;
217
218         encoding = au_format_to_encoding (SF_CODEC (psf->sf.format)) ;
219         if (! encoding)
220                 return (psf->error = SFE_BAD_OPEN_FORMAT) ;
221
222         /* Reset the current header length to zero. */
223         psf->header [0] = 0 ;
224         psf->headindex = 0 ;
225
226         /*
227         ** Only attempt to seek if we are not writng to a pipe. If we are
228         ** writing to a pipe we shouldn't be here anyway.
229         */
230         if (psf->is_pipe == SF_FALSE)
231                 psf_fseek (psf, 0, SEEK_SET) ;
232
233         /*
234         **      AU format files allow a datalength value of -1 if the datalength
235         **      is not know at the time the header is written.
236         **      Also use this value of -1 if the datalength > 2 gigabytes.
237         */
238         if (psf->datalength     < 0 || psf->datalength > 0x7FFFFFFF)
239                 datalength = -1 ;
240         else
241                 datalength = (int) (psf->datalength & 0x7FFFFFFF) ;
242
243         if (psf->endian == SF_ENDIAN_BIG)
244         {       psf_binheader_writef (psf, "Em4", DOTSND_MARKER, AU_DATA_OFFSET) ;
245                 psf_binheader_writef (psf, "E4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ;
246                 }
247         else if (psf->endian == SF_ENDIAN_LITTLE)
248         {       psf_binheader_writef (psf, "em4", DNSDOT_MARKER, AU_DATA_OFFSET) ;
249                 psf_binheader_writef (psf, "e4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ;
250                 }
251         else
252                 return (psf->error = SFE_BAD_OPEN_FORMAT) ;
253
254         /* Header construction complete so write it out. */
255         psf_fwrite (psf->header, psf->headindex, 1, psf) ;
256
257         if (psf->error)
258                 return psf->error ;
259
260         psf->dataoffset = psf->headindex ;
261
262         if (current > 0)
263                 psf_fseek (psf, current, SEEK_SET) ;
264
265         return psf->error ;
266 } /* au_write_header */
267
268 static int
269 au_format_to_encoding (int format)
270 {
271         switch (format)
272         {       case SF_FORMAT_PCM_S8 :         return AU_ENCODING_PCM_8 ;
273                 case SF_FORMAT_PCM_16 :         return AU_ENCODING_PCM_16 ;
274                 case SF_FORMAT_PCM_24 :         return AU_ENCODING_PCM_24 ;
275                 case SF_FORMAT_PCM_32 :         return AU_ENCODING_PCM_32 ;
276
277                 case SF_FORMAT_FLOAT :          return AU_ENCODING_FLOAT ;
278                 case SF_FORMAT_DOUBLE :         return AU_ENCODING_DOUBLE ;
279
280                 case SF_FORMAT_ULAW :           return AU_ENCODING_ULAW_8 ;
281                 case SF_FORMAT_ALAW :           return AU_ENCODING_ALAW_8 ;
282
283                 case SF_FORMAT_G721_32 :        return AU_ENCODING_ADPCM_G721_32 ;
284                 case SF_FORMAT_G723_24 :        return AU_ENCODING_ADPCM_G723_24 ;
285                 case SF_FORMAT_G723_40 :        return AU_ENCODING_ADPCM_G723_40 ;
286
287                 default : break ;
288                 } ;
289         return 0 ;
290 } /* au_format_to_encoding */
291
292 static int
293 au_read_header (SF_PRIVATE *psf)
294 {       AU_FMT  au_fmt ;
295         int             marker, dword ;
296
297         memset (&au_fmt, 0, sizeof (au_fmt)) ;
298         psf_binheader_readf (psf, "pm", 0, &marker) ;
299         psf_log_printf (psf, "%M\n", marker) ;
300
301         if (marker == DOTSND_MARKER)
302         {       psf->endian = SF_ENDIAN_BIG ;
303
304                 psf_binheader_readf (psf, "E44444", &(au_fmt.dataoffset), &(au_fmt.datasize),
305                                         &(au_fmt.encoding), &(au_fmt.samplerate), &(au_fmt.channels)) ;
306                 }
307         else if (marker == DNSDOT_MARKER)
308         {       psf->endian = SF_ENDIAN_LITTLE ;
309                 psf_binheader_readf (psf, "e44444", &(au_fmt.dataoffset), &(au_fmt.datasize),
310                                         &(au_fmt.encoding), &(au_fmt.samplerate), &(au_fmt.channels)) ;
311                 }
312         else
313                 return SFE_AU_NO_DOTSND ;
314
315         psf_log_printf (psf, "  Data Offset : %d\n", au_fmt.dataoffset) ;
316
317         if (psf->fileoffset > 0 && au_fmt.datasize == -1)
318         {       psf_log_printf (psf, "  Data Size   : -1\n") ;
319                 return SFE_AU_EMBED_BAD_LEN ;
320                 } ;
321
322         if (psf->fileoffset > 0)
323         {       psf->filelength = au_fmt.dataoffset + au_fmt.datasize ;
324                 psf_log_printf (psf, "  Data Size   : %d\n", au_fmt.datasize) ;
325                 }
326         else if (au_fmt.datasize == -1 || au_fmt.dataoffset + au_fmt.datasize == psf->filelength)
327                 psf_log_printf (psf, "  Data Size   : %d\n", au_fmt.datasize) ;
328         else if (au_fmt.dataoffset + au_fmt.datasize < psf->filelength)
329         {       psf->filelength = au_fmt.dataoffset + au_fmt.datasize ;
330                 psf_log_printf (psf, "  Data Size   : %d\n", au_fmt.datasize) ;
331                 }
332         else
333         {       dword = psf->filelength - au_fmt.dataoffset ;
334                 psf_log_printf (psf, "  Data Size   : %d (should be %d)\n", au_fmt.datasize, dword) ;
335                 au_fmt.datasize = dword ;
336                 } ;
337
338         psf->dataoffset = au_fmt.dataoffset ;
339         psf->datalength = psf->filelength - psf->dataoffset ;
340
341         if (psf_ftell (psf) < psf->dataoffset)
342                 psf_binheader_readf (psf, "j", psf->dataoffset - psf_ftell (psf)) ;
343
344         psf->sf.samplerate      = au_fmt.samplerate ;
345         psf->sf.channels        = au_fmt.channels ;
346
347         /* Only fill in type major. */
348         if (psf->endian == SF_ENDIAN_BIG)
349                 psf->sf.format = SF_FORMAT_AU ;
350         else if (psf->endian == SF_ENDIAN_LITTLE)
351                 psf->sf.format = SF_ENDIAN_LITTLE | SF_FORMAT_AU ;
352
353         psf_log_printf (psf, "  Encoding    : %d => ", au_fmt.encoding) ;
354
355         psf->sf.format = SF_ENDIAN (psf->sf.format) ;
356
357         switch (au_fmt.encoding)
358         {       case AU_ENCODING_ULAW_8 :
359                                 psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_ULAW ;
360                                 psf->bytewidth = 1 ;    /* Before decoding */
361                                 psf_log_printf (psf, "8-bit ISDN u-law\n") ;
362                                 break ;
363
364                 case AU_ENCODING_PCM_8 :
365                                 psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_S8 ;
366                                 psf->bytewidth = 1 ;
367                                 psf_log_printf (psf, "8-bit linear PCM\n") ;
368                                 break ;
369
370                 case AU_ENCODING_PCM_16 :
371                                 psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_16 ;
372                                 psf->bytewidth = 2 ;
373                                 psf_log_printf (psf, "16-bit linear PCM\n") ;
374                                 break ;
375
376                 case AU_ENCODING_PCM_24 :
377                                 psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_24 ;
378                                 psf->bytewidth = 3 ;
379                                 psf_log_printf (psf, "24-bit linear PCM\n") ;
380                                 break ;
381
382                 case AU_ENCODING_PCM_32 :
383                                 psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_32 ;
384                                 psf->bytewidth = 4 ;
385                                 psf_log_printf (psf, "32-bit linear PCM\n") ;
386                                 break ;
387
388                 case AU_ENCODING_FLOAT :
389                                 psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_FLOAT ;
390                                 psf->bytewidth = 4 ;
391                                 psf_log_printf (psf, "32-bit float\n") ;
392                                 break ;
393
394                 case AU_ENCODING_DOUBLE :
395                                 psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_DOUBLE ;
396                                 psf->bytewidth = 8 ;
397                                 psf_log_printf (psf, "64-bit double precision float\n") ;
398                                 break ;
399
400                 case AU_ENCODING_ALAW_8 :
401                                 psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_ALAW ;
402                                 psf->bytewidth = 1 ;    /* Before decoding */
403                                 psf_log_printf (psf, "8-bit ISDN A-law\n") ;
404                                 break ;
405
406                 case AU_ENCODING_ADPCM_G721_32 :
407                                 psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G721_32 ;
408                                 psf->bytewidth = 0 ;
409                                 psf_log_printf (psf, "G721 32kbs ADPCM\n") ;
410                                 break ;
411
412                 case AU_ENCODING_ADPCM_G723_24 :
413                                 psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G723_24 ;
414                                 psf->bytewidth = 0 ;
415                                 psf_log_printf (psf, "G723 24kbs ADPCM\n") ;
416                                 break ;
417
418                 case AU_ENCODING_ADPCM_G723_40 :
419                                 psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G723_40 ;
420                                 psf->bytewidth = 0 ;
421                                 psf_log_printf (psf, "G723 40kbs ADPCM\n") ;
422                                 break ;
423
424                 case AU_ENCODING_ADPCM_G722 :
425                                 psf_log_printf (psf, "G722 64 kbs ADPCM (unsupported)\n") ;
426                                 break ;
427
428                 case AU_ENCODING_NEXT :
429                                 psf_log_printf (psf, "Weird NeXT encoding format (unsupported)\n") ;
430                                 break ;
431
432                 default :
433                                 psf_log_printf (psf, "Unknown!!\n") ;
434                                 break ;
435                 } ;
436
437         psf_log_printf (psf, "  Sample Rate : %d\n", au_fmt.samplerate) ;
438         if (au_fmt.channels < 1)
439         {       psf_log_printf (psf, "  Channels    : %d  **** should be >= 1\n", au_fmt.channels) ;
440                 return SFE_CHANNEL_COUNT_ZERO ;
441                 }
442         else
443                 psf_log_printf (psf, "  Channels    : %d\n", au_fmt.channels) ;
444
445         psf->blockwidth = psf->sf.channels * psf->bytewidth ;
446
447         if (! psf->sf.frames && psf->blockwidth)
448                 psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
449
450         return 0 ;
451 } /* au_read_header */
452