2 ** Copyright (C) 2001-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 /* The IRCAM magic number is weird in that one byte in the number can have
35 ** values of 0x1, 0x2, 0x03 or 0x04. Hence the need for a marker and a mask.
38 #define IRCAM_BE_MASK (MAKE_MARKER (0xFF, 0xFF, 0x00, 0xFF))
39 #define IRCAM_BE_MARKER (MAKE_MARKER (0x64, 0xA3, 0x00, 0x00))
41 #define IRCAM_LE_MASK (MAKE_MARKER (0xFF, 0x00, 0xFF, 0xFF))
42 #define IRCAM_LE_MARKER (MAKE_MARKER (0x00, 0x00, 0xA3, 0x64))
44 #define IRCAM_02B_MARKER (MAKE_MARKER (0x64, 0xA3, 0x02, 0x00))
45 #define IRCAM_03L_MARKER (MAKE_MARKER (0x64, 0xA3, 0x03, 0x00))
47 #define IRCAM_DATA_OFFSET (1024)
49 /*------------------------------------------------------------------------------
54 { IRCAM_PCM_16
= 0x00002,
55 IRCAM_FLOAT
= 0x00004,
58 IRCAM_PCM_32
= 0x40004
62 /*------------------------------------------------------------------------------
63 ** Private static functions.
66 static int ircam_close (SF_PRIVATE
*psf
) ;
67 static int ircam_write_header (SF_PRIVATE
*psf
, int calc_length
) ;
68 static int ircam_read_header (SF_PRIVATE
*psf
) ;
70 static int get_encoding (int subformat
) ;
72 static const char* get_encoding_str (int encoding
) ;
74 /*------------------------------------------------------------------------------
79 ircam_open (SF_PRIVATE
*psf
)
81 int error
= SFE_NO_ERROR
;
83 if (psf
->file
.mode
== SFM_READ
|| (psf
->file
.mode
== SFM_RDWR
&& psf
->filelength
> 0))
84 { if ((error
= ircam_read_header (psf
)))
88 subformat
= SF_CODEC (psf
->sf
.format
) ;
90 if (psf
->file
.mode
== SFM_WRITE
|| psf
->file
.mode
== SFM_RDWR
)
91 { if ((SF_CONTAINER (psf
->sf
.format
)) != SF_FORMAT_IRCAM
)
92 return SFE_BAD_OPEN_FORMAT
;
94 psf
->endian
= SF_ENDIAN (psf
->sf
.format
) ;
95 if (psf
->endian
== 0 || psf
->endian
== SF_ENDIAN_CPU
)
96 psf
->endian
= (CPU_IS_BIG_ENDIAN
) ? SF_ENDIAN_BIG
: SF_ENDIAN_LITTLE
;
98 psf
->dataoffset
= IRCAM_DATA_OFFSET
;
100 if ((error
= ircam_write_header (psf
, SF_FALSE
)))
103 psf
->write_header
= ircam_write_header
;
106 psf
->container_close
= ircam_close
;
109 { case SF_FORMAT_ULAW
: /* 8-bit Ulaw encoding. */
110 error
= ulaw_init (psf
) ;
113 case SF_FORMAT_ALAW
: /* 8-bit Alaw encoding. */
114 error
= alaw_init (psf
) ;
117 case SF_FORMAT_PCM_16
: /* 16-bit linear PCM. */
118 case SF_FORMAT_PCM_32
: /* 32-bit linear PCM. */
119 error
= pcm_init (psf
) ;
122 case SF_FORMAT_FLOAT
: /* 32-bit linear PCM. */
123 error
= float32_init (psf
) ;
132 /*------------------------------------------------------------------------------
136 ircam_read_header (SF_PRIVATE
*psf
)
137 { unsigned int marker
, encoding
;
139 int error
= SFE_NO_ERROR
;
141 psf_binheader_readf (psf
, "epmf44", 0, &marker
, &samplerate
, &(psf
->sf
.channels
), &encoding
) ;
143 if (((marker
& IRCAM_BE_MASK
) != IRCAM_BE_MARKER
) && ((marker
& IRCAM_LE_MASK
) != IRCAM_LE_MARKER
))
144 { psf_log_printf (psf
, "marker: 0x%X\n", marker
) ;
145 return SFE_IRCAM_NO_MARKER
;
148 psf
->endian
= SF_ENDIAN_LITTLE
;
150 if (psf
->sf
.channels
> 256)
151 { psf_binheader_readf (psf
, "Epmf44", 0, &marker
, &samplerate
, &(psf
->sf
.channels
), &encoding
) ;
153 /* Sanity checking for endian-ness detection. */
154 if (psf
->sf
.channels
> 256)
155 { psf_log_printf (psf
, "marker: 0x%X\n", marker
) ;
156 return SFE_IRCAM_BAD_CHANNELS
;
159 psf
->endian
= SF_ENDIAN_BIG
;
162 psf_log_printf (psf
, "marker: 0x%X\n", marker
) ;
164 psf
->sf
.samplerate
= (int) samplerate
;
166 psf_log_printf (psf
, " Sample Rate : %d\n"
168 " Encoding : %X => %s\n", psf
->sf
.samplerate
, psf
->sf
.channels
, encoding
, get_encoding_str (encoding
)) ;
171 { case IRCAM_PCM_16
:
173 psf
->blockwidth
= psf
->sf
.channels
* psf
->bytewidth
;
175 psf
->sf
.format
= SF_FORMAT_IRCAM
| SF_FORMAT_PCM_16
;
180 psf
->blockwidth
= psf
->sf
.channels
* psf
->bytewidth
;
182 psf
->sf
.format
= SF_FORMAT_IRCAM
| SF_FORMAT_PCM_32
;
187 psf
->blockwidth
= psf
->sf
.channels
* psf
->bytewidth
;
189 psf
->sf
.format
= SF_FORMAT_IRCAM
| SF_FORMAT_FLOAT
;
194 psf
->blockwidth
= psf
->sf
.channels
* psf
->bytewidth
;
196 psf
->sf
.format
= SF_FORMAT_IRCAM
| SF_FORMAT_ALAW
;
201 psf
->blockwidth
= psf
->sf
.channels
* psf
->bytewidth
;
203 psf
->sf
.format
= SF_FORMAT_IRCAM
| SF_FORMAT_ULAW
;
207 error
= SFE_IRCAM_UNKNOWN_FORMAT
;
211 if (psf
->endian
== SF_ENDIAN_BIG
)
212 psf
->sf
.format
|= SF_ENDIAN_BIG
;
214 psf
->sf
.format
|= SF_ENDIAN_LITTLE
;
219 psf
->dataoffset
= IRCAM_DATA_OFFSET
;
220 psf
->datalength
= psf
->filelength
- psf
->dataoffset
;
222 if (psf
->sf
.frames
== 0 && psf
->blockwidth
)
223 psf
->sf
.frames
= psf
->datalength
/ psf
->blockwidth
;
225 psf_log_printf (psf
, " Samples : %d\n", psf
->sf
.frames
) ;
227 psf_binheader_readf (psf
, "p", IRCAM_DATA_OFFSET
) ;
230 } /* ircam_read_header */
233 ircam_close (SF_PRIVATE
*psf
)
235 psf_log_printf (psf
, "close\n") ;
241 ircam_write_header (SF_PRIVATE
*psf
, int UNUSED (calc_length
))
246 if (psf
->pipeoffset
> 0)
249 current
= psf_ftell (psf
) ;
251 /* This also sets psf->endian. */
252 encoding
= get_encoding (SF_CODEC (psf
->sf
.format
)) ;
255 return SFE_BAD_OPEN_FORMAT
;
257 /* Reset the current header length to zero. */
258 psf
->header
[0] = 0 ;
261 if (psf
->is_pipe
== SF_FALSE
)
262 psf_fseek (psf
, 0, SEEK_SET
) ;
264 samplerate
= psf
->sf
.samplerate
;
267 { case SF_ENDIAN_BIG
:
268 psf_binheader_writef (psf
, "Emf", IRCAM_02B_MARKER
, samplerate
) ;
269 psf_binheader_writef (psf
, "E44", psf
->sf
.channels
, encoding
) ;
272 case SF_ENDIAN_LITTLE
:
273 psf_binheader_writef (psf
, "emf", IRCAM_03L_MARKER
, samplerate
) ;
274 psf_binheader_writef (psf
, "e44", psf
->sf
.channels
, encoding
) ;
277 default : return SFE_BAD_OPEN_FORMAT
;
280 psf_binheader_writef (psf
, "z", (size_t) (IRCAM_DATA_OFFSET
- psf
->headindex
)) ;
282 /* Header construction complete so write it out. */
283 psf_fwrite (psf
->header
, psf
->headindex
, 1, psf
) ;
289 psf_fseek (psf
, current
, SEEK_SET
) ;
292 } /* ircam_write_header */
295 get_encoding (int subformat
)
297 { case SF_FORMAT_PCM_16
: return IRCAM_PCM_16
;
298 case SF_FORMAT_PCM_32
: return IRCAM_PCM_32
;
300 case SF_FORMAT_FLOAT
: return IRCAM_FLOAT
;
302 case SF_FORMAT_ULAW
: return IRCAM_ULAW
;
303 case SF_FORMAT_ALAW
: return IRCAM_ALAW
;
312 get_encoding_str (int encoding
)
314 { case IRCAM_PCM_16
: return "16 bit PCM" ;
315 case IRCAM_FLOAT
: return "32 bit float" ;
316 case IRCAM_ALAW
: return "A law" ;
317 case IRCAM_ULAW
: return "u law" ;
318 case IRCAM_PCM_32
: return "32 bit PCM" ;
320 return "Unknown encoding" ;
321 } /* get_encoding_str */