2 ** Copyright (C) 1999-2003 Erik de Castro Lopo <erikd@zip.com.au>
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.
31 /*------------------------------------------------------------------------------
32 ** Macros to handle big/little endian issues.
35 #define DOTSND_MARKER (MAKE_MARKER ('.', 's', 'n', 'd'))
36 #define DNSDOT_MARKER (MAKE_MARKER ('d', 'n', 's', '.'))
38 #define AU_DATA_OFFSET 24
40 /*------------------------------------------------------------------------------
41 ** Known AU file encoding types.
45 { AU_ENCODING_ULAW_8
= 1, /* 8-bit u-law samples */
46 AU_ENCODING_PCM_8
= 2, /* 8-bit linear samples */
47 AU_ENCODING_PCM_16
= 3, /* 16-bit linear samples */
48 AU_ENCODING_PCM_24
= 4, /* 24-bit linear samples */
49 AU_ENCODING_PCM_32
= 5, /* 32-bit linear samples */
51 AU_ENCODING_FLOAT
= 6, /* floating-point samples */
52 AU_ENCODING_DOUBLE
= 7, /* double-precision float samples */
53 AU_ENCODING_INDIRECT
= 8, /* fragmented sampled data */
54 AU_ENCODING_NESTED
= 9, /* ? */
55 AU_ENCODING_DSP_CORE
= 10, /* DSP program */
56 AU_ENCODING_DSP_DATA_8
= 11, /* 8-bit fixed-point samples */
57 AU_ENCODING_DSP_DATA_16
= 12, /* 16-bit fixed-point samples */
58 AU_ENCODING_DSP_DATA_24
= 13, /* 24-bit fixed-point samples */
59 AU_ENCODING_DSP_DATA_32
= 14, /* 32-bit fixed-point samples */
61 AU_ENCODING_DISPLAY
= 16, /* non-audio display data */
62 AU_ENCODING_MULAW_SQUELCH
= 17, /* ? */
63 AU_ENCODING_EMPHASIZED
= 18, /* 16-bit linear with emphasis */
64 AU_ENCODING_NEXT
= 19, /* 16-bit linear with compression (NEXT) */
65 AU_ENCODING_COMPRESSED_EMPHASIZED
= 20, /* A combination of the two above */
66 AU_ENCODING_DSP_COMMANDS
= 21, /* Music Kit DSP commands */
67 AU_ENCODING_DSP_COMMANDS_SAMPLES
= 22, /* ? */
69 AU_ENCODING_ADPCM_G721_32
= 23, /* G721 32 kbs ADPCM - 4 bits per sample. */
70 AU_ENCODING_ADPCM_G722
= 24, /* G722 64 kbs ADPCM */
71 AU_ENCODING_ADPCM_G723_24
= 25, /* G723 24 kbs ADPCM - 3 bits per sample. */
72 AU_ENCODING_ADPCM_G723_40
= 26, /* G723 40 kbs ADPCM - 5 bits per sample. */
74 AU_ENCODING_ALAW_8
= 27
77 /*------------------------------------------------------------------------------
90 /*------------------------------------------------------------------------------
91 ** Private static functions.
94 static int au_close (SF_PRIVATE
*psf
) ;
96 static int au_format_to_encoding (int format
) ;
98 static int au_write_header (SF_PRIVATE
*psf
, int calc_length
) ;
99 static int au_read_header (SF_PRIVATE
*psf
) ;
101 /*------------------------------------------------------------------------------
106 au_open (SF_PRIVATE
*psf
)
110 if (psf
->mode
== SFM_READ
|| (psf
->mode
== SFM_RDWR
&& psf
->filelength
> 0))
111 { if ((error
= au_read_header (psf
)))
115 if ((psf
->sf
.format
& SF_FORMAT_TYPEMASK
) != SF_FORMAT_AU
)
116 return SFE_BAD_OPEN_FORMAT
;
118 subformat
= psf
->sf
.format
& SF_FORMAT_SUBMASK
;
120 if (psf
->mode
== SFM_WRITE
|| psf
->mode
== SFM_RDWR
)
121 { psf
->endian
= psf
->sf
.format
& SF_FORMAT_ENDMASK
;
122 if (CPU_IS_LITTLE_ENDIAN
&& psf
->endian
== SF_ENDIAN_CPU
)
123 psf
->endian
= SF_ENDIAN_LITTLE
;
124 else if (psf
->endian
!= SF_ENDIAN_LITTLE
)
125 psf
->endian
= SF_ENDIAN_BIG
;
127 if (au_write_header (psf
, SF_FALSE
))
130 psf
->write_header
= au_write_header
;
133 psf
->close
= au_close
;
135 psf
->blockwidth
= psf
->bytewidth
* psf
->sf
.channels
;
138 { case SF_FORMAT_ULAW
: /* 8-bit Ulaw encoding. */
142 case SF_FORMAT_PCM_S8
: /* 8-bit linear PCM. */
143 error
= pcm_init (psf
) ;
146 case SF_FORMAT_PCM_16
: /* 16-bit linear PCM. */
147 case SF_FORMAT_PCM_24
: /* 24-bit linear PCM */
148 case SF_FORMAT_PCM_32
: /* 32-bit linear PCM. */
149 error
= pcm_init (psf
) ;
152 case SF_FORMAT_FLOAT
: /* 32-bit floats. */
153 error
= float32_init (psf
) ;
156 case SF_FORMAT_DOUBLE
: /* 64-bit double precision floats. */
157 error
= double64_init (psf
) ;
160 case SF_FORMAT_ALAW
: /* 8-bit Alaw encoding. */
164 case SF_FORMAT_G721_32
:
165 if (psf
->mode
== SFM_READ
)
166 error
= au_g72x_reader_init (psf
, AU_H_G721_32
) ;
167 else if (psf
->mode
== SFM_WRITE
)
168 error
= au_g72x_writer_init (psf
, AU_H_G721_32
) ;
169 psf
->sf
.seekable
= SF_FALSE
;
172 case SF_FORMAT_G723_24
:
173 if (psf
->mode
== SFM_READ
)
174 error
= au_g72x_reader_init (psf
, AU_H_G723_24
) ;
175 else if (psf
->mode
== SFM_WRITE
)
176 error
= au_g72x_writer_init (psf
, AU_H_G723_24
) ;
177 psf
->sf
.seekable
= SF_FALSE
;
180 case SF_FORMAT_G723_40
:
181 if (psf
->mode
== SFM_READ
)
182 error
= au_g72x_reader_init (psf
, AU_H_G723_40
) ;
183 else if (psf
->mode
== SFM_WRITE
)
184 error
= au_g72x_writer_init (psf
, AU_H_G723_40
) ;
185 psf
->sf
.seekable
= SF_FALSE
;
195 au_nh_open (SF_PRIVATE
*psf
)
197 if (psf
->mode
== SFM_RDWR
)
198 return SFE_BAD_OPEN_FORMAT
;
200 if (psf_fseek (psf
, psf
->dataoffset
, SEEK_SET
))
201 return SFE_BAD_SEEK
;
203 psf_log_printf (psf
, "Header-less u-law encoded file.\n") ;
204 psf_log_printf (psf
, "Setting up for 8kHz, mono, u-law.\n") ;
206 psf
->sf
.format
= SF_FORMAT_AU
| SF_FORMAT_ULAW
;
208 psf
->dataoffset
= 0 ;
209 psf
->endian
= 0 ; /* Irrelevant but it must be something. */
210 psf
->sf
.samplerate
= 8000 ;
211 psf
->sf
.channels
= 1 ;
212 psf
->bytewidth
= 1 ; /* Before decoding */
216 psf
->close
= au_close
;
218 psf
->blockwidth
= 1 ;
219 psf
->sf
.frames
= psf
->filelength
;
220 psf
->datalength
= psf
->filelength
- AU_DATA_OFFSET
;
225 /*------------------------------------------------------------------------------
229 au_close (SF_PRIVATE
*psf
)
231 if (psf
->mode
== SFM_WRITE
|| psf
->mode
== SFM_RDWR
)
232 au_write_header (psf
, SF_TRUE
) ;
238 au_write_header (SF_PRIVATE
*psf
, int calc_length
)
239 { sf_count_t current
;
242 current
= psf_ftell (psf
) ;
245 { psf
->filelength
= psf_get_filelen (psf
) ;
247 psf
->datalength
= psf
->filelength
- psf
->dataoffset
;
249 psf
->datalength
-= psf
->filelength
- psf
->dataend
;
251 psf
->sf
.frames
= psf
->datalength
/ (psf
->bytewidth
* psf
->sf
.channels
) ;
254 encoding
= au_format_to_encoding (psf
->sf
.format
& SF_FORMAT_SUBMASK
) ;
256 return (psf
->error
= SFE_BAD_OPEN_FORMAT
) ;
258 /* Reset the current header length to zero. */
259 psf
->header
[0] = 0 ;
261 psf_fseek (psf
, 0, SEEK_SET
) ;
263 if (psf
->endian
== SF_ENDIAN_BIG
)
264 { psf_binheader_writef (psf
, "Em4", DOTSND_MARKER
, AU_DATA_OFFSET
) ;
265 psf_binheader_writef (psf
, "Et8444", psf
->datalength
, encoding
, psf
->sf
.samplerate
, psf
->sf
.channels
) ;
267 else if (psf
->endian
== SF_ENDIAN_LITTLE
)
268 { psf_binheader_writef (psf
, "em4", DNSDOT_MARKER
, AU_DATA_OFFSET
) ;
269 psf_binheader_writef (psf
, "et8444", psf
->datalength
, encoding
, psf
->sf
.samplerate
, psf
->sf
.channels
) ;
272 return (psf
->error
= SFE_BAD_OPEN_FORMAT
) ;
274 /* Header construction complete so write it out. */
275 psf_fwrite (psf
->header
, psf
->headindex
, 1, psf
) ;
280 psf
->dataoffset
= psf
->headindex
;
283 psf_fseek (psf
, current
, SEEK_SET
) ;
286 } /* au_write_header */
289 au_format_to_encoding (int format
)
292 { case SF_FORMAT_PCM_S8
: return AU_ENCODING_PCM_8
;
293 case SF_FORMAT_PCM_16
: return AU_ENCODING_PCM_16
;
294 case SF_FORMAT_PCM_24
: return AU_ENCODING_PCM_24
;
295 case SF_FORMAT_PCM_32
: return AU_ENCODING_PCM_32
;
297 case SF_FORMAT_FLOAT
: return AU_ENCODING_FLOAT
;
298 case SF_FORMAT_DOUBLE
: return AU_ENCODING_DOUBLE
;
300 case SF_FORMAT_ULAW
: return AU_ENCODING_ULAW_8
;
301 case SF_FORMAT_ALAW
: return AU_ENCODING_ALAW_8
;
303 case SF_FORMAT_G721_32
: return AU_ENCODING_ADPCM_G721_32
;
304 case SF_FORMAT_G723_24
: return AU_ENCODING_ADPCM_G723_24
;
305 case SF_FORMAT_G723_40
: return AU_ENCODING_ADPCM_G723_40
;
310 } /* au_format_to_encoding */
313 au_read_header (SF_PRIVATE
*psf
)
317 psf_binheader_readf (psf
, "pm", 0, &marker
) ;
318 psf_log_printf (psf
, "%M\n", marker
) ;
320 if (marker
== DOTSND_MARKER
)
321 { psf
->endian
= SF_ENDIAN_BIG
;
323 psf_binheader_readf (psf
, "E44444", &(au_fmt
.dataoffset
), &(au_fmt
.datasize
),
324 &(au_fmt
.encoding
), &(au_fmt
.samplerate
), &(au_fmt
.channels
)) ;
326 else if (marker
== DNSDOT_MARKER
)
327 { psf
->endian
= SF_ENDIAN_LITTLE
;
328 psf_binheader_readf (psf
, "e44444", &(au_fmt
.dataoffset
), &(au_fmt
.datasize
),
329 &(au_fmt
.encoding
), &(au_fmt
.samplerate
), &(au_fmt
.channels
)) ;
332 return SFE_AU_NO_DOTSND
;
335 psf_log_printf (psf
, " Data Offset : %d\n", au_fmt
.dataoffset
) ;
337 if (psf
->fileoffset
> 0 && au_fmt
.datasize
== -1)
338 { psf_log_printf (psf
, " Data Size : -1\n") ;
339 return SFE_AU_EMBED_BAD_LEN
;
342 if (psf
->fileoffset
> 0)
343 { psf
->filelength
= au_fmt
.dataoffset
+ au_fmt
.datasize
;
344 psf_log_printf (psf
, " Data Size : %d\n", au_fmt
.datasize
) ;
346 else if (au_fmt
.datasize
== -1 || au_fmt
.dataoffset
+ au_fmt
.datasize
== psf
->filelength
)
347 psf_log_printf (psf
, " Data Size : %d\n", au_fmt
.datasize
) ;
348 else if (au_fmt
.dataoffset
+ au_fmt
.datasize
< psf
->filelength
)
349 { psf
->filelength
= au_fmt
.dataoffset
+ au_fmt
.datasize
;
350 psf_log_printf (psf
, " Data Size : %d\n", au_fmt
.datasize
) ;
353 { dword
= psf
->filelength
- au_fmt
.dataoffset
;
354 psf_log_printf (psf
, " Data Size : %d (should be %d)\n", au_fmt
.datasize
, dword
) ;
355 au_fmt
.datasize
= dword
;
358 psf
->dataoffset
= au_fmt
.dataoffset
;
359 psf
->datalength
= psf
->filelength
- psf
->dataoffset
;
361 if (psf_fseek (psf
, psf
->dataoffset
, SEEK_SET
) != psf
->dataoffset
)
362 return SFE_BAD_SEEK
;
364 psf
->close
= au_close
;
366 psf
->sf
.samplerate
= au_fmt
.samplerate
;
367 psf
->sf
.channels
= au_fmt
.channels
;
369 /* Only fill in type major. */
370 if (psf
->endian
== SF_ENDIAN_BIG
)
371 psf
->sf
.format
= SF_FORMAT_AU
;
372 else if (psf
->endian
== SF_ENDIAN_LITTLE
)
373 psf
->sf
.format
= SF_ENDIAN_LITTLE
| SF_FORMAT_AU
;
375 psf_log_printf (psf
, " Encoding : %d => ", au_fmt
.encoding
) ;
377 psf
->sf
.format
= psf
->sf
.format
& SF_FORMAT_ENDMASK
;
379 switch (au_fmt
.encoding
)
380 { case AU_ENCODING_ULAW_8
:
381 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_ULAW
;
382 psf
->bytewidth
= 1 ; /* Before decoding */
383 psf_log_printf (psf
, "8-bit ISDN u-law\n") ;
386 case AU_ENCODING_PCM_8
:
387 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_PCM_S8
;
389 psf_log_printf (psf
, "8-bit linear PCM\n") ;
392 case AU_ENCODING_PCM_16
:
393 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_PCM_16
;
395 psf_log_printf (psf
, "16-bit linear PCM\n") ;
398 case AU_ENCODING_PCM_24
:
399 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_PCM_24
;
401 psf_log_printf (psf
, "24-bit linear PCM\n") ;
404 case AU_ENCODING_PCM_32
:
405 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_PCM_32
;
407 psf_log_printf (psf
, "32-bit linear PCM\n") ;
410 case AU_ENCODING_FLOAT
:
411 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_FLOAT
;
413 psf_log_printf (psf
, "32-bit float\n") ;
416 case AU_ENCODING_DOUBLE
:
417 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_DOUBLE
;
419 psf_log_printf (psf
, "64-bit double precision float\n") ;
422 case AU_ENCODING_ALAW_8
:
423 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_ALAW
;
424 psf
->bytewidth
= 1 ; /* Before decoding */
425 psf_log_printf (psf
, "8-bit ISDN A-law\n") ;
428 case AU_ENCODING_ADPCM_G721_32
:
429 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_G721_32
;
431 psf_log_printf (psf
, "G721 32kbs ADPCM\n") ;
434 case AU_ENCODING_ADPCM_G723_24
:
435 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_G723_24
;
437 psf_log_printf (psf
, "G723 24kbs ADPCM\n") ;
440 case AU_ENCODING_ADPCM_G723_40
:
441 psf
->sf
.format
|= SF_FORMAT_AU
| SF_FORMAT_G723_40
;
443 psf_log_printf (psf
, "G723 40kbs ADPCM\n") ;
446 case AU_ENCODING_ADPCM_G722
:
447 psf_log_printf (psf
, "G722 64 kbs ADPCM (unsupported)\n") ;
450 case AU_ENCODING_NEXT
:
451 psf_log_printf (psf
, "Weird NeXT encoding format (unsupported)\n") ;
455 psf_log_printf (psf
, "Unknown!!\n") ;
459 psf_log_printf (psf
, " Sample Rate : %d\n", au_fmt
.samplerate
) ;
460 psf_log_printf (psf
, " Channels : %d\n", au_fmt
.channels
) ;
462 psf
->blockwidth
= psf
->sf
.channels
* psf
->bytewidth
;
464 if (! psf
->sf
.frames
&& psf
->blockwidth
)
465 psf
->sf
.frames
= (psf
->filelength
- psf
->dataoffset
) / psf
->blockwidth
;
468 } /* au_read_header */