2 ** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
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.
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.
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.
30 /*------------------------------------------------------------------------------
31 ** Macros to handle big/little endian issues.
34 #define DOTSND_MARKER (MAKE_MARKER ('.', 's', 'n', 'd'))
35 #define DNSDOT_MARKER (MAKE_MARKER ('d', 'n', 's', '.'))
37 #define AU_DATA_OFFSET 24
39 /*------------------------------------------------------------------------------
40 ** Known AU file encoding types.
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 */
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 */
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, /* ? */
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. */
73 AU_ENCODING_ALAW_8
= 27
76 /*------------------------------------------------------------------------------
89 /*------------------------------------------------------------------------------
90 ** Private static functions.
93 static int au_close (SF_PRIVATE
*psf
) ;
95 static int au_format_to_encoding (int format
) ;
97 static int au_write_header (SF_PRIVATE
*psf
, int calc_length
) ;
98 static int au_read_header (SF_PRIVATE
*psf
) ;
100 /*------------------------------------------------------------------------------
105 au_open (SF_PRIVATE
*psf
)
109 if (psf
->file
.mode
== SFM_READ
|| (psf
->file
.mode
== SFM_RDWR
&& psf
->filelength
> 0))
110 { if ((error
= au_read_header (psf
)))
114 if ((SF_CONTAINER (psf
->sf
.format
)) != SF_FORMAT_AU
)
115 return SFE_BAD_OPEN_FORMAT
;
117 subformat
= SF_CODEC (psf
->sf
.format
) ;
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
;
126 if (au_write_header (psf
, SF_FALSE
))
129 psf
->write_header
= au_write_header
;
132 psf
->container_close
= au_close
;
134 psf
->blockwidth
= psf
->bytewidth
* psf
->sf
.channels
;
137 { case SF_FORMAT_ULAW
: /* 8-bit Ulaw encoding. */
141 case SF_FORMAT_PCM_S8
: /* 8-bit linear PCM. */
142 error
= pcm_init (psf
) ;
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
) ;
151 case SF_FORMAT_ALAW
: /* 8-bit Alaw encoding. */
155 /* Lite remove start */
156 case SF_FORMAT_FLOAT
: /* 32-bit floats. */
157 error
= float32_init (psf
) ;
160 case SF_FORMAT_DOUBLE
: /* 64-bit double precision floats. */
161 error
= double64_init (psf
) ;
164 case SF_FORMAT_G721_32
:
165 error
= g72x_init (psf
) ;
166 psf
->sf
.seekable
= SF_FALSE
;
169 case SF_FORMAT_G723_24
:
170 error
= g72x_init (psf
) ;
171 psf
->sf
.seekable
= SF_FALSE
;
174 case SF_FORMAT_G723_40
:
175 error
= g72x_init (psf
) ;
176 psf
->sf
.seekable
= SF_FALSE
;
178 /* Lite remove end */
186 /*------------------------------------------------------------------------------
190 au_close (SF_PRIVATE
*psf
)
192 if (psf
->file
.mode
== SFM_WRITE
|| psf
->file
.mode
== SFM_RDWR
)
193 au_write_header (psf
, SF_TRUE
) ;
199 au_write_header (SF_PRIVATE
*psf
, int calc_length
)
200 { sf_count_t current
;
201 int encoding
, datalength
;
203 if (psf
->pipeoffset
> 0)
206 current
= psf_ftell (psf
) ;
209 { psf
->filelength
= psf_get_filelen (psf
) ;
211 psf
->datalength
= psf
->filelength
- psf
->dataoffset
;
213 psf
->datalength
-= psf
->filelength
- psf
->dataend
;
215 psf
->sf
.frames
= psf
->datalength
/ (psf
->bytewidth
* psf
->sf
.channels
) ;
218 encoding
= au_format_to_encoding (SF_CODEC (psf
->sf
.format
)) ;
220 return (psf
->error
= SFE_BAD_OPEN_FORMAT
) ;
222 /* Reset the current header length to zero. */
223 psf
->header
[0] = 0 ;
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.
230 if (psf
->is_pipe
== SF_FALSE
)
231 psf_fseek (psf
, 0, SEEK_SET
) ;
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.
238 if (psf
->datalength
< 0 || psf
->datalength
> 0x7FFFFFFF)
241 datalength
= (int) (psf
->datalength
& 0x7FFFFFFF) ;
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
) ;
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
) ;
252 return (psf
->error
= SFE_BAD_OPEN_FORMAT
) ;
254 /* Header construction complete so write it out. */
255 psf_fwrite (psf
->header
, psf
->headindex
, 1, psf
) ;
260 psf
->dataoffset
= psf
->headindex
;
263 psf_fseek (psf
, current
, SEEK_SET
) ;
266 } /* au_write_header */
269 au_format_to_encoding (int 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
;
277 case SF_FORMAT_FLOAT
: return AU_ENCODING_FLOAT
;
278 case SF_FORMAT_DOUBLE
: return AU_ENCODING_DOUBLE
;
280 case SF_FORMAT_ULAW
: return AU_ENCODING_ULAW_8
;
281 case SF_FORMAT_ALAW
: return AU_ENCODING_ALAW_8
;
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
;
290 } /* au_format_to_encoding */
293 au_read_header (SF_PRIVATE
*psf
)
297 memset (&au_fmt
, 0, sizeof (au_fmt
)) ;
298 psf_binheader_readf (psf
, "pm", 0, &marker
) ;
299 psf_log_printf (psf
, "%M\n", marker
) ;
301 if (marker
== DOTSND_MARKER
)
302 { psf
->endian
= SF_ENDIAN_BIG
;
304 psf_binheader_readf (psf
, "E44444", &(au_fmt
.dataoffset
), &(au_fmt
.datasize
),
305 &(au_fmt
.encoding
), &(au_fmt
.samplerate
), &(au_fmt
.channels
)) ;
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
)) ;
313 return SFE_AU_NO_DOTSND
;
315 psf_log_printf (psf
, " Data Offset : %d\n", au_fmt
.dataoffset
) ;
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
;
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
) ;
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
) ;
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
;
338 psf
->dataoffset
= au_fmt
.dataoffset
;
339 psf
->datalength
= psf
->filelength
- psf
->dataoffset
;
341 if (psf_ftell (psf
) < psf
->dataoffset
)
342 psf_binheader_readf (psf
, "j", psf
->dataoffset
- psf_ftell (psf
)) ;
344 psf
->sf
.samplerate
= au_fmt
.samplerate
;
345 psf
->sf
.channels
= au_fmt
.channels
;
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
;
353 psf_log_printf (psf
, " Encoding : %d => ", au_fmt
.encoding
) ;
355 psf
->sf
.format
= SF_ENDIAN (psf
->sf
.format
) ;
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") ;
364 case AU_ENCODING_PCM_8
:
365 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_PCM_S8
;
367 psf_log_printf (psf
, "8-bit linear PCM\n") ;
370 case AU_ENCODING_PCM_16
:
371 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_PCM_16
;
373 psf_log_printf (psf
, "16-bit linear PCM\n") ;
376 case AU_ENCODING_PCM_24
:
377 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_PCM_24
;
379 psf_log_printf (psf
, "24-bit linear PCM\n") ;
382 case AU_ENCODING_PCM_32
:
383 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_PCM_32
;
385 psf_log_printf (psf
, "32-bit linear PCM\n") ;
388 case AU_ENCODING_FLOAT
:
389 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_FLOAT
;
391 psf_log_printf (psf
, "32-bit float\n") ;
394 case AU_ENCODING_DOUBLE
:
395 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_DOUBLE
;
397 psf_log_printf (psf
, "64-bit double precision float\n") ;
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") ;
406 case AU_ENCODING_ADPCM_G721_32
:
407 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_G721_32
;
409 psf_log_printf (psf
, "G721 32kbs ADPCM\n") ;
412 case AU_ENCODING_ADPCM_G723_24
:
413 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_G723_24
;
415 psf_log_printf (psf
, "G723 24kbs ADPCM\n") ;
418 case AU_ENCODING_ADPCM_G723_40
:
419 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_G723_40
;
421 psf_log_printf (psf
, "G723 40kbs ADPCM\n") ;
424 case AU_ENCODING_ADPCM_G722
:
425 psf_log_printf (psf
, "G722 64 kbs ADPCM (unsupported)\n") ;
428 case AU_ENCODING_NEXT
:
429 psf_log_printf (psf
, "Weird NeXT encoding format (unsupported)\n") ;
433 psf_log_printf (psf
, "Unknown!!\n") ;
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
;
443 psf_log_printf (psf
, " Channels : %d\n", au_fmt
.channels
) ;
445 psf
->blockwidth
= psf
->sf
.channels
* psf
->bytewidth
;
447 if (! psf
->sf
.frames
&& psf
->blockwidth
)
448 psf
->sf
.frames
= (psf
->filelength
- psf
->dataoffset
) / psf
->blockwidth
;
451 } /* au_read_header */