2 ** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
3 ** Copyright (C) 2004-2005 David Viens <davidv@plogue.com>
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU Lesser General Public License as published by
7 ** the Free Software Foundation; either version 2.1 of the License, or
8 ** (at your option) any later version.
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU Lesser General Public License for more details.
15 ** You should have received a copy of the GNU Lesser General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 /*------------------------------------------------------------------------------
35 * Macros to handle big/little endian issues.
38 #define RIFF_MARKER (MAKE_MARKER ('R', 'I', 'F', 'F'))
39 #define RIFX_MARKER (MAKE_MARKER ('R', 'I', 'F', 'X'))
40 #define WAVE_MARKER (MAKE_MARKER ('W', 'A', 'V', 'E'))
41 #define fmt_MARKER (MAKE_MARKER ('f', 'm', 't', ' '))
42 #define data_MARKER (MAKE_MARKER ('d', 'a', 't', 'a'))
43 #define fact_MARKER (MAKE_MARKER ('f', 'a', 'c', 't'))
44 #define PEAK_MARKER (MAKE_MARKER ('P', 'E', 'A', 'K'))
46 #define cue_MARKER (MAKE_MARKER ('c', 'u', 'e', ' '))
47 #define LIST_MARKER (MAKE_MARKER ('L', 'I', 'S', 'T'))
48 #define slnt_MARKER (MAKE_MARKER ('s', 'l', 'n', 't'))
49 #define wavl_MARKER (MAKE_MARKER ('w', 'a', 'v', 'l'))
50 #define INFO_MARKER (MAKE_MARKER ('I', 'N', 'F', 'O'))
51 #define plst_MARKER (MAKE_MARKER ('p', 'l', 's', 't'))
52 #define adtl_MARKER (MAKE_MARKER ('a', 'd', 't', 'l'))
53 #define labl_MARKER (MAKE_MARKER ('l', 'a', 'b', 'l'))
54 #define ltxt_MARKER (MAKE_MARKER ('l', 't', 'x', 't'))
55 #define note_MARKER (MAKE_MARKER ('n', 'o', 't', 'e'))
56 #define smpl_MARKER (MAKE_MARKER ('s', 'm', 'p', 'l'))
57 #define bext_MARKER (MAKE_MARKER ('b', 'e', 'x', 't'))
58 #define iXML_MARKER (MAKE_MARKER ('i', 'X', 'M', 'L'))
59 #define levl_MARKER (MAKE_MARKER ('l', 'e', 'v', 'l'))
60 #define MEXT_MARKER (MAKE_MARKER ('M', 'E', 'X', 'T'))
61 #define DISP_MARKER (MAKE_MARKER ('D', 'I', 'S', 'P'))
62 #define acid_MARKER (MAKE_MARKER ('a', 'c', 'i', 'd'))
63 #define strc_MARKER (MAKE_MARKER ('s', 't', 'r', 'c'))
64 #define PAD_MARKER (MAKE_MARKER ('P', 'A', 'D', ' '))
65 #define afsp_MARKER (MAKE_MARKER ('a', 'f', 's', 'p'))
66 #define clm_MARKER (MAKE_MARKER ('c', 'l', 'm', ' '))
67 #define elmo_MARKER (MAKE_MARKER ('e', 'l', 'm', 'o'))
68 #define cart_MARKER (MAKE_MARKER ('c', 'a', 'r', 't'))
69 #define FLLR_MARKER (MAKE_MARKER ('F', 'L', 'L', 'R'))
71 #define exif_MARKER (MAKE_MARKER ('e', 'x', 'i', 'f'))
72 #define ever_MARKER (MAKE_MARKER ('e', 'v', 'e', 'r'))
73 #define etim_MARKER (MAKE_MARKER ('e', 't', 'i', 'm'))
74 #define ecor_MARKER (MAKE_MARKER ('e', 'c', 'o', 'r'))
75 #define emdl_MARKER (MAKE_MARKER ('e', 'm', 'd', 'l'))
76 #define emnt_MARKER (MAKE_MARKER ('e', 'm', 'n', 't'))
77 #define erel_MARKER (MAKE_MARKER ('e', 'r', 'e', 'l'))
78 #define eucm_MARKER (MAKE_MARKER ('e', 'u', 'c', 'm'))
80 #define ISFT_MARKER (MAKE_MARKER ('I', 'S', 'F', 'T'))
81 #define ICRD_MARKER (MAKE_MARKER ('I', 'C', 'R', 'D'))
82 #define ICOP_MARKER (MAKE_MARKER ('I', 'C', 'O', 'P'))
83 #define IARL_MARKER (MAKE_MARKER ('I', 'A', 'R', 'L'))
84 #define IART_MARKER (MAKE_MARKER ('I', 'A', 'R', 'T'))
85 #define INAM_MARKER (MAKE_MARKER ('I', 'N', 'A', 'M'))
86 #define IENG_MARKER (MAKE_MARKER ('I', 'E', 'N', 'G'))
87 #define IGNR_MARKER (MAKE_MARKER ('I', 'G', 'N', 'R'))
88 #define ICOP_MARKER (MAKE_MARKER ('I', 'C', 'O', 'P'))
89 #define IPRD_MARKER (MAKE_MARKER ('I', 'P', 'R', 'D'))
90 #define ISRC_MARKER (MAKE_MARKER ('I', 'S', 'R', 'C'))
91 #define ISBJ_MARKER (MAKE_MARKER ('I', 'S', 'B', 'J'))
92 #define ICMT_MARKER (MAKE_MARKER ('I', 'C', 'M', 'T'))
94 /* Weird WAVPACK marker which can show up at the start of the DATA section. */
95 #define wvpk_MARKER (MAKE_MARKER ('w', 'v', 'p', 'k'))
96 #define OggS_MARKER (MAKE_MARKER ('O', 'g', 'g', 'S'))
98 #define WAV_PEAK_CHUNK_SIZE(ch) (2 * sizeof (int) + ch * (sizeof (float) + sizeof (int)))
99 #define WAV_BEXT_MIN_CHUNK_SIZE 602
100 #define WAV_BEXT_MAX_CHUNK_SIZE (10 * 1024)
109 HAVE_other
= 0x80000000
114 /* known WAVEFORMATEXTENSIBLE GUIDS */
115 static const EXT_SUBFORMAT MSGUID_SUBTYPE_PCM
=
116 { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
119 static const EXT_SUBFORMAT MSGUID_SUBTYPE_MS_ADPCM
=
120 { 0x00000002, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
123 static const EXT_SUBFORMAT MSGUID_SUBTYPE_IEEE_FLOAT
=
124 { 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
127 static const EXT_SUBFORMAT MSGUID_SUBTYPE_ALAW
=
128 { 0x00000006, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
131 static const EXT_SUBFORMAT MSGUID_SUBTYPE_MULAW
=
132 { 0x00000007, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
136 ** the next two are from
137 ** http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html
139 static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM
=
140 { 0x00000001, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 }
143 static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT
=
144 { 0x00000003, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 }
149 /* maybe interesting one day to read the following through sf_read_raw */
150 /* http://www.bath.ac.uk/~masrwd/pvocex/pvocex.html */
151 static const EXT_SUBFORMAT MSGUID_SUBTYPE_PVOCEX
=
152 { 0x8312B9C2, 0x2E6E, 0x11d4, { 0xA8, 0x24, 0xDE, 0x5B, 0x96, 0xC3, 0xAB, 0x21 }
156 /*------------------------------------------------------------------------------
157 ** Private static functions.
160 static int wav_read_header (SF_PRIVATE
*psf
, int *blockalign
, int *framesperblock
) ;
161 static int wav_write_header (SF_PRIVATE
*psf
, int calc_length
) ;
163 static int wav_write_tailer (SF_PRIVATE
*psf
) ;
164 static void wav_write_strings (SF_PRIVATE
*psf
, int location
) ;
165 static int wav_command (SF_PRIVATE
*psf
, int command
, void *data
, int datasize
) ;
166 static int wav_close (SF_PRIVATE
*psf
) ;
168 static int wav_subchunk_parse (SF_PRIVATE
*psf
, int chunk
) ;
169 static int exif_subchunk_parse (SF_PRIVATE
*psf
, unsigned int length
) ;
170 static int wav_read_smpl_chunk (SF_PRIVATE
*psf
, unsigned int chunklen
) ;
171 static int wav_read_acid_chunk (SF_PRIVATE
*psf
, unsigned int chunklen
) ;
173 /*------------------------------------------------------------------------------
178 wav_open (SF_PRIVATE
*psf
)
179 { WAV_PRIVATE
* wpriv
;
180 int format
, subformat
, error
, blockalign
= 0, framesperblock
= 0 ;
182 if ((wpriv
= calloc (1, sizeof (WAV_PRIVATE
))) == NULL
)
183 return SFE_MALLOC_FAILED
;
184 psf
->container_data
= wpriv
;
186 wpriv
->wavex_ambisonic
= SF_AMBISONIC_NONE
;
187 psf
->str_flags
= SF_STR_ALLOW_START
| SF_STR_ALLOW_END
;
189 if (psf
->file
.mode
== SFM_READ
|| (psf
->file
.mode
== SFM_RDWR
&& psf
->filelength
> 0))
190 { if ((error
= wav_read_header (psf
, &blockalign
, &framesperblock
)))
194 subformat
= SF_CODEC (psf
->sf
.format
) ;
196 if (psf
->file
.mode
== SFM_WRITE
|| psf
->file
.mode
== SFM_RDWR
)
198 return SFE_NO_PIPE_WRITE
;
200 wpriv
->wavex_ambisonic
= SF_AMBISONIC_NONE
;
202 format
= SF_CONTAINER (psf
->sf
.format
) ;
203 if (format
!= SF_FORMAT_WAV
&& format
!= SF_FORMAT_WAVEX
)
204 return SFE_BAD_OPEN_FORMAT
;
206 psf
->blockwidth
= psf
->bytewidth
* psf
->sf
.channels
;
208 /* RIFF WAVs are little-endian, RIFX WAVs are big-endian, default to little */
209 psf
->endian
= SF_ENDIAN (psf
->sf
.format
) ;
210 if (CPU_IS_BIG_ENDIAN
&& psf
->endian
== SF_ENDIAN_CPU
)
211 psf
->endian
= SF_ENDIAN_BIG
;
212 else if (psf
->endian
!= SF_ENDIAN_BIG
)
213 psf
->endian
= SF_ENDIAN_LITTLE
;
215 if (psf
->file
.mode
!= SFM_RDWR
|| psf
->filelength
< 44)
216 { psf
->filelength
= 0 ;
217 psf
->datalength
= 0 ;
218 psf
->dataoffset
= 0 ;
222 if (subformat
== SF_FORMAT_IMA_ADPCM
|| subformat
== SF_FORMAT_MS_ADPCM
)
223 { blockalign
= wav_w64_srate2blocksize (psf
->sf
.samplerate
* psf
->sf
.channels
) ;
224 framesperblock
= -1 ; /* Corrected later. */
227 /* By default, add the peak chunk to floating point files. Default behaviour
228 ** can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE).
230 if (psf
->file
.mode
== SFM_WRITE
&& (subformat
== SF_FORMAT_FLOAT
|| subformat
== SF_FORMAT_DOUBLE
))
231 { if ((psf
->peak_info
= peak_info_calloc (psf
->sf
.channels
)) == NULL
)
232 return SFE_MALLOC_FAILED
;
233 psf
->peak_info
->peak_loc
= SF_PEAK_START
;
236 psf
->write_header
= wav_write_header
;
239 psf
->container_close
= wav_close
;
240 psf
->command
= wav_command
;
243 { case SF_FORMAT_PCM_U8
:
244 case SF_FORMAT_PCM_16
:
245 case SF_FORMAT_PCM_24
:
246 case SF_FORMAT_PCM_32
:
247 error
= pcm_init (psf
) ;
250 case SF_FORMAT_ULAW
:
251 error
= ulaw_init (psf
) ;
254 case SF_FORMAT_ALAW
:
255 error
= alaw_init (psf
) ;
258 /* Lite remove start */
259 case SF_FORMAT_FLOAT
:
260 error
= float32_init (psf
) ;
263 case SF_FORMAT_DOUBLE
:
264 error
= double64_init (psf
) ;
267 case SF_FORMAT_IMA_ADPCM
:
268 error
= wav_w64_ima_init (psf
, blockalign
, framesperblock
) ;
271 case SF_FORMAT_MS_ADPCM
:
272 error
= wav_w64_msadpcm_init (psf
, blockalign
, framesperblock
) ;
275 case SF_FORMAT_G721_32
:
276 error
= g72x_init (psf
) ;
278 /* Lite remove end */
280 case SF_FORMAT_GSM610
:
281 error
= gsm610_init (psf
) ;
284 default : return SFE_UNIMPLEMENTED
;
287 if (psf
->file
.mode
== SFM_WRITE
|| (psf
->file
.mode
== SFM_RDWR
&& psf
->filelength
== 0))
288 return psf
->write_header (psf
, SF_FALSE
) ;
293 /*=========================================================================
294 ** Private functions.
298 wav_read_header (SF_PRIVATE
*psf
, int *blockalign
, int *framesperblock
)
299 { WAV_PRIVATE
*wpriv
;
301 FACT_CHUNK fact_chunk
;
302 unsigned dword
= 0, marker
, RIFFsize
= 0, done
= 0 ;
303 int parsestage
= 0, error
, format
= 0 ;
306 if (psf
->filelength
> SF_PLATFORM_S64 (0xffffffff))
307 psf_log_printf (psf
, "Warning : filelength > 0xffffffff. This is bad!!!!\n") ;
309 if ((wpriv
= psf
->container_data
) == NULL
)
310 return SFE_INTERNAL
;
311 wav_fmt
= &wpriv
->wav_fmt
;
313 /* Set position to start of file to begin reading header. */
314 psf_binheader_readf (psf
, "p", 0) ;
317 { psf_binheader_readf (psf
, "m", &marker
) ;
323 return SFE_WAV_NO_RIFF
;
325 parsestage
|= HAVE_RIFF
;
327 /* RIFX signifies big-endian format for all header and data
328 ** to prevent lots of code copying here, we'll set the psf->rwf_endian
329 ** flag once here, and never specify endian-ness for all other header ops
331 if (marker
== RIFF_MARKER
)
332 psf
->rwf_endian
= SF_ENDIAN_LITTLE
;
334 psf
->rwf_endian
= SF_ENDIAN_BIG
;
336 psf_binheader_readf (psf
, "4", &RIFFsize
) ;
338 if (psf
->fileoffset
> 0 && psf
->filelength
> RIFFsize
+ 8)
339 { /* Set file length. */
340 psf
->filelength
= RIFFsize
+ 8 ;
341 if (marker
== RIFF_MARKER
)
342 psf_log_printf (psf
, "RIFF : %u\n", RIFFsize
) ;
344 psf_log_printf (psf
, "RIFX : %u\n", RIFFsize
) ;
346 else if (psf
->filelength
< RIFFsize
+ 2 * SIGNED_SIZEOF (dword
))
347 { if (marker
== RIFF_MARKER
)
348 psf_log_printf (psf
, "RIFF : %u (should be %D)\n", RIFFsize
, psf
->filelength
- 2 * SIGNED_SIZEOF (dword
)) ;
350 psf_log_printf (psf
, "RIFX : %u (should be %D)\n", RIFFsize
, psf
->filelength
- 2 * SIGNED_SIZEOF (dword
)) ;
355 { if (marker
== RIFF_MARKER
)
356 psf_log_printf (psf
, "RIFF : %u\n", RIFFsize
) ;
358 psf_log_printf (psf
, "RIFX : %u\n", RIFFsize
) ;
363 if ((parsestage
& HAVE_RIFF
) != HAVE_RIFF
)
364 return SFE_WAV_NO_WAVE
;
365 parsestage
|= HAVE_WAVE
;
367 psf_log_printf (psf
, "WAVE\n") ;
371 if ((parsestage
& (HAVE_RIFF
| HAVE_WAVE
)) != (HAVE_RIFF
| HAVE_WAVE
))
372 return SFE_WAV_NO_FMT
;
374 /* If this file has a SECOND fmt chunk, I don't want to know about it. */
375 if (parsestage
& HAVE_fmt
)
378 parsestage
|= HAVE_fmt
;
380 psf_binheader_readf (psf
, "4", &dword
) ;
381 psf_log_printf (psf
, "fmt : %d\n", dword
) ;
383 if ((error
= wav_w64_read_fmt_chunk (psf
, dword
)))
386 format
= wav_fmt
->format
;
390 if ((parsestage
& (HAVE_RIFF
| HAVE_WAVE
| HAVE_fmt
)) != (HAVE_RIFF
| HAVE_WAVE
| HAVE_fmt
))
391 return SFE_WAV_NO_DATA
;
393 if (psf
->file
.mode
== SFM_RDWR
&& (parsestage
& HAVE_other
) != 0)
394 return SFE_RDWR_BAD_HEADER
;
396 parsestage
|= HAVE_data
;
398 psf_binheader_readf (psf
, "4", &dword
) ;
400 psf
->datalength
= dword
;
401 psf
->dataoffset
= psf_ftell (psf
) ;
403 if (psf
->dataoffset
> 0)
404 { if (dword
== 0 && RIFFsize
== 8 && psf
->filelength
> 44)
405 { psf_log_printf (psf
, "*** Looks like a WAV file which wasn't closed properly. Fixing it.\n") ;
406 psf
->datalength
= psf
->filelength
- psf
->dataoffset
;
409 if (psf
->datalength
> psf
->filelength
- psf
->dataoffset
)
410 { psf_log_printf (psf
, "data : %D (should be %D)\n", psf
->datalength
, psf
->filelength
- psf
->dataoffset
) ;
411 psf
->datalength
= psf
->filelength
- psf
->dataoffset
;
414 psf_log_printf (psf
, "data : %D\n", psf
->datalength
) ;
416 /* Only set dataend if there really is data at the end. */
417 if (psf
->datalength
+ psf
->dataoffset
< psf
->filelength
)
418 psf
->dataend
= psf
->datalength
+ psf
->dataoffset
;
420 if (format
== WAVE_FORMAT_MS_ADPCM
&& psf
->datalength
% 2)
421 { psf
->datalength
++ ;
422 psf_log_printf (psf
, "*** Data length odd. Increasing it by 1.\n") ;
426 if (! psf
->sf
.seekable
|| psf
->dataoffset
< 0)
429 /* Seek past data and continue reading header. */
430 psf_fseek (psf
, psf
->datalength
, SEEK_CUR
) ;
432 if (psf_ftell (psf
) != psf
->datalength
+ psf
->dataoffset
)
433 psf_log_printf (psf
, "*** psf_fseek past end error ***\n") ;
437 if ((parsestage
& (HAVE_RIFF
| HAVE_WAVE
)) != (HAVE_RIFF
| HAVE_WAVE
))
438 return SFE_WAV_BAD_FACT
;
440 parsestage
|= HAVE_fact
;
442 if ((parsestage
& HAVE_fmt
) != HAVE_fmt
)
443 psf_log_printf (psf
, "*** Should have 'fmt ' chunk before 'fact'\n") ;
445 psf_binheader_readf (psf
, "44", &dword
, & (fact_chunk
.frames
)) ;
447 if (dword
> SIGNED_SIZEOF (fact_chunk
))
448 psf_binheader_readf (psf
, "j", (int) (dword
- SIGNED_SIZEOF (fact_chunk
))) ;
451 psf_log_printf (psf
, "%M : %d\n", marker
, dword
) ;
453 psf_log_printf (psf
, "%M : %d (should not be zero)\n", marker
, dword
) ;
455 psf_log_printf (psf
, " frames : %d\n", fact_chunk
.frames
) ;
459 if ((parsestage
& (HAVE_RIFF
| HAVE_WAVE
| HAVE_fmt
)) != (HAVE_RIFF
| HAVE_WAVE
| HAVE_fmt
))
460 return SFE_WAV_PEAK_B4_FMT
;
462 parsestage
|= HAVE_PEAK
;
464 psf_binheader_readf (psf
, "4", &dword
) ;
466 psf_log_printf (psf
, "%M : %d\n", marker
, dword
) ;
467 if (dword
!= WAV_PEAK_CHUNK_SIZE (psf
->sf
.channels
))
468 { psf_binheader_readf (psf
, "j", dword
) ;
469 psf_log_printf (psf
, "*** File PEAK chunk size doesn't fit with number of channels (%d).\n", psf
->sf
.channels
) ;
470 return SFE_WAV_BAD_PEAK
;
473 if ((psf
->peak_info
= peak_info_calloc (psf
->sf
.channels
)) == NULL
)
474 return SFE_MALLOC_FAILED
;
476 /* read in rest of PEAK chunk. */
477 psf_binheader_readf (psf
, "44", & (psf
->peak_info
->version
), & (psf
->peak_info
->timestamp
)) ;
479 if (psf
->peak_info
->version
!= 1)
480 psf_log_printf (psf
, " version : %d *** (should be version 1)\n", psf
->peak_info
->version
) ;
482 psf_log_printf (psf
, " version : %d\n", psf
->peak_info
->version
) ;
484 psf_log_printf (psf
, " time stamp : %d\n", psf
->peak_info
->timestamp
) ;
485 psf_log_printf (psf
, " Ch Position Value\n") ;
488 for (dword
= 0 ; dword
< (unsigned) psf
->sf
.channels
; dword
++)
490 unsigned int position
;
492 psf_binheader_readf (psf
, "f4", &value
, &position
) ;
493 psf
->peak_info
->peaks
[dword
].value
= value
;
494 psf
->peak_info
->peaks
[dword
].position
= position
;
496 snprintf (cptr
, sizeof (psf
->u
.cbuf
), " %2d %-12" PRId64
" %g\n",
497 dword
, psf
->peak_info
->peaks
[dword
].position
, psf
->peak_info
->peaks
[dword
].value
) ;
498 cptr
[sizeof (psf
->u
.cbuf
) - 1] = 0 ;
499 psf_log_printf (psf
, "%s", cptr
) ;
502 psf
->peak_info
->peak_loc
= ((parsestage
& HAVE_data
) == 0) ? SF_PEAK_START
: SF_PEAK_END
;
506 parsestage
|= HAVE_other
;
508 { unsigned bytesread
, cue_count
;
509 int id
, position
, chunk_id
, chunk_start
, block_start
, offset
;
511 bytesread
= psf_binheader_readf (psf
, "44", &dword
, &cue_count
) ;
512 bytesread
-= 4 ; /* Remove bytes for first dword. */
513 psf_log_printf (psf
, "%M : %u\n", marker
, dword
) ;
516 { psf_log_printf (psf
, " Count : %d (skipping)\n", cue_count
) ;
517 psf_binheader_readf (psf
, "j", cue_count
* 24) ;
521 psf_log_printf (psf
, " Count : %d\n", cue_count
) ;
524 { bytesread
+= psf_binheader_readf (psf
, "444444", &id
, &position
,
525 &chunk_id
, &chunk_start
, &block_start
, &offset
) ;
526 psf_log_printf (psf
, " Cue ID : %2d"
527 " Pos : %5u Chunk : %M"
528 " Chk Start : %d Blk Start : %d"
530 id
, position
, chunk_id
, chunk_start
, block_start
, offset
) ;
534 if (bytesread
!= dword
)
535 { psf_log_printf (psf
, "**** Chunk size weirdness (%d != %d)\n", dword
, bytesread
) ;
536 psf_binheader_readf (psf
, "j", dword
- bytesread
) ;
542 parsestage
|= HAVE_other
;
544 psf_binheader_readf (psf
, "4", &dword
) ;
545 psf_log_printf (psf
, "smpl : %u\n", dword
) ;
547 if ((error
= wav_read_smpl_chunk (psf
, dword
)))
552 parsestage
|= HAVE_other
;
554 psf_binheader_readf (psf
, "4", &dword
) ;
555 psf_log_printf (psf
, "acid : %u\n", dword
) ;
557 if ((error
= wav_read_acid_chunk (psf
, dword
)))
563 parsestage
|= HAVE_other
;
565 if ((error
= wav_subchunk_parse (psf
, marker
)) != 0)
571 The 'bext' chunk can actually be updated, so don't need to set this.
572 parsestage |= HAVE_other ;
574 psf_binheader_readf (psf
, "4", &dword
) ;
575 if ((error
= wav_read_bext_chunk (psf
, dword
)))
581 We can eat into a 'PAD ' chunk if we need to.
582 parsestage |= HAVE_other ;
584 psf_binheader_readf (psf
, "4", &dword
) ;
585 psf_log_printf (psf
, "%M : %u\n", marker
, dword
) ;
586 dword
+= (dword
& 1) ;
587 psf_binheader_readf (psf
, "j", dword
) ;
590 case iXML_MARKER
: /* See http://en.wikipedia.org/wiki/IXML */
591 case strc_MARKER
: /* Multiple of 32 bytes. */
601 psf_binheader_readf (psf
, "4", &dword
) ;
602 psf_log_printf (psf
, "%M : %u\n", marker
, dword
) ;
603 dword
+= (dword
& 1) ;
604 psf_binheader_readf (psf
, "j", dword
) ;
608 if (psf_isprint ((marker
>> 24) & 0xFF) && psf_isprint ((marker
>> 16) & 0xFF)
609 && psf_isprint ((marker
>> 8) & 0xFF) && psf_isprint (marker
& 0xFF))
610 { psf_binheader_readf (psf
, "4", &dword
) ;
611 psf_log_printf (psf
, "*** %M : %d (unknown marker)\n", marker
, dword
) ;
612 psf_binheader_readf (psf
, "j", dword
) ;
615 if (psf_ftell (psf
) & 0x03)
616 { psf_log_printf (psf
, " Unknown chunk marker at position %d. Resynching.\n", dword
- 4) ;
617 psf_binheader_readf (psf
, "j", -3) ;
618 /* File is too messed up so we prevent editing in RDWR mode here. */
619 parsestage
|= HAVE_other
;
622 psf_log_printf (psf
, "*** Unknown chunk marker (%X) at position %D. Exiting parser.\n", marker
, psf_ftell (psf
) - 4) ;
625 } ; /* switch (dword) */
627 if (! psf
->sf
.seekable
&& (parsestage
& HAVE_data
))
630 if (psf_ftell (psf
) >= psf
->filelength
- SIGNED_SIZEOF (dword
))
631 { psf_log_printf (psf
, "End\n") ;
636 if (psf
->dataoffset
<= 0)
637 return SFE_WAV_NO_DATA
;
639 /* WAVs can be little or big endian */
640 psf
->endian
= psf
->rwf_endian
;
642 psf_fseek (psf
, psf
->dataoffset
, SEEK_SET
) ;
644 if (psf
->is_pipe
== 0)
646 ** Check for 'wvpk' at the start of the DATA section. Not able to
649 psf_binheader_readf (psf
, "4", &marker
) ;
650 if (marker
== wvpk_MARKER
|| marker
== OggS_MARKER
)
651 return SFE_WAV_WVPK_DATA
;
654 /* Seek to start of DATA section. */
655 psf_fseek (psf
, psf
->dataoffset
, SEEK_SET
) ;
658 { if (psf
->filelength
- psf
->dataoffset
< psf
->datalength
)
659 psf
->sf
.frames
= (psf
->filelength
- psf
->dataoffset
) / psf
->blockwidth
;
661 psf
->sf
.frames
= psf
->datalength
/ psf
->blockwidth
;
665 { case WAVE_FORMAT_EXTENSIBLE
:
666 if (psf
->sf
.format
== (SF_FORMAT_WAVEX
| SF_FORMAT_MS_ADPCM
))
667 { *blockalign
= wav_fmt
->msadpcm
.blockalign
;
668 *framesperblock
= wav_fmt
->msadpcm
.samplesperblock
;
672 case WAVE_FORMAT_PCM
:
673 psf
->sf
.format
= SF_FORMAT_WAV
| u_bitwidth_to_subformat (psf
->bytewidth
* 8) ;
676 case WAVE_FORMAT_MULAW
:
677 case IBM_FORMAT_MULAW
:
678 psf
->sf
.format
= (SF_FORMAT_WAV
| SF_FORMAT_ULAW
) ;
681 case WAVE_FORMAT_ALAW
:
682 case IBM_FORMAT_ALAW
:
683 psf
->sf
.format
= (SF_FORMAT_WAV
| SF_FORMAT_ALAW
) ;
686 case WAVE_FORMAT_MS_ADPCM
:
687 psf
->sf
.format
= (SF_FORMAT_WAV
| SF_FORMAT_MS_ADPCM
) ;
688 *blockalign
= wav_fmt
->msadpcm
.blockalign
;
689 *framesperblock
= wav_fmt
->msadpcm
.samplesperblock
;
692 case WAVE_FORMAT_IMA_ADPCM
:
693 psf
->sf
.format
= (SF_FORMAT_WAV
| SF_FORMAT_IMA_ADPCM
) ;
694 *blockalign
= wav_fmt
->ima
.blockalign
;
695 *framesperblock
= wav_fmt
->ima
.samplesperblock
;
698 case WAVE_FORMAT_GSM610
:
699 psf
->sf
.format
= (SF_FORMAT_WAV
| SF_FORMAT_GSM610
) ;
702 case WAVE_FORMAT_IEEE_FLOAT
:
703 psf
->sf
.format
= SF_FORMAT_WAV
;
704 psf
->sf
.format
|= (psf
->bytewidth
== 8) ? SF_FORMAT_DOUBLE
: SF_FORMAT_FLOAT
;
707 case WAVE_FORMAT_G721_ADPCM
:
708 psf
->sf
.format
= SF_FORMAT_WAV
| SF_FORMAT_G721_32
;
711 default : return SFE_UNIMPLEMENTED
;
714 if (wpriv
->fmt_is_broken
)
715 wav_w64_analyze (psf
) ;
717 /* Only set the format endian-ness if its non-standard big-endian. */
718 if (psf
->endian
== SF_ENDIAN_BIG
)
719 psf
->sf
.format
|= SF_ENDIAN_BIG
;
722 } /* wav_read_header */
725 wav_write_fmt_chunk (SF_PRIVATE
*psf
)
726 { int subformat
, fmt_size
, add_fact_chunk
= 0 ;
728 subformat
= SF_CODEC (psf
->sf
.format
) ;
731 { case SF_FORMAT_PCM_U8
:
732 case SF_FORMAT_PCM_16
:
733 case SF_FORMAT_PCM_24
:
734 case SF_FORMAT_PCM_32
:
735 fmt_size
= 2 + 2 + 4 + 4 + 2 + 2 ;
737 /* fmt : format, channels, samplerate */
738 psf_binheader_writef (psf
, "4224", fmt_size
, WAVE_FORMAT_PCM
, psf
->sf
.channels
, psf
->sf
.samplerate
) ;
739 /* fmt : bytespersec */
740 psf_binheader_writef (psf
, "4", psf
->sf
.samplerate
* psf
->bytewidth
* psf
->sf
.channels
) ;
741 /* fmt : blockalign, bitwidth */
742 psf_binheader_writef (psf
, "22", psf
->bytewidth
* psf
->sf
.channels
, psf
->bytewidth
* 8) ;
745 case SF_FORMAT_FLOAT
:
746 case SF_FORMAT_DOUBLE
:
747 fmt_size
= 2 + 2 + 4 + 4 + 2 + 2 ;
749 /* fmt : format, channels, samplerate */
750 psf_binheader_writef (psf
, "4224", fmt_size
, WAVE_FORMAT_IEEE_FLOAT
, psf
->sf
.channels
, psf
->sf
.samplerate
) ;
751 /* fmt : bytespersec */
752 psf_binheader_writef (psf
, "4", psf
->sf
.samplerate
* psf
->bytewidth
* psf
->sf
.channels
) ;
753 /* fmt : blockalign, bitwidth */
754 psf_binheader_writef (psf
, "22", psf
->bytewidth
* psf
->sf
.channels
, psf
->bytewidth
* 8) ;
756 add_fact_chunk
= SF_TRUE
;
759 case SF_FORMAT_ULAW
:
760 fmt_size
= 2 + 2 + 4 + 4 + 2 + 2 + 2 ;
762 /* fmt : format, channels, samplerate */
763 psf_binheader_writef (psf
, "4224", fmt_size
, WAVE_FORMAT_MULAW
, psf
->sf
.channels
, psf
->sf
.samplerate
) ;
764 /* fmt : bytespersec */
765 psf_binheader_writef (psf
, "4", psf
->sf
.samplerate
* psf
->bytewidth
* psf
->sf
.channels
) ;
766 /* fmt : blockalign, bitwidth, extrabytes */
767 psf_binheader_writef (psf
, "222", psf
->bytewidth
* psf
->sf
.channels
, 8, 0) ;
769 add_fact_chunk
= SF_TRUE
;
772 case SF_FORMAT_ALAW
:
773 fmt_size
= 2 + 2 + 4 + 4 + 2 + 2 + 2 ;
775 /* fmt : format, channels, samplerate */
776 psf_binheader_writef (psf
, "4224", fmt_size
, WAVE_FORMAT_ALAW
, psf
->sf
.channels
, psf
->sf
.samplerate
) ;
777 /* fmt : bytespersec */
778 psf_binheader_writef (psf
, "4", psf
->sf
.samplerate
* psf
->bytewidth
* psf
->sf
.channels
) ;
779 /* fmt : blockalign, bitwidth, extrabytes */
780 psf_binheader_writef (psf
, "222", psf
->bytewidth
* psf
->sf
.channels
, 8, 0) ;
782 add_fact_chunk
= SF_TRUE
;
785 /* Lite remove start */
786 case SF_FORMAT_IMA_ADPCM
:
787 { int blockalign
, framesperblock
, bytespersec
;
789 blockalign
= wav_w64_srate2blocksize (psf
->sf
.samplerate
* psf
->sf
.channels
) ;
790 framesperblock
= 2 * (blockalign
- 4 * psf
->sf
.channels
) / psf
->sf
.channels
+ 1 ;
791 bytespersec
= (psf
->sf
.samplerate
* blockalign
) / framesperblock
;
794 fmt_size
= 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
796 /* fmt : size, WAV format type, channels, samplerate, bytespersec */
797 psf_binheader_writef (psf
, "42244", fmt_size
, WAVE_FORMAT_IMA_ADPCM
,
798 psf
->sf
.channels
, psf
->sf
.samplerate
, bytespersec
) ;
800 /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
801 psf_binheader_writef (psf
, "2222", blockalign
, 4, 2, framesperblock
) ;
804 add_fact_chunk
= SF_TRUE
;
807 case SF_FORMAT_MS_ADPCM
:
808 { int blockalign
, framesperblock
, bytespersec
, extrabytes
;
810 blockalign
= wav_w64_srate2blocksize (psf
->sf
.samplerate
* psf
->sf
.channels
) ;
811 framesperblock
= 2 + 2 * (blockalign
- 7 * psf
->sf
.channels
) / psf
->sf
.channels
;
812 bytespersec
= (psf
->sf
.samplerate
* blockalign
) / framesperblock
;
815 extrabytes
= 2 + 2 + MSADPCM_ADAPT_COEFF_COUNT
* (2 + 2) ;
816 fmt_size
= 2 + 2 + 4 + 4 + 2 + 2 + 2 + extrabytes
;
818 /* fmt : size, WAV format type, channels. */
819 psf_binheader_writef (psf
, "422", fmt_size
, WAVE_FORMAT_MS_ADPCM
, psf
->sf
.channels
) ;
821 /* fmt : samplerate, bytespersec. */
822 psf_binheader_writef (psf
, "44", psf
->sf
.samplerate
, bytespersec
) ;
824 /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
825 psf_binheader_writef (psf
, "22222", blockalign
, 4, extrabytes
, framesperblock
, 7) ;
827 msadpcm_write_adapt_coeffs (psf
) ;
830 add_fact_chunk
= SF_TRUE
;
834 case SF_FORMAT_G721_32
:
836 fmt_size
= 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
838 /* fmt : size, WAV format type, channels, samplerate, bytespersec */
839 psf_binheader_writef (psf
, "42244", fmt_size
, WAVE_FORMAT_G721_ADPCM
,
840 psf
->sf
.channels
, psf
->sf
.samplerate
, psf
->sf
.samplerate
* psf
->sf
.channels
/ 2) ;
842 /* fmt : blockalign, bitwidth, extrabytes, auxblocksize. */
843 psf_binheader_writef (psf
, "2222", 64, 4, 2, 0) ;
845 add_fact_chunk
= SF_TRUE
;
848 /* Lite remove end */
850 case SF_FORMAT_GSM610
:
851 { int blockalign
, framesperblock
, bytespersec
;
853 blockalign
= WAV_W64_GSM610_BLOCKSIZE
;
854 framesperblock
= WAV_W64_GSM610_SAMPLES
;
855 bytespersec
= (psf
->sf
.samplerate
* blockalign
) / framesperblock
;
858 fmt_size
= 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
860 /* fmt : size, WAV format type, channels. */
861 psf_binheader_writef (psf
, "422", fmt_size
, WAVE_FORMAT_GSM610
, psf
->sf
.channels
) ;
863 /* fmt : samplerate, bytespersec. */
864 psf_binheader_writef (psf
, "44", psf
->sf
.samplerate
, bytespersec
) ;
866 /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
867 psf_binheader_writef (psf
, "2222", blockalign
, 0, 2, framesperblock
) ;
870 add_fact_chunk
= SF_TRUE
;
873 default : return SFE_UNIMPLEMENTED
;
877 psf_binheader_writef (psf
, "tm48", fact_MARKER
, 4, psf
->sf
.frames
) ;
880 } /* wav_write_fmt_chunk */
883 wavex_write_fmt_chunk (SF_PRIVATE
*psf
)
884 { WAV_PRIVATE
*wpriv
;
885 int subformat
, fmt_size
, add_fact_chunk
= 0 ;
887 if ((wpriv
= psf
->container_data
) == NULL
)
888 return SFE_INTERNAL
;
890 subformat
= SF_CODEC (psf
->sf
.format
) ;
892 /* initial section (same for all, it appears) */
894 { case SF_FORMAT_PCM_U8
:
895 case SF_FORMAT_PCM_16
:
896 case SF_FORMAT_PCM_24
:
897 case SF_FORMAT_PCM_32
:
898 case SF_FORMAT_FLOAT
:
899 case SF_FORMAT_DOUBLE
:
900 case SF_FORMAT_ULAW
:
901 case SF_FORMAT_ALAW
:
902 fmt_size
= 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 + 4 + 4 + 2 + 2 + 8 ;
904 /* fmt : format, channels, samplerate */
905 psf_binheader_writef (psf
, "4224", fmt_size
, WAVE_FORMAT_EXTENSIBLE
, psf
->sf
.channels
, psf
->sf
.samplerate
) ;
906 /* fmt : bytespersec */
907 psf_binheader_writef (psf
, "4", psf
->sf
.samplerate
* psf
->bytewidth
* psf
->sf
.channels
) ;
908 /* fmt : blockalign, bitwidth */
909 psf_binheader_writef (psf
, "22", psf
->bytewidth
* psf
->sf
.channels
, psf
->bytewidth
* 8) ;
911 /* cbSize 22 is sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX) */
912 psf_binheader_writef (psf
, "2", 22) ;
914 /* wValidBitsPerSample, for our use same as bitwidth as we use it fully */
915 psf_binheader_writef (psf
, "2", psf
->bytewidth
* 8) ;
917 /* For an Ambisonic file set the channel mask to zero.
918 ** Otherwise use a default based on the channel count.
920 if (wpriv
->wavex_ambisonic
!= SF_AMBISONIC_NONE
)
921 psf_binheader_writef (psf
, "4", 0) ;
922 else if (wpriv
->wavex_channelmask
!= 0)
923 psf_binheader_writef (psf
, "4", wpriv
->wavex_channelmask
) ;
926 ** Ok some liberty is taken here to use the most commonly used channel masks
927 ** instead of "no mapping". If you really want to use "no mapping" for 8 channels and less
928 ** please don't use wavex. (otherwise we'll have to create a new SF_COMMAND)
930 switch (psf
->sf
.channels
)
931 { case 1 : /* center channel mono */
932 psf_binheader_writef (psf
, "4", 0x4) ;
935 case 2 : /* front left and right */
936 psf_binheader_writef (psf
, "4", 0x1 | 0x2) ;
940 psf_binheader_writef (psf
, "4", 0x1 | 0x2 | 0x10 | 0x20) ;
944 psf_binheader_writef (psf
, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20) ;
948 psf_binheader_writef (psf
, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80) ;
951 default : /* 0 when in doubt , use direct out, ie NO mapping*/
952 psf_binheader_writef (psf
, "4", 0x0) ;
958 case SF_FORMAT_MS_ADPCM
: /* Todo, GUID exists might have different header as per wav_write_header */
960 return SFE_UNIMPLEMENTED
;
963 /* GUID section, different for each */
966 { case SF_FORMAT_PCM_U8
:
967 case SF_FORMAT_PCM_16
:
968 case SF_FORMAT_PCM_24
:
969 case SF_FORMAT_PCM_32
:
970 wavex_write_guid (psf
, wpriv
->wavex_ambisonic
== SF_AMBISONIC_NONE
?
971 &MSGUID_SUBTYPE_PCM
: &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM
) ;
974 case SF_FORMAT_FLOAT
:
975 case SF_FORMAT_DOUBLE
:
976 wavex_write_guid (psf
, wpriv
->wavex_ambisonic
== SF_AMBISONIC_NONE
?
977 &MSGUID_SUBTYPE_IEEE_FLOAT
: &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT
) ;
978 add_fact_chunk
= SF_TRUE
;
981 case SF_FORMAT_ULAW
:
982 wavex_write_guid (psf
, &MSGUID_SUBTYPE_MULAW
) ;
983 add_fact_chunk
= SF_TRUE
;
986 case SF_FORMAT_ALAW
:
987 wavex_write_guid (psf
, &MSGUID_SUBTYPE_ALAW
) ;
988 add_fact_chunk
= SF_TRUE
;
992 /* This is dead code due to return in previous switch statement. */
993 case SF_FORMAT_MS_ADPCM
: /* todo, GUID exists */
994 wavex_write_guid (psf
, &MSGUID_SUBTYPE_MS_ADPCM
) ;
995 add_fact_chunk
= SF_TRUE
;
997 return SFE_UNIMPLEMENTED
;
1000 default : return SFE_UNIMPLEMENTED
;
1004 psf_binheader_writef (psf
, "tm48", fact_MARKER
, 4, psf
->sf
.frames
) ;
1007 } /* wavex_write_fmt_chunk */
1011 wav_write_header (SF_PRIVATE
*psf
, int calc_length
)
1012 { sf_count_t current
;
1013 int k
, error
, has_data
= SF_FALSE
;
1015 current
= psf_ftell (psf
) ;
1017 if (current
> psf
->dataoffset
)
1018 has_data
= SF_TRUE
;
1021 { psf
->filelength
= psf_get_filelen (psf
) ;
1023 psf
->datalength
= psf
->filelength
- psf
->dataoffset
;
1026 psf
->datalength
-= psf
->filelength
- psf
->dataend
;
1028 if (psf
->bytewidth
> 0)
1029 psf
->sf
.frames
= psf
->datalength
/ (psf
->bytewidth
* psf
->sf
.channels
) ;
1032 /* Reset the current header length to zero. */
1033 psf
->header
[0] = 0 ;
1034 psf
->headindex
= 0 ;
1035 psf_fseek (psf
, 0, SEEK_SET
) ;
1038 ** RIFX signifies big-endian format for all header and data.
1039 ** To prevent lots of code copying here, we'll set the psf->rwf_endian flag
1040 ** once here, and never specify endian-ness for all other header operations.
1043 /* RIFF/RIFX marker, length, WAVE and 'fmt ' markers. */
1045 if (psf
->endian
== SF_ENDIAN_LITTLE
)
1046 psf_binheader_writef (psf
, "etm8", RIFF_MARKER
, (psf
->filelength
< 8) ? 8 : psf
->filelength
- 8) ;
1048 psf_binheader_writef (psf
, "Etm8", RIFX_MARKER
, (psf
->filelength
< 8) ? 8 : psf
->filelength
- 8) ;
1050 /* WAVE and 'fmt ' markers. */
1051 psf_binheader_writef (psf
, "mm", WAVE_MARKER
, fmt_MARKER
) ;
1053 /* Write the 'fmt ' chunk. */
1054 switch (SF_CONTAINER (psf
->sf
.format
))
1055 { case SF_FORMAT_WAV
:
1056 if ((error
= wav_write_fmt_chunk (psf
)) != 0)
1060 case SF_FORMAT_WAVEX
:
1061 if ((error
= wavex_write_fmt_chunk (psf
)) != 0)
1066 return SFE_UNIMPLEMENTED
;
1069 /* The LIST/INFO chunk. */
1070 if (psf
->str_flags
& SF_STR_LOCATE_START
)
1071 wav_write_strings (psf
, SF_STR_LOCATE_START
) ;
1073 if (psf
->peak_info
!= NULL
&& psf
->peak_info
->peak_loc
== SF_PEAK_START
)
1074 { psf_binheader_writef (psf
, "m4", PEAK_MARKER
, WAV_PEAK_CHUNK_SIZE (psf
->sf
.channels
)) ;
1075 psf_binheader_writef (psf
, "44", 1, time (NULL
)) ;
1076 for (k
= 0 ; k
< psf
->sf
.channels
; k
++)
1077 psf_binheader_writef (psf
, "ft8", (float) psf
->peak_info
->peaks
[k
].value
, psf
->peak_info
->peaks
[k
].position
) ;
1080 if (psf
->broadcast_16k
!= NULL
)
1081 wav_write_bext_chunk (psf
) ;
1083 if (psf
->instrument
!= NULL
)
1085 double dtune
= (double) (0x40000000) / 25.0 ;
1087 psf_binheader_writef (psf
, "m4", smpl_MARKER
, 9 * 4 + psf
->instrument
->loop_count
* 6 * 4) ;
1088 psf_binheader_writef (psf
, "44", 0, 0) ; /* Manufacturer zero is everyone */
1089 tmp
= (int) (1.0e9
/ psf
->sf
.samplerate
) ; /* Sample period in nano seconds */
1090 psf_binheader_writef (psf
, "44", tmp
, psf
->instrument
->basenote
) ;
1091 tmp
= (unsigned int) (psf
->instrument
->detune
* dtune
+ 0.5) ;
1092 psf_binheader_writef (psf
, "4", tmp
) ;
1093 psf_binheader_writef (psf
, "44", 0, 0) ; /* SMTPE format */
1094 psf_binheader_writef (psf
, "44", psf
->instrument
->loop_count
, 0) ;
1096 for (tmp
= 0 ; tmp
< psf
->instrument
->loop_count
; tmp
++)
1099 type
= psf
->instrument
->loops
[tmp
].mode
;
1100 type
= (type
== SF_LOOP_FORWARD
? 0 : type
==SF_LOOP_BACKWARD
? 2 : type
== SF_LOOP_ALTERNATING
? 1 : 32) ;
1102 psf_binheader_writef (psf
, "44", tmp
, type
) ;
1103 psf_binheader_writef (psf
, "44", psf
->instrument
->loops
[tmp
].start
, psf
->instrument
->loops
[tmp
].end
- 1) ;
1104 psf_binheader_writef (psf
, "44", 0, psf
->instrument
->loops
[tmp
].count
) ;
1108 if (psf
->headindex
+ 16 < psf
->dataoffset
)
1109 { /* Add PAD data if necessary. */
1110 k
= psf
->dataoffset
- (psf
->headindex
+ 16) ;
1111 psf_binheader_writef (psf
, "m4z", PAD_MARKER
, k
, make_size_t (k
)) ;
1114 psf_binheader_writef (psf
, "tm8", data_MARKER
, psf
->datalength
) ;
1115 psf_fwrite (psf
->header
, psf
->headindex
, 1, psf
) ;
1119 if (has_data
&& psf
->dataoffset
!= psf
->headindex
)
1120 { psf_log_printf (psf
, "Oooops : has_data && psf->dataoffset != psf->headindex\n") ;
1121 return psf
->error
= SFE_INTERNAL
;
1124 psf
->dataoffset
= psf
->headindex
;
1127 psf_fseek (psf
, psf
->dataoffset
, SEEK_SET
) ;
1128 else if (current
> 0)
1129 psf_fseek (psf
, current
, SEEK_SET
) ;
1132 } /* wav_write_header */
1136 wav_write_tailer (SF_PRIVATE
*psf
)
1139 /* Reset the current header buffer length to zero. */
1140 psf
->header
[0] = 0 ;
1141 psf
->headindex
= 0 ;
1143 if (psf
->dataend
> 0)
1144 psf_fseek (psf
, psf
->dataend
, SEEK_SET
) ;
1146 psf
->dataend
= psf_fseek (psf
, 0, SEEK_END
) ;
1148 /* Add a PEAK chunk if requested. */
1149 if (psf
->peak_info
!= NULL
&& psf
->peak_info
->peak_loc
== SF_PEAK_END
)
1150 { psf_binheader_writef (psf
, "m4", PEAK_MARKER
, WAV_PEAK_CHUNK_SIZE (psf
->sf
.channels
)) ;
1151 psf_binheader_writef (psf
, "44", 1, time (NULL
)) ;
1152 for (k
= 0 ; k
< psf
->sf
.channels
; k
++)
1153 psf_binheader_writef (psf
, "f4", psf
->peak_info
->peaks
[k
].value
, psf
->peak_info
->peaks
[k
].position
) ;
1156 if (psf
->str_flags
& SF_STR_LOCATE_END
)
1157 wav_write_strings (psf
, SF_STR_LOCATE_END
) ;
1159 /* Write the tailer. */
1160 if (psf
->headindex
> 0)
1161 psf_fwrite (psf
->header
, psf
->headindex
, 1, psf
) ;
1164 } /* wav_write_tailer */
1167 wav_write_strings (SF_PRIVATE
*psf
, int location
)
1168 { int k
, prev_head_index
, saved_head_index
;
1170 if (psf_location_string_count (psf
, location
) == 0)
1173 prev_head_index
= psf
->headindex
+ 4 ;
1175 psf_binheader_writef (psf
, "m4m", LIST_MARKER
, 0xBADBAD, INFO_MARKER
) ;
1177 for (k
= 0 ; k
< SF_MAX_STRINGS
; k
++)
1178 { if (psf
->strings
[k
].type
== 0)
1180 if (psf
->strings
[k
].type
< 0 || psf
->strings
[k
].flags
!= location
)
1183 switch (psf
->strings
[k
].type
)
1184 { case SF_STR_SOFTWARE
:
1185 psf_binheader_writef (psf
, "ms", ISFT_MARKER
, psf
->strings
[k
].str
) ;
1189 psf_binheader_writef (psf
, "ms", INAM_MARKER
, psf
->strings
[k
].str
) ;
1192 case SF_STR_COPYRIGHT
:
1193 psf_binheader_writef (psf
, "ms", ICOP_MARKER
, psf
->strings
[k
].str
) ;
1196 case SF_STR_ARTIST
:
1197 psf_binheader_writef (psf
, "ms", IART_MARKER
, psf
->strings
[k
].str
) ;
1200 case SF_STR_COMMENT
:
1201 psf_binheader_writef (psf
, "ms", ICMT_MARKER
, psf
->strings
[k
].str
) ;
1205 psf_binheader_writef (psf
, "ms", ICRD_MARKER
, psf
->strings
[k
].str
) ;
1209 psf_binheader_writef (psf
, "ms", IGNR_MARKER
, psf
->strings
[k
].str
) ;
1217 saved_head_index
= psf
->headindex
;
1218 psf
->headindex
= prev_head_index
;
1219 psf_binheader_writef (psf
, "4", saved_head_index
- prev_head_index
- 4) ;
1220 psf
->headindex
= saved_head_index
;
1222 } /* wav_write_strings */
1225 wav_close (SF_PRIVATE
*psf
)
1227 if (psf
->file
.mode
== SFM_WRITE
|| psf
->file
.mode
== SFM_RDWR
)
1228 { wav_write_tailer (psf
) ;
1230 if (psf
->file
.mode
== SFM_RDWR
)
1231 { sf_count_t current
= psf_ftell (psf
) ;
1234 ** If the mode is RDWR and the current position is less than the
1235 ** filelength, truncate the file.
1238 if (current
< psf
->filelength
)
1239 { psf_ftruncate (psf
, current
) ;
1240 psf
->filelength
= current
;
1244 psf
->write_header (psf
, SF_TRUE
) ;
1251 wav_command (SF_PRIVATE
*psf
, int command
, void * UNUSED (data
), int datasize
)
1252 { WAV_PRIVATE
*wpriv
;
1254 if ((wpriv
= psf
->container_data
) == NULL
)
1255 return SFE_INTERNAL
;
1258 { case SFC_WAVEX_SET_AMBISONIC
:
1259 if ((SF_CONTAINER (psf
->sf
.format
)) == SF_FORMAT_WAVEX
)
1260 { if (datasize
== SF_AMBISONIC_NONE
)
1261 wpriv
->wavex_ambisonic
= SF_AMBISONIC_NONE
;
1262 else if (datasize
== SF_AMBISONIC_B_FORMAT
)
1263 wpriv
->wavex_ambisonic
= SF_AMBISONIC_B_FORMAT
;
1267 return wpriv
->wavex_ambisonic
;
1269 case SFC_WAVEX_GET_AMBISONIC
:
1270 return wpriv
->wavex_ambisonic
;
1272 case SFC_SET_CHANNEL_MAP_INFO
:
1273 wpriv
->wavex_channelmask
= wavex_gen_channel_mask (psf
->channel_map
, psf
->sf
.channels
) ;
1274 return (wpriv
->wavex_channelmask
!= 0) ;
1284 wav_subchunk_parse (SF_PRIVATE
*psf
, int chunk
)
1285 { sf_count_t current_pos
;
1287 unsigned dword
, bytesread
, length
;
1289 current_pos
= psf_fseek (psf
, 0, SEEK_CUR
) ;
1291 bytesread
= psf_binheader_readf (psf
, "4", &length
) ;
1294 { /* This case is for broken files generated by PEAK. */
1295 psf_log_printf (psf
, "%M : %d (weird length)\n", chunk
, length
) ;
1296 psf_binheader_readf (psf
, "mj", &chunk
, length
- 4) ;
1297 psf_log_printf (psf
, " %M\n", chunk
) ;
1301 if (psf
->headindex
+ length
> SIGNED_SIZEOF (psf
->header
))
1302 { psf_log_printf (psf
, "%M : %d (too long)\n", chunk
, length
) ;
1303 psf_binheader_readf (psf
, "j", length
) ;
1307 if (current_pos
+ length
> psf
->filelength
)
1308 { psf_log_printf (psf
, "%M : %d (should be %d)\n", chunk
, length
, (int) (psf
->filelength
- current_pos
)) ;
1309 length
= psf
->filelength
- current_pos
;
1312 psf_log_printf (psf
, "%M : %d\n", chunk
, length
) ;
1314 while (bytesread
< length
)
1315 { bytesread
+= psf_binheader_readf (psf
, "m", &chunk
) ;
1318 { case adtl_MARKER
:
1320 /* These markers don't contain anything. */
1321 psf_log_printf (psf
, " %M\n", chunk
) ;
1325 psf_log_printf (psf
, " %M inside a LIST block??? Backing out.\n", chunk
) ;
1326 /* Jump back four bytes and return to caller. */
1327 psf_binheader_readf (psf
, "j", -4) ;
1342 bytesread
+= psf_binheader_readf (psf
, "4", &dword
) ;
1343 dword
+= (dword
& 1) ;
1344 if (dword
>= SIGNED_SIZEOF (psf
->u
.cbuf
))
1345 { psf_log_printf (psf
, " *** %M : %d (too big)\n", chunk
, dword
) ;
1346 psf_binheader_readf (psf
, "j", dword
) ;
1350 cptr
= psf
->u
.cbuf
;
1351 psf_binheader_readf (psf
, "b", cptr
, dword
) ;
1352 bytesread
+= dword
;
1354 psf_log_printf (psf
, " %M : %s\n", chunk
, cptr
) ;
1360 bytesread
+= psf_binheader_readf (psf
, "44", &dword
, &mark_id
) ;
1362 dword
+= (dword
& 1) ;
1363 if (dword
< 1 || dword
>= SIGNED_SIZEOF (psf
->u
.cbuf
))
1364 { psf_log_printf (psf
, " *** %M : %d (too big)\n", chunk
, dword
) ;
1365 psf_binheader_readf (psf
, "j", dword
) ;
1369 cptr
= psf
->u
.cbuf
;
1370 psf_binheader_readf (psf
, "b", cptr
, dword
) ;
1371 bytesread
+= dword
;
1373 psf_log_printf (psf
, " %M : %d : %s\n", chunk
, mark_id
, cptr
) ;
1381 bytesread
+= psf_binheader_readf (psf
, "4", &dword
) ;
1382 dword
+= (dword
& 1) ;
1383 psf_binheader_readf (psf
, "j", dword
) ;
1384 bytesread
+= dword
;
1385 psf_log_printf (psf
, " %M : %d\n", chunk
, dword
) ;
1389 psf_log_printf (psf
, " %M\n", chunk
) ;
1390 bytesread
+= exif_subchunk_parse (psf
, length
- bytesread
) ;
1395 ** Four zero bytes where a marker was expected. Assume this means
1396 ** the rest of the chunk is garbage.
1398 psf_log_printf (psf
, " *** Found weird-ass zero marker. Jumping to end of chunk.\n") ;
1399 if (bytesread
< length
)
1400 bytesread
+= psf_binheader_readf (psf
, "j", length
- bytesread
+ 4) ;
1401 psf_log_printf (psf
, " *** Offset is now : 0x%X\n", psf_fseek (psf
, 0, SEEK_CUR
)) ;
1405 psf_binheader_readf (psf
, "4", &dword
) ;
1406 bytesread
+= sizeof (dword
) ;
1407 dword
+= (dword
& 1) ;
1408 psf_binheader_readf (psf
, "j", dword
) ;
1409 bytesread
+= dword
;
1410 psf_log_printf (psf
, " *** %M : %d\n", chunk
, dword
) ;
1417 { case ISFT_MARKER
:
1418 psf_store_string (psf
, SF_STR_SOFTWARE
, psf
->u
.cbuf
) ;
1421 psf_store_string (psf
, SF_STR_COPYRIGHT
, psf
->u
.cbuf
) ;
1424 psf_store_string (psf
, SF_STR_TITLE
, psf
->u
.cbuf
) ;
1427 psf_store_string (psf
, SF_STR_ARTIST
, psf
->u
.cbuf
) ;
1430 psf_store_string (psf
, SF_STR_COMMENT
, psf
->u
.cbuf
) ;
1433 psf_store_string (psf
, SF_STR_DATE
, psf
->u
.cbuf
) ;
1436 psf_store_string (psf
, SF_STR_GENRE
, psf
->u
.cbuf
) ;
1441 current_pos
= psf_fseek (psf
, 0, SEEK_CUR
) - current_pos
;
1443 if (current_pos
- 4 != length
)
1444 psf_log_printf (psf
, "**** Bad chunk length %d sbould be %D\n", length
, current_pos
- 4) ;
1447 } /* wav_subchunk_parse */
1450 wav_read_smpl_chunk (SF_PRIVATE
*psf
, unsigned int chunklen
)
1451 { unsigned int bytesread
= 0, dword
, sampler_data
, loop_count
;
1452 unsigned int note
, start
, end
, type
= -1, count
;
1455 chunklen
+= (chunklen
& 1) ;
1457 bytesread
+= psf_binheader_readf (psf
, "4", &dword
) ;
1458 psf_log_printf (psf
, " Manufacturer : %X\n", dword
) ;
1460 bytesread
+= psf_binheader_readf (psf
, "4", &dword
) ;
1461 psf_log_printf (psf
, " Product : %u\n", dword
) ;
1463 bytesread
+= psf_binheader_readf (psf
, "4", &dword
) ;
1464 psf_log_printf (psf
, " Period : %u nsec\n", dword
) ;
1466 bytesread
+= psf_binheader_readf (psf
, "4", ¬e
) ;
1467 psf_log_printf (psf
, " Midi Note : %u\n", note
) ;
1469 bytesread
+= psf_binheader_readf (psf
, "4", &dword
) ;
1471 { snprintf (psf
->u
.cbuf
, sizeof (psf
->u
.cbuf
), "%f",
1472 (1.0 * 0x80000000) / ((unsigned int) dword
)) ;
1473 psf_log_printf (psf
, " Pitch Fract. : %s\n", psf
->u
.cbuf
) ;
1476 psf_log_printf (psf
, " Pitch Fract. : 0\n") ;
1478 bytesread
+= psf_binheader_readf (psf
, "4", &dword
) ;
1479 psf_log_printf (psf
, " SMPTE Format : %u\n", dword
) ;
1481 bytesread
+= psf_binheader_readf (psf
, "4", &dword
) ;
1482 snprintf (psf
->u
.cbuf
, sizeof (psf
->u
.cbuf
), "%02d:%02d:%02d %02d",
1483 (dword
>> 24) & 0x7F, (dword
>> 16) & 0x7F, (dword
>> 8) & 0x7F, dword
& 0x7F) ;
1484 psf_log_printf (psf
, " SMPTE Offset : %s\n", psf
->u
.cbuf
) ;
1486 bytesread
+= psf_binheader_readf (psf
, "4", &loop_count
) ;
1487 psf_log_printf (psf
, " Loop Count : %u\n", loop_count
) ;
1489 /* Sampler Data holds the number of data bytes after the CUE chunks which
1490 ** is not actually CUE data. Display value after CUE data.
1492 bytesread
+= psf_binheader_readf (psf
, "4", &sampler_data
) ;
1494 if ((psf
->instrument
= psf_instrument_alloc ()) == NULL
)
1495 return SFE_MALLOC_FAILED
;
1497 psf
->instrument
->loop_count
= loop_count
;
1499 for (j
= 0 ; loop_count
> 0 && chunklen
- bytesread
>= 24 ; j
++)
1500 { bytesread
+= psf_binheader_readf (psf
, "4", &dword
) ;
1501 psf_log_printf (psf
, " Cue ID : %2u", dword
) ;
1503 bytesread
+= psf_binheader_readf (psf
, "4", &type
) ;
1504 psf_log_printf (psf
, " Type : %2u", type
) ;
1506 bytesread
+= psf_binheader_readf (psf
, "4", &start
) ;
1507 psf_log_printf (psf
, " Start : %5u", start
) ;
1509 bytesread
+= psf_binheader_readf (psf
, "4", &end
) ;
1510 psf_log_printf (psf
, " End : %5u", end
) ;
1512 bytesread
+= psf_binheader_readf (psf
, "4", &dword
) ;
1513 psf_log_printf (psf
, " Fraction : %5u", dword
) ;
1515 bytesread
+= psf_binheader_readf (psf
, "4", &count
) ;
1516 psf_log_printf (psf
, " Count : %5u\n", count
) ;
1518 if (j
< ARRAY_LEN (psf
->instrument
->loops
))
1519 { psf
->instrument
->loops
[j
].start
= start
;
1520 psf
->instrument
->loops
[j
].end
= end
+ 1 ;
1521 psf
->instrument
->loops
[j
].count
= count
;
1525 psf
->instrument
->loops
[j
].mode
= SF_LOOP_FORWARD
;
1528 psf
->instrument
->loops
[j
].mode
= SF_LOOP_ALTERNATING
;
1531 psf
->instrument
->loops
[j
].mode
= SF_LOOP_BACKWARD
;
1534 psf
->instrument
->loops
[j
].mode
= SF_LOOP_NONE
;
1542 if (chunklen
- bytesread
== 0)
1543 { if (sampler_data
!= 0)
1544 psf_log_printf (psf
, " Sampler Data : %u (should be 0)\n", sampler_data
) ;
1546 psf_log_printf (psf
, " Sampler Data : %u\n", sampler_data
) ;
1549 { if (sampler_data
!= chunklen
- bytesread
)
1550 { psf_log_printf (psf
, " Sampler Data : %u (should have been %u)\n", sampler_data
, chunklen
- bytesread
) ;
1551 sampler_data
= chunklen
- bytesread
;
1554 psf_log_printf (psf
, " Sampler Data : %u\n", sampler_data
) ;
1556 psf_log_printf (psf
, " ") ;
1557 for (k
= 0 ; k
< (int) sampler_data
; k
++)
1560 if (k
> 0 && (k
% 20) == 0)
1561 psf_log_printf (psf
, "\n ") ;
1563 bytesread
+= psf_binheader_readf (psf
, "1", &ch
) ;
1564 psf_log_printf (psf
, "%02X ", ch
& 0xFF) ;
1567 psf_log_printf (psf
, "\n") ;
1570 psf
->instrument
->basenote
= note
;
1571 psf
->instrument
->gain
= 1 ;
1572 psf
->instrument
->velocity_lo
= psf
->instrument
->key_lo
= 0 ;
1573 psf
->instrument
->velocity_hi
= psf
->instrument
->key_hi
= 127 ;
1576 } /* wav_read_smpl_chunk */
1579 ** The acid chunk goes a little something like this:
1582 ** 4 bytes (int) length of chunk starting at next byte
1584 ** 4 bytes (int) type of file:
1585 ** this appears to be a bit mask,however some combinations
1586 ** are probably impossible and/or qualified as "errors"
1588 ** 0x01 On: One Shot Off: Loop
1589 ** 0x02 On: Root note is Set Off: No root
1590 ** 0x04 On: Stretch is On, Off: Strech is OFF
1591 ** 0x08 On: Disk Based Off: Ram based
1592 ** 0x10 On: ?????????? Off: ????????? (Acidizer puts that ON)
1594 ** 2 bytes (short) root note
1595 ** if type 0x10 is OFF : [C,C#,(...),B] -> [0x30 to 0x3B]
1596 ** if type 0x10 is ON : [C,C#,(...),B] -> [0x3C to 0x47]
1597 ** (both types fit on same MIDI pitch albeit different octaves, so who cares)
1599 ** 2 bytes (short) ??? always set to 0x8000
1600 ** 4 bytes (float) ??? seems to be always 0
1601 ** 4 bytes (int) number of beats
1602 ** 2 bytes (short) meter denominator //always 4 in SF/ACID
1603 ** 2 bytes (short) meter numerator //always 4 in SF/ACID
1604 ** //are we sure about the order?? usually its num/denom
1605 ** 4 bytes (float) tempo
1610 wav_read_acid_chunk (SF_PRIVATE
*psf
, unsigned int chunklen
)
1611 { unsigned int bytesread
= 0 ;
1613 short rootnote
, q1
, meter_denom
, meter_numer
;
1616 chunklen
+= (chunklen
& 1) ;
1618 bytesread
+= psf_binheader_readf (psf
, "422f", &flags
, &rootnote
, &q1
, &q2
) ;
1620 snprintf (psf
->u
.cbuf
, sizeof (psf
->u
.cbuf
), "%f", q2
) ;
1622 psf_log_printf (psf
, " Flags : 0x%04x (%s,%s,%s,%s,%s)\n", flags
,
1623 (flags
& 0x01) ? "OneShot" : "Loop",
1624 (flags
& 0x02) ? "RootNoteValid" : "RootNoteInvalid",
1625 (flags
& 0x04) ? "StretchOn" : "StretchOff",
1626 (flags
& 0x08) ? "DiskBased" : "RAMBased",
1627 (flags
& 0x10) ? "??On" : "??Off") ;
1629 psf_log_printf (psf
, " Root note : 0x%x\n ???? : 0x%04x\n ???? : %s\n",
1630 rootnote
, q1
, psf
->u
.cbuf
) ;
1632 bytesread
+= psf_binheader_readf (psf
, "422f", &beats
, &meter_denom
, &meter_numer
, &tempo
) ;
1633 snprintf (psf
->u
.cbuf
, sizeof (psf
->u
.cbuf
), "%f", tempo
) ;
1634 psf_log_printf (psf
, " Beats : %d\n Meter : %d/%d\n Tempo : %s\n",
1635 beats
, meter_numer
, meter_denom
, psf
->u
.cbuf
) ;
1637 psf_binheader_readf (psf
, "j", chunklen
- bytesread
) ;
1639 if ((psf
->loop_info
= calloc (1, sizeof (SF_LOOP_INFO
))) == NULL
)
1640 return SFE_MALLOC_FAILED
;
1642 psf
->loop_info
->time_sig_num
= meter_numer
;
1643 psf
->loop_info
->time_sig_den
= meter_denom
;
1644 psf
->loop_info
->loop_mode
= (flags
& 0x01) ? SF_LOOP_NONE
: SF_LOOP_FORWARD
;
1645 psf
->loop_info
->num_beats
= beats
;
1646 psf
->loop_info
->bpm
= tempo
;
1647 psf
->loop_info
->root_key
= (flags
& 0x02) ? rootnote
: -1 ;
1650 } /* wav_read_acid_chunk */
1653 wav_read_bext_chunk (SF_PRIVATE
*psf
, unsigned int chunksize
)
1655 SF_BROADCAST_INFO_16K
* b
;
1656 unsigned int bytes
= 0 ;
1658 if (chunksize
< WAV_BEXT_MIN_CHUNK_SIZE
)
1659 { psf_log_printf (psf
, "bext : %u (should be >= %d)\n", chunksize
, WAV_BEXT_MIN_CHUNK_SIZE
) ;
1660 psf_binheader_readf (psf
, "j", chunksize
) ;
1664 if (chunksize
> WAV_BEXT_MAX_CHUNK_SIZE
)
1665 { psf_log_printf (psf
, "bext : %u (should be < %d)\n", chunksize
, WAV_BEXT_MAX_CHUNK_SIZE
) ;
1666 psf_binheader_readf (psf
, "j", chunksize
) ;
1670 if (chunksize
>= sizeof (SF_BROADCAST_INFO_16K
))
1671 { psf_log_printf (psf
, "bext : %u too big to be handled\n", chunksize
) ;
1672 psf_binheader_readf (psf
, "j", chunksize
) ;
1676 psf_log_printf (psf
, "bext : %u\n", chunksize
) ;
1678 if ((psf
->broadcast_16k
= broadcast_var_alloc ()) == NULL
)
1679 { psf
->error
= SFE_MALLOC_FAILED
;
1683 b
= psf
->broadcast_16k
;
1685 bytes
+= psf_binheader_readf (psf
, "b", b
->description
, sizeof (b
->description
)) ;
1686 bytes
+= psf_binheader_readf (psf
, "b", b
->originator
, sizeof (b
->originator
)) ;
1687 bytes
+= psf_binheader_readf (psf
, "b", b
->originator_reference
, sizeof (b
->originator_reference
)) ;
1688 bytes
+= psf_binheader_readf (psf
, "b", b
->origination_date
, sizeof (b
->origination_date
)) ;
1689 bytes
+= psf_binheader_readf (psf
, "b", b
->origination_time
, sizeof (b
->origination_time
)) ;
1690 bytes
+= psf_binheader_readf (psf
, "442", &b
->time_reference_low
, &b
->time_reference_high
, &b
->version
) ;
1691 bytes
+= psf_binheader_readf (psf
, "bj", &b
->umid
, sizeof (b
->umid
), 190) ;
1693 if (chunksize
> WAV_BEXT_MIN_CHUNK_SIZE
)
1694 { /* File has coding history data. */
1696 b
->coding_history_size
= chunksize
- WAV_BEXT_MIN_CHUNK_SIZE
;
1698 /* We do not parse the coding history */
1699 bytes
+= psf_binheader_readf (psf
, "b", b
->coding_history
, b
->coding_history_size
) ;
1702 if (bytes
< chunksize
)
1703 psf_binheader_readf (psf
, "j", chunksize
- bytes
) ;
1706 } /* wav_read_bext_chunk */
1709 wav_write_bext_chunk (SF_PRIVATE
*psf
)
1710 { SF_BROADCAST_INFO_16K
*b
;
1712 if (psf
->broadcast_16k
== NULL
)
1715 b
= psf
->broadcast_16k
;
1717 psf_binheader_writef (psf
, "m4", bext_MARKER
, WAV_BEXT_MIN_CHUNK_SIZE
+ b
->coding_history_size
) ;
1720 ** Note that it is very important the the field widths of the SF_BROADCAST_INFO
1721 ** struct match those for the bext chunk fields.
1724 psf_binheader_writef (psf
, "b", b
->description
, sizeof (b
->description
)) ;
1725 psf_binheader_writef (psf
, "b", b
->originator
, sizeof (b
->originator
)) ;
1726 psf_binheader_writef (psf
, "b", b
->originator_reference
, sizeof (b
->originator_reference
)) ;
1727 psf_binheader_writef (psf
, "b", b
->origination_date
, sizeof (b
->origination_date
)) ;
1728 psf_binheader_writef (psf
, "b", b
->origination_time
, sizeof (b
->origination_time
)) ;
1729 psf_binheader_writef (psf
, "442", b
->time_reference_low
, b
->time_reference_high
, b
->version
) ;
1730 psf_binheader_writef (psf
, "b", b
->umid
, sizeof (b
->umid
)) ;
1731 psf_binheader_writef (psf
, "z", make_size_t (190)) ;
1733 if (b
->coding_history_size
> 0)
1734 psf_binheader_writef (psf
, "b", b
->coding_history
, make_size_t (b
->coding_history_size
)) ;
1737 } /* wav_write_bext_chunk */
1740 exif_fill_and_sink (SF_PRIVATE
*psf
, char* buf
, size_t bufsz
, size_t toread
)
1742 size_t bytesread
= 0 ;
1748 bytesread
= psf_binheader_readf (psf
, "b", buf
, bufsz
) ;
1751 if (bytesread
== bufsz
&& toread
> bufsz
)
1752 bytesread
+= psf_binheader_readf (psf
, "j", toread
- bufsz
) ;
1755 } /* exif_fill_and_sink */
1758 ** Exif specification for audio files, at JEITA CP-3451 Exif 2.2 section 5
1759 ** (Exif Audio File Specification) http://www.exif.org/Exif2-2.PDF
1762 exif_subchunk_parse (SF_PRIVATE
*psf
, unsigned int length
)
1763 { unsigned marker
, dword
, vmajor
= -1, vminor
= -1, bytesread
= 0 ;
1766 while (bytesread
< length
)
1768 bytesread
+= psf_binheader_readf (psf
, "m", &marker
) ;
1772 case 0 : /* camera padding? */
1776 bytesread
+= psf_binheader_readf (psf
, "j4", 4, &dword
) ;
1777 vmajor
= 10 * (((dword
>> 24) & 0xff) - '0') + (((dword
>> 16) & 0xff) - '0') ;
1778 vminor
= 10 * (((dword
>> 8) & 0xff) - '0') + ((dword
& 0xff) - '0') ;
1779 psf_log_printf (psf
, " EXIF Version : %u.%02u\n", vmajor
, vminor
) ;
1782 case emnt_MARKER
: /* design information: null-terminated string */
1783 case emdl_MARKER
: /* model name ; null-terminated string */
1784 case ecor_MARKER
: /* manufacturer: null-terminated string */
1785 case etim_MARKER
: /* creation time: null-terminated string in the format "hour:minute:second.subsecond" */
1786 case erel_MARKER
: /* relation info: null-terminated string (filename) */
1787 case eucm_MARKER
: /* user comment: 4-byte size follows, then possibly unicode data */
1788 psf_binheader_readf (psf
, "4", &dword
) ;
1789 bytesread
+= sizeof (dword
) ;
1790 dword
+= (dword
& 1) ;
1792 if (dword
>= sizeof (buf
))
1793 { psf_log_printf (psf
, "*** Marker '%M' is too big %u\n\n", marker
, dword
) ;
1797 bytesread
+= exif_fill_and_sink (psf
, buf
, sizeof (buf
), dword
) ;
1799 /* BAD - don't know what's going on here -- maybe a bug in the camera */
1800 /* field should be NULL-terminated but there's no room for it with the reported number */
1801 /* example output: emdl : 8 (EX-Z1050) */
1802 if (marker
== emdl_MARKER
&& dword
== strlen (buf
) /* should be >= strlen+1*/)
1803 { psf_log_printf (psf
, " *** field size too small for string (sinking 2 bytes)\n") ;
1804 bytesread
+= psf_binheader_readf (psf
, "j", 2) ;
1807 psf_log_printf (psf
, " %M : %d (%s)\n", marker
, dword
, buf
) ;
1813 psf_log_printf (psf
, " *** %M (%d): -- ignored --\n", marker
, marker
) ;
1819 } /* exif_subchunk_parse */