Merge remote-tracking branch 'remotes/origin/upstream' into tizen
[platform/upstream/libsndfile.git] / src / wav.c
1 /*
2 ** Copyright (C) 1999-2015 Erik de Castro Lopo <erikd@mega-nerd.com>
3 ** Copyright (C) 2004-2005 David Viens <davidv@plogue.com>
4 **
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.
9 **
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.
14 **
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.
18 */
19
20 #include        "sfconfig.h"
21
22 #include        <stdio.h>
23 #include        <stdlib.h>
24 #include        <string.h>
25 #include        <ctype.h>
26 #include        <time.h>
27 #include        <inttypes.h>
28
29 #include        "sndfile.h"
30 #include        "sfendian.h"
31 #include        "common.h"
32 #include        "wav_w64.h"
33
34 /*------------------------------------------------------------------------------
35  * Macros to handle big/little endian issues.
36  */
37
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'))
45
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'))
70
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'))
79 #define olym_MARKER             (MAKE_MARKER ('o', 'l', 'y', 'm'))
80 #define minf_MARKER             (MAKE_MARKER ('m', 'i', 'n', 'f'))
81 #define elm1_MARKER             (MAKE_MARKER ('e', 'l', 'm', '1'))
82 #define regn_MARKER             (MAKE_MARKER ('r', 'e', 'g', 'n'))
83 #define ovwf_MARKER             (MAKE_MARKER ('o', 'v', 'w', 'f'))
84 #define umid_MARKER             (MAKE_MARKER ('u', 'm', 'i', 'd'))
85 #define SyLp_MARKER             (MAKE_MARKER ('S', 'y', 'L', 'p'))
86 #define Cr8r_MARKER             (MAKE_MARKER ('C', 'r', '8', 'r'))
87 #define JUNK_MARKER             (MAKE_MARKER ('J', 'U', 'N', 'K'))
88 #define PMX_MARKER              (MAKE_MARKER ('_', 'P', 'M', 'X'))
89 #define inst_MARKER             (MAKE_MARKER ('i', 'n', 's', 't'))
90 #define AFAn_MARKER             (MAKE_MARKER ('A', 'F', 'A', 'n'))
91
92
93 #define ISFT_MARKER             (MAKE_MARKER ('I', 'S', 'F', 'T'))
94 #define ICRD_MARKER             (MAKE_MARKER ('I', 'C', 'R', 'D'))
95 #define ICOP_MARKER             (MAKE_MARKER ('I', 'C', 'O', 'P'))
96 #define IARL_MARKER             (MAKE_MARKER ('I', 'A', 'R', 'L'))
97 #define IART_MARKER             (MAKE_MARKER ('I', 'A', 'R', 'T'))
98 #define INAM_MARKER             (MAKE_MARKER ('I', 'N', 'A', 'M'))
99 #define IENG_MARKER             (MAKE_MARKER ('I', 'E', 'N', 'G'))
100 #define IGNR_MARKER             (MAKE_MARKER ('I', 'G', 'N', 'R'))
101 #define ICOP_MARKER             (MAKE_MARKER ('I', 'C', 'O', 'P'))
102 #define IPRD_MARKER             (MAKE_MARKER ('I', 'P', 'R', 'D'))
103 #define ISRC_MARKER             (MAKE_MARKER ('I', 'S', 'R', 'C'))
104 #define ISBJ_MARKER             (MAKE_MARKER ('I', 'S', 'B', 'J'))
105 #define ICMT_MARKER             (MAKE_MARKER ('I', 'C', 'M', 'T'))
106 #define IAUT_MARKER             (MAKE_MARKER ('I', 'A', 'U', 'T'))
107 #define ITRK_MARKER             (MAKE_MARKER ('I', 'T', 'R', 'K'))
108
109 /* Weird WAVPACK marker which can show up at the start of the DATA section. */
110 #define wvpk_MARKER (MAKE_MARKER ('w', 'v', 'p', 'k'))
111 #define OggS_MARKER (MAKE_MARKER ('O', 'g', 'g', 'S'))
112
113 #define WAV_PEAK_CHUNK_SIZE(ch)         (2 * sizeof (int) + ch * (sizeof (float) + sizeof (int)))
114 #define WAV_BEXT_MIN_CHUNK_SIZE         602
115 #define WAV_BEXT_MAX_CHUNK_SIZE         (10 * 1024)
116
117 #define WAV_CART_MIN_CHUNK_SIZE         2048
118 #define WAV_CART_MAX_CHUNK_SIZE         0xffffffff
119
120
121 enum
122 {       HAVE_RIFF       = 0x01,
123         HAVE_WAVE       = 0x02,
124         HAVE_fmt        = 0x04,
125         HAVE_fact       = 0x08,
126         HAVE_PEAK       = 0x10,
127         HAVE_data       = 0x20,
128         HAVE_other      = 0x80000000
129 } ;
130
131
132
133 /*  known WAVEFORMATEXTENSIBLE GUIDS  */
134 static const EXT_SUBFORMAT MSGUID_SUBTYPE_PCM =
135 {       0x00000001, 0x0000, 0x0010, {   0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
136 } ;
137
138 static const EXT_SUBFORMAT MSGUID_SUBTYPE_MS_ADPCM =
139 {       0x00000002, 0x0000, 0x0010, {   0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
140 } ;
141
142 static const EXT_SUBFORMAT MSGUID_SUBTYPE_IEEE_FLOAT =
143 {       0x00000003, 0x0000, 0x0010, {   0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
144 } ;
145
146 static const EXT_SUBFORMAT MSGUID_SUBTYPE_ALAW =
147 {       0x00000006, 0x0000, 0x0010, {   0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
148 } ;
149
150 static const EXT_SUBFORMAT MSGUID_SUBTYPE_MULAW =
151 {       0x00000007, 0x0000, 0x0010, {   0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
152 } ;
153
154 /*
155 ** the next two are from
156 ** http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html
157 */
158 static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM =
159 {       0x00000001, 0x0721, 0x11d3, {   0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 }
160 } ;
161
162 static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT =
163 {       0x00000003, 0x0721, 0x11d3, {   0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 }
164 } ;
165
166
167 #if 0
168 /* maybe interesting one day to read the following through sf_read_raw */
169 /* http://www.bath.ac.uk/~masrwd/pvocex/pvocex.html */
170 static const EXT_SUBFORMAT MSGUID_SUBTYPE_PVOCEX =
171 {       0x8312B9C2, 0x2E6E, 0x11d4, {   0xA8, 0x24, 0xDE, 0x5B, 0x96, 0xC3, 0xAB, 0x21 }
172 } ;
173 #endif
174
175 /*------------------------------------------------------------------------------
176 ** Private static functions.
177 */
178
179 static int      wav_read_header         (SF_PRIVATE *psf, int *blockalign, int *framesperblock) ;
180 static int      wav_write_header        (SF_PRIVATE *psf, int calc_length) ;
181
182 static int      wav_write_tailer (SF_PRIVATE *psf) ;
183 static void wav_write_strings (SF_PRIVATE *psf, int location) ;
184 static int      wav_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
185 static int      wav_close (SF_PRIVATE *psf) ;
186
187 static int      wav_subchunk_parse      (SF_PRIVATE *psf, int chunk, uint32_t length) ;
188 static int      exif_subchunk_parse     (SF_PRIVATE *psf, uint32_t length) ;
189 static int      wav_read_smpl_chunk (SF_PRIVATE *psf, uint32_t chunklen) ;
190 static int      wav_read_acid_chunk (SF_PRIVATE *psf, uint32_t chunklen) ;
191
192 static int wav_set_chunk (SF_PRIVATE *psf, const SF_CHUNK_INFO * chunk_info) ;
193 static SF_CHUNK_ITERATOR * wav_next_chunk_iterator (SF_PRIVATE *psf, SF_CHUNK_ITERATOR * iterator) ;
194 static int wav_get_chunk_size (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
195 static int wav_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ;
196
197 /*------------------------------------------------------------------------------
198 ** Public function.
199 */
200
201 int
202 wav_open        (SF_PRIVATE *psf)
203 {       WAV_PRIVATE * wpriv ;
204         int     format, subformat, error, blockalign = 0, framesperblock = 0 ;
205
206         if ((wpriv = calloc (1, sizeof (WAV_PRIVATE))) == NULL)
207                 return SFE_MALLOC_FAILED ;
208         psf->container_data = wpriv ;
209
210         wpriv->wavex_ambisonic = SF_AMBISONIC_NONE ;
211         psf->strings.flags = SF_STR_ALLOW_START | SF_STR_ALLOW_END ;
212
213         if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
214         {       if ((error = wav_read_header (psf, &blockalign, &framesperblock)))
215                         return error ;
216
217                 psf->next_chunk_iterator = wav_next_chunk_iterator ;
218                 psf->get_chunk_size = wav_get_chunk_size ;
219                 psf->get_chunk_data = wav_get_chunk_data ;
220                 } ;
221
222         subformat = SF_CODEC (psf->sf.format) ;
223
224         if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
225         {       if (psf->is_pipe)
226                         return SFE_NO_PIPE_WRITE ;
227
228                 wpriv->wavex_ambisonic = SF_AMBISONIC_NONE ;
229
230                 format = SF_CONTAINER (psf->sf.format) ;
231                 if (format != SF_FORMAT_WAV && format != SF_FORMAT_WAVEX)
232                         return  SFE_BAD_OPEN_FORMAT ;
233
234                 psf->blockwidth = psf->bytewidth * psf->sf.channels ;
235
236                 /* RIFF WAVs are little-endian, RIFX WAVs are big-endian, default to little */
237                 psf->endian = SF_ENDIAN (psf->sf.format) ;
238                 if (CPU_IS_BIG_ENDIAN && psf->endian == SF_ENDIAN_CPU)
239                         psf->endian = SF_ENDIAN_BIG ;
240                 else if (psf->endian != SF_ENDIAN_BIG)
241                         psf->endian = SF_ENDIAN_LITTLE ;
242
243                 if (psf->file.mode != SFM_RDWR || psf->filelength < 44)
244                 {       psf->filelength = 0 ;
245                         psf->datalength = 0 ;
246                         psf->dataoffset = 0 ;
247                         psf->sf.frames = 0 ;
248                         } ;
249
250                 if (subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM)
251                 {       blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ;
252                         framesperblock = -1 ; /* Corrected later. */
253                         } ;
254
255                 /* By default, add the peak chunk to floating point files. Default behaviour
256                 ** can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE).
257                 */
258                 if (psf->file.mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE))
259                 {       if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
260                                 return SFE_MALLOC_FAILED ;
261                         psf->peak_info->peak_loc = SF_PEAK_START ;
262                         } ;
263
264                 psf->write_header       = wav_write_header ;
265                 psf->set_chunk          = wav_set_chunk ;
266                 } ;
267
268         psf->container_close = wav_close ;
269         psf->command = wav_command ;
270
271         switch (subformat)
272         {       case SF_FORMAT_PCM_U8 :
273                 case SF_FORMAT_PCM_16 :
274                 case SF_FORMAT_PCM_24 :
275                 case SF_FORMAT_PCM_32 :
276                                         error = pcm_init (psf) ;
277                                         break ;
278
279                 case SF_FORMAT_ULAW :
280                                         error = ulaw_init (psf) ;
281                                         break ;
282
283                 case SF_FORMAT_ALAW :
284                                         error = alaw_init (psf) ;
285                                         break ;
286
287                 /* Lite remove start */
288                 case SF_FORMAT_FLOAT :
289                                         error = float32_init (psf) ;
290                                         break ;
291
292                 case SF_FORMAT_DOUBLE :
293                                         error = double64_init (psf) ;
294                                         break ;
295
296                 case SF_FORMAT_IMA_ADPCM :
297                                         error = wav_w64_ima_init (psf, blockalign, framesperblock) ;
298                                         break ;
299
300                 case SF_FORMAT_MS_ADPCM :
301                                         error = wav_w64_msadpcm_init (psf, blockalign, framesperblock) ;
302                                         break ;
303
304                 case SF_FORMAT_G721_32 :
305                                         error = g72x_init (psf) ;
306                                         break ;
307                 /* Lite remove end */
308
309                 case SF_FORMAT_GSM610 :
310                                         error = gsm610_init (psf) ;
311                                         break ;
312
313                 default :       return SFE_UNIMPLEMENTED ;
314                 } ;
315
316         if (psf->file.mode == SFM_WRITE || (psf->file.mode == SFM_RDWR && psf->filelength == 0))
317                 return psf->write_header (psf, SF_FALSE) ;
318
319         return error ;
320 } /* wav_open */
321
322 /*=========================================================================
323 ** Private functions.
324 */
325
326 static int
327 wav_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
328 {       WAV_PRIVATE     *wpriv ;
329         WAV_FMT         *wav_fmt ;
330         FACT_CHUNK      fact_chunk ;
331         uint32_t        marker, chunk_size = 0, RIFFsize = 0, done = 0, uk ;
332         int                     parsestage = 0, error, format = 0 ;
333         char            buffer [256] ;
334
335         if (psf->is_pipe == 0 && psf->filelength > SF_PLATFORM_S64 (0xffffffff))
336                 psf_log_printf (psf, "Warning : filelength > 0xffffffff. This is bad!!!!\n") ;
337
338         if ((wpriv = psf->container_data) == NULL)
339                 return SFE_INTERNAL ;
340         wav_fmt = &wpriv->wav_fmt ;
341
342         /* Set position to start of file to begin reading header. */
343         psf_binheader_readf (psf, "pmj", 0, &marker, -4) ;
344         psf->headindex = 0 ;
345
346         /* RIFX signifies big-endian format for all header and data  to prevent
347         ** lots of code copying here, we'll set the psf->rwf_endian flag once here,
348         ** and never specify endian-ness for all other header ops/
349         */
350         psf->rwf_endian = (marker == RIFF_MARKER) ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ;
351
352         while (! done)
353         {       size_t jump = chunk_size & 1 ;
354
355                 marker = chunk_size = 0 ;
356                 psf_binheader_readf (psf, "jm4", jump, &marker, &chunk_size) ;
357                 if (marker == 0)
358                 {       sf_count_t pos = psf_ftell (psf) ;
359                         psf_log_printf (psf, "Have 0 marker at position %D (0x%x).\n", pos, pos) ;
360                         break ;
361                         } ;
362
363                 psf_store_read_chunk_u32 (&psf->rchunks, marker, psf_ftell (psf), chunk_size) ;
364
365                 switch (marker)
366                 {       case RIFF_MARKER :
367                         case RIFX_MARKER :
368                                         if (parsestage)
369                                                 return SFE_WAV_NO_RIFF ;
370
371                                         parsestage |= HAVE_RIFF ;
372
373                                         RIFFsize = chunk_size ;
374
375                                         if (psf->fileoffset > 0 && psf->filelength > RIFFsize + 8)
376                                         {       /* Set file length. */
377                                                 psf->filelength = RIFFsize + 8 ;
378                                                 if (marker == RIFF_MARKER)
379                                                         psf_log_printf (psf, "RIFF : %u\n", RIFFsize) ;
380                                                 else
381                                                         psf_log_printf (psf, "RIFX : %u\n", RIFFsize) ;
382                                                 }
383                                         else if (psf->filelength < RIFFsize + 2 * SIGNED_SIZEOF (marker))
384                                         {       if (marker == RIFF_MARKER)
385                                                         psf_log_printf (psf, "RIFF : %u (should be %D)\n", RIFFsize, psf->filelength - 2 * SIGNED_SIZEOF (marker)) ;
386                                                 else
387                                                         psf_log_printf (psf, "RIFX : %u (should be %D)\n", RIFFsize, psf->filelength - 2 * SIGNED_SIZEOF (marker)) ;
388
389                                                 RIFFsize = psf->filelength - 2 * SIGNED_SIZEOF (RIFFsize) ;
390                                                 }
391                                         else
392                                         {       if (marker == RIFF_MARKER)
393                                                         psf_log_printf (psf, "RIFF : %u\n", RIFFsize) ;
394                                                 else
395                                                         psf_log_printf (psf, "RIFX : %u\n", RIFFsize) ;
396                                         } ;
397
398                                         psf_binheader_readf (psf, "m", &marker) ;
399                                         if (marker != WAVE_MARKER)
400                                                 return SFE_WAV_NO_WAVE ;
401                                         parsestage |= HAVE_WAVE ;
402                                         psf_log_printf (psf, "WAVE\n") ;
403                                         chunk_size = 0 ;
404                                         break ;
405
406                         case fmt_MARKER :
407                                         if ((parsestage & (HAVE_RIFF | HAVE_WAVE)) != (HAVE_RIFF | HAVE_WAVE))
408                                                 return SFE_WAV_NO_FMT ;
409
410                                         /* If this file has a SECOND fmt chunk, I don't want to know about it. */
411                                         if (parsestage & HAVE_fmt)
412                                                 break ;
413
414                                         parsestage |= HAVE_fmt ;
415
416                                         psf_log_printf (psf, "fmt  : %d\n", chunk_size) ;
417
418                                         if ((error = wav_w64_read_fmt_chunk (psf, chunk_size)))
419                                                 return error ;
420
421                                         format = wav_fmt->format ;
422                                         break ;
423
424                         case data_MARKER :
425                                         if ((parsestage & (HAVE_RIFF | HAVE_WAVE | HAVE_fmt)) != (HAVE_RIFF | HAVE_WAVE | HAVE_fmt))
426                                                 return SFE_WAV_NO_DATA ;
427
428                                         if (psf->file.mode == SFM_RDWR && (parsestage & HAVE_other) != 0)
429                                                 return SFE_RDWR_BAD_HEADER ;
430
431                                         parsestage |= HAVE_data ;
432
433                                         psf->datalength = chunk_size ;
434                                         if (psf->datalength & 1)
435                                                 psf_log_printf (psf, "*** 'data' chunk should be an even number of bytes in length.\n") ;
436
437                                         psf->dataoffset = psf_ftell (psf) ;
438
439                                         if (psf->dataoffset > 0)
440                                         {       if (chunk_size == 0 && RIFFsize == 8 && psf->filelength > 44)
441                                                 {       psf_log_printf (psf, "*** Looks like a WAV file which wasn't closed properly. Fixing it.\n") ;
442                                                         psf->datalength = psf->filelength - psf->dataoffset ;
443                                                         } ;
444
445                                                 if (psf->datalength > psf->filelength - psf->dataoffset)
446                                                 {       psf_log_printf (psf, "data : %D (should be %D)\n", psf->datalength, psf->filelength - psf->dataoffset) ;
447                                                         psf->datalength = psf->filelength - psf->dataoffset ;
448                                                         }
449                                                 else
450                                                         psf_log_printf (psf, "data : %D\n", psf->datalength) ;
451
452                                                 /* Only set dataend if there really is data at the end. */
453                                                 if (psf->datalength + psf->dataoffset < psf->filelength)
454                                                         psf->dataend = psf->datalength + psf->dataoffset ;
455
456                                                 psf->datalength += chunk_size & 1 ;
457                                                 chunk_size = 0 ;
458                                                 } ;
459
460                                         if (! psf->sf.seekable || psf->dataoffset < 0)
461                                                 break ;
462
463                                         /* Seek past data and continue reading header. */
464                                         psf_fseek (psf, psf->datalength, SEEK_CUR) ;
465
466                                         if (psf_ftell (psf) != psf->datalength + psf->dataoffset)
467                                                 psf_log_printf (psf, "*** psf_fseek past end error ***\n") ;
468                                         break ;
469
470                         case fact_MARKER :
471                                         if ((parsestage & (HAVE_RIFF | HAVE_WAVE)) != (HAVE_RIFF | HAVE_WAVE))
472                                                 return SFE_WAV_BAD_FACT ;
473
474                                         parsestage |= HAVE_fact ;
475
476                                         if ((parsestage & HAVE_fmt) != HAVE_fmt)
477                                                 psf_log_printf (psf, "*** Should have 'fmt ' chunk before 'fact'\n") ;
478
479                                         psf_binheader_readf (psf, "4", & (fact_chunk.frames)) ;
480
481                                         if (chunk_size > SIGNED_SIZEOF (fact_chunk))
482                                                 psf_binheader_readf (psf, "j", (int) (chunk_size - SIGNED_SIZEOF (fact_chunk))) ;
483
484                                         if (chunk_size)
485                                                 psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ;
486                                         else
487                                                 psf_log_printf (psf, "%M : %u (should not be zero)\n", marker, chunk_size) ;
488
489                                         psf_log_printf (psf, "  frames  : %d\n", fact_chunk.frames) ;
490                                         break ;
491
492                         case PEAK_MARKER :
493                                         if ((parsestage & (HAVE_RIFF | HAVE_WAVE | HAVE_fmt)) != (HAVE_RIFF | HAVE_WAVE | HAVE_fmt))
494                                                 return SFE_WAV_PEAK_B4_FMT ;
495
496                                         parsestage |= HAVE_PEAK ;
497
498                                         psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ;
499                                         if (chunk_size != WAV_PEAK_CHUNK_SIZE (psf->sf.channels))
500                                         {       psf_binheader_readf (psf, "j", chunk_size) ;
501                                                 psf_log_printf (psf, "*** File PEAK chunk size doesn't fit with number of channels (%d).\n", psf->sf.channels) ;
502                                                 return SFE_WAV_BAD_PEAK ;
503                                                 } ;
504
505                                         if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
506                                                 return SFE_MALLOC_FAILED ;
507
508                                         /* read in rest of PEAK chunk. */
509                                         psf_binheader_readf (psf, "44", & (psf->peak_info->version), & (psf->peak_info->timestamp)) ;
510
511                                         if (psf->peak_info->version != 1)
512                                                 psf_log_printf (psf, "  version    : %d *** (should be version 1)\n", psf->peak_info->version) ;
513                                         else
514                                                 psf_log_printf (psf, "  version    : %d\n", psf->peak_info->version) ;
515
516                                         psf_log_printf (psf, "  time stamp : %d\n", psf->peak_info->timestamp) ;
517                                         psf_log_printf (psf, "    Ch   Position       Value\n") ;
518
519                                         for (uk = 0 ; uk < (uint32_t) psf->sf.channels ; uk++)
520                                         {       float value ;
521                                                 uint32_t position ;
522
523                                                 psf_binheader_readf (psf, "f4", &value, &position) ;
524                                                 psf->peak_info->peaks [uk].value = value ;
525                                                 psf->peak_info->peaks [uk].position = position ;
526
527                                                 snprintf (buffer, sizeof (buffer), "    %2d   %-12" PRId64 "   %g\n",
528                                                                 uk, psf->peak_info->peaks [uk].position, psf->peak_info->peaks [uk].value) ;
529                                                 buffer [sizeof (buffer) - 1] = 0 ;
530                                                 psf_log_printf (psf, "%s", buffer) ;
531                                                 } ;
532
533                                         psf->peak_info->peak_loc = ((parsestage & HAVE_data) == 0) ? SF_PEAK_START : SF_PEAK_END ;
534                                         break ;
535
536                         case cue_MARKER :
537                                         parsestage |= HAVE_other ;
538
539                                         {       uint32_t thisread, bytesread, cue_count ;
540                                                 int id, position, chunk_id, chunk_start, block_start, offset ;
541
542                                                 bytesread = psf_binheader_readf (psf, "4", &cue_count) ;
543                                                 psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ;
544
545                                                 if (cue_count > 10)
546                                                 {       psf_log_printf (psf, "  Count : %u (skipping)\n", cue_count) ;
547                                                         psf_binheader_readf (psf, "j", (cue_count > 20 ? 20 : cue_count) * 24) ;
548                                                         break ;
549                                                         } ;
550
551                                                 psf_log_printf (psf, "  Count : %d\n", cue_count) ;
552
553                                                 while (cue_count)
554                                                 {
555                                                         if ((thisread = psf_binheader_readf (psf, "444444", &id, &position, &chunk_id, &chunk_start, &block_start, &offset)) == 0)
556                                                                 break ;
557                                                         bytesread += thisread ;
558
559                                                         psf_log_printf (psf,    "   Cue ID : %2d"
560                                                                                                         "  Pos : %5u  Chunk : %M"
561                                                                                                         "  Chk Start : %d  Blk Start : %d"
562                                                                                                         "  Offset : %5d\n",
563                                                                         id, position, chunk_id, chunk_start, block_start, offset) ;
564                                                         cue_count -- ;
565                                                         } ;
566
567                                                 if (bytesread != chunk_size)
568                                                 {       psf_log_printf (psf, "**** Chunk size weirdness (%d != %d)\n", chunk_size, bytesread) ;
569                                                         psf_binheader_readf (psf, "j", chunk_size - bytesread) ;
570                                                         } ;
571                                                 } ;
572                                         break ;
573
574                         case smpl_MARKER :
575                                         parsestage |= HAVE_other ;
576
577                                         psf_log_printf (psf, "smpl : %u\n", chunk_size) ;
578
579                                         if ((error = wav_read_smpl_chunk (psf, chunk_size)))
580                                                 return error ;
581                                         break ;
582
583                         case acid_MARKER :
584                                         parsestage |= HAVE_other ;
585
586                                         psf_log_printf (psf, "acid : %u\n", chunk_size) ;
587
588                                         if ((error = wav_read_acid_chunk (psf, chunk_size)))
589                                                 return error ;
590                                         break ;
591
592                         case INFO_MARKER :
593                         case LIST_MARKER :
594                                         parsestage |= HAVE_other ;
595
596                                         if ((error = wav_subchunk_parse (psf, marker, chunk_size)) != 0)
597                                                 return error ;
598                                         break ;
599
600                         case bext_MARKER :
601                                         /*
602                                         The 'bext' chunk can actually be updated, so don't need to set this.
603                                         parsestage |= HAVE_other ;
604                                         */
605                                         if ((error = wav_read_bext_chunk (psf, chunk_size)))
606                                                 return error ;
607                                         break ;
608
609                         case PAD_MARKER :
610                                         /*
611                                         We can eat into a 'PAD ' chunk if we need to.
612                                         parsestage |= HAVE_other ;
613                                         */
614                                         psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ;
615                                         psf_binheader_readf (psf, "j", chunk_size) ;
616                                         break ;
617
618                         case cart_MARKER:
619                                         if ((error = wav_read_cart_chunk (psf, chunk_size)))
620                                                 return error ;
621                                         break ;
622
623                         case iXML_MARKER : /* See http://en.wikipedia.org/wiki/IXML */
624                         case strc_MARKER : /* Multiple of 32 bytes. */
625                         case afsp_MARKER :
626                         case clm_MARKER :
627                         case elmo_MARKER :
628                         case levl_MARKER :
629                         case plst_MARKER :
630                         case minf_MARKER :
631                         case elm1_MARKER :
632                         case regn_MARKER :
633                         case ovwf_MARKER :
634                         case inst_MARKER :
635                         case AFAn_MARKER :
636                         case umid_MARKER :
637                         case SyLp_MARKER :
638                         case Cr8r_MARKER :
639                         case JUNK_MARKER :
640                         case PMX_MARKER :
641                         case DISP_MARKER :
642                         case MEXT_MARKER :
643                         case FLLR_MARKER :
644                                         psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ;
645                                         psf_binheader_readf (psf, "j", chunk_size) ;
646                                         break ;
647
648                         default :
649                                         if (chunk_size >= 0xffff0000)
650                                         {       done = SF_TRUE ;
651                                                 psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D with length %u. Exiting parser.\n", marker, psf_ftell (psf) - 8, chunk_size) ;
652                                                 break ;
653                                                 } ;
654
655                                         if (psf_isprint ((marker >> 24) & 0xFF) && psf_isprint ((marker >> 16) & 0xFF)
656                                                 && psf_isprint ((marker >> 8) & 0xFF) && psf_isprint (marker & 0xFF))
657                                         {       psf_log_printf (psf, "*** %M : %u (unknown marker)\n", marker, chunk_size) ;
658                                                 psf_binheader_readf (psf, "j", chunk_size) ;
659                                                 break ;
660                                                 } ;
661                                         if (psf_ftell (psf) & 0x03)
662                                         {       psf_log_printf (psf, "  Unknown chunk marker at position %D. Resynching.\n", psf_ftell (psf) - 8) ;
663                                                 psf_binheader_readf (psf, "j", -3) ;
664                                                 /* File is too messed up so we prevent editing in RDWR mode here. */
665                                                 parsestage |= HAVE_other ;
666                                                 break ;
667                                                 } ;
668                                         psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D. Exiting parser.\n", marker, psf_ftell (psf) - 8) ;
669                                         done = SF_TRUE ;
670                                         break ;
671                         } ;     /* switch (marker) */
672
673                 if (chunk_size >= psf->filelength)
674                 {       psf_log_printf (psf, "*** Chunk size %u > file length %D. Exiting parser.\n", chunk_size, psf->filelength) ;
675                         break ;
676                         } ;
677
678                 if (! psf->sf.seekable && (parsestage & HAVE_data))
679                         break ;
680
681                 if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (chunk_size))
682                 {       psf_log_printf (psf, "End\n") ;
683                         break ;
684                         } ;
685                 } ; /* while (1) */
686
687         if (psf->dataoffset <= 0)
688                 return SFE_WAV_NO_DATA ;
689
690         if (psf->sf.channels < 1)
691                 return SFE_CHANNEL_COUNT_ZERO ;
692
693         if (psf->sf.channels >= SF_MAX_CHANNELS)
694                 return SFE_CHANNEL_COUNT ;
695
696         if (format != WAVE_FORMAT_PCM && (parsestage & HAVE_fact) == 0)
697                 psf_log_printf (psf, "**** All non-PCM format files should have a 'fact' chunk.\n") ;
698
699         /* WAVs can be little or big endian */
700         psf->endian = psf->rwf_endian ;
701
702         psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
703
704         if (psf->is_pipe == 0)
705         {       /*
706                 ** Check for 'wvpk' at the start of the DATA section. Not able to
707                 ** handle this.
708                 */
709                 psf_binheader_readf (psf, "4", &marker) ;
710                 if (marker == wvpk_MARKER || marker == OggS_MARKER)
711                         return SFE_WAV_WVPK_DATA ;
712                 } ;
713
714         /* Seek to start of DATA section. */
715         psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
716
717         if (psf->blockwidth)
718         {       if (psf->filelength - psf->dataoffset < psf->datalength)
719                         psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
720                 else
721                         psf->sf.frames = psf->datalength / psf->blockwidth ;
722                 } ;
723
724         switch (format)
725         {       case WAVE_FORMAT_EXTENSIBLE :
726                         if (psf->sf.format == (SF_FORMAT_WAVEX | SF_FORMAT_MS_ADPCM))
727                         {       *blockalign = wav_fmt->msadpcm.blockalign ;
728                                 *framesperblock = wav_fmt->msadpcm.samplesperblock ;
729                                 } ;
730                         break ;
731
732                 case WAVE_FORMAT_PCM :
733                                         psf->sf.format = SF_FORMAT_WAV | u_bitwidth_to_subformat (psf->bytewidth * 8) ;
734                                         break ;
735
736                 case WAVE_FORMAT_MULAW :
737                 case IBM_FORMAT_MULAW :
738                                         psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_ULAW) ;
739                                         break ;
740
741                 case WAVE_FORMAT_ALAW :
742                 case IBM_FORMAT_ALAW :
743                                         psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_ALAW) ;
744                                         break ;
745
746                 case WAVE_FORMAT_MS_ADPCM :
747                                         psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM) ;
748                                         *blockalign = wav_fmt->msadpcm.blockalign ;
749                                         *framesperblock = wav_fmt->msadpcm.samplesperblock ;
750                                         break ;
751
752                 case WAVE_FORMAT_IMA_ADPCM :
753                                         psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM) ;
754                                         *blockalign = wav_fmt->ima.blockalign ;
755                                         *framesperblock = wav_fmt->ima.samplesperblock ;
756                                         break ;
757
758                 case WAVE_FORMAT_GSM610 :
759                                         psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_GSM610) ;
760                                         break ;
761
762                 case WAVE_FORMAT_IEEE_FLOAT :
763                                         psf->sf.format = SF_FORMAT_WAV ;
764                                         psf->sf.format |= (psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT ;
765                                         break ;
766
767                 case WAVE_FORMAT_G721_ADPCM :
768                                         psf->sf.format = SF_FORMAT_WAV | SF_FORMAT_G721_32 ;
769                                         break ;
770
771                 default : return SFE_UNIMPLEMENTED ;
772                 } ;
773
774         if (wpriv->fmt_is_broken)
775                 wav_w64_analyze (psf) ;
776
777         /* Only set the format endian-ness if its non-standard big-endian. */
778         if (psf->endian == SF_ENDIAN_BIG)
779                 psf->sf.format |= SF_ENDIAN_BIG ;
780
781         return 0 ;
782 } /* wav_read_header */
783
784 static int
785 wav_write_fmt_chunk (SF_PRIVATE *psf)
786 {       int subformat, fmt_size, add_fact_chunk = 0 ;
787
788         subformat = SF_CODEC (psf->sf.format) ;
789
790         switch (subformat)
791         {       case SF_FORMAT_PCM_U8 :
792                 case SF_FORMAT_PCM_16 :
793                 case SF_FORMAT_PCM_24 :
794                 case SF_FORMAT_PCM_32 :
795                                         fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ;
796
797                                         /* fmt : format, channels, samplerate */
798                                         psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_PCM, psf->sf.channels, psf->sf.samplerate) ;
799                                         /*  fmt : bytespersec */
800                                         psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
801                                         /*  fmt : blockalign, bitwidth */
802                                         psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
803                                         break ;
804
805                 case SF_FORMAT_FLOAT :
806                 case SF_FORMAT_DOUBLE :
807                                         fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ;
808
809                                         /* fmt : format, channels, samplerate */
810                                         psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_IEEE_FLOAT, psf->sf.channels, psf->sf.samplerate) ;
811                                         /*  fmt : bytespersec */
812                                         psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
813                                         /*  fmt : blockalign, bitwidth */
814                                         psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
815
816                                         add_fact_chunk = SF_TRUE ;
817                                         break ;
818
819                 case SF_FORMAT_ULAW :
820                                         fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 ;
821
822                                         /* fmt : format, channels, samplerate */
823                                         psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_MULAW, psf->sf.channels, psf->sf.samplerate) ;
824                                         /*  fmt : bytespersec */
825                                         psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
826                                         /*  fmt : blockalign, bitwidth, extrabytes */
827                                         psf_binheader_writef (psf, "222", psf->bytewidth * psf->sf.channels, 8, 0) ;
828
829                                         add_fact_chunk = SF_TRUE ;
830                                         break ;
831
832                 case SF_FORMAT_ALAW :
833                                         fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 ;
834
835                                         /* fmt : format, channels, samplerate */
836                                         psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_ALAW, psf->sf.channels, psf->sf.samplerate) ;
837                                         /*  fmt : bytespersec */
838                                         psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
839                                         /*  fmt : blockalign, bitwidth, extrabytes */
840                                         psf_binheader_writef (psf, "222", psf->bytewidth * psf->sf.channels, 8, 0) ;
841
842                                         add_fact_chunk = SF_TRUE ;
843                                         break ;
844
845                 /* Lite remove start */
846                 case SF_FORMAT_IMA_ADPCM :
847                                         {       int blockalign, framesperblock, bytespersec ;
848
849                                                 blockalign              = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ;
850                                                 framesperblock  = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ;
851                                                 bytespersec             = (psf->sf.samplerate * blockalign) / framesperblock ;
852
853                                                 /* fmt chunk. */
854                                                 fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
855
856                                                 /* fmt : size, WAV format type, channels, samplerate, bytespersec */
857                                                 psf_binheader_writef (psf, "42244", fmt_size, WAVE_FORMAT_IMA_ADPCM,
858                                                                         psf->sf.channels, psf->sf.samplerate, bytespersec) ;
859
860                                                 /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
861                                                 psf_binheader_writef (psf, "2222", blockalign, 4, 2, framesperblock) ;
862                                                 } ;
863
864                                         add_fact_chunk = SF_TRUE ;
865                                         break ;
866
867                 case SF_FORMAT_MS_ADPCM :
868                                         {       int     blockalign, framesperblock, bytespersec, extrabytes ;
869
870                                                 blockalign              = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ;
871                                                 framesperblock  = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ;
872                                                 bytespersec             = (psf->sf.samplerate * blockalign) / framesperblock ;
873
874                                                 /* fmt chunk. */
875                                                 extrabytes      = 2 + 2 + MSADPCM_ADAPT_COEFF_COUNT * (2 + 2) ;
876                                                 fmt_size        = 2 + 2 + 4 + 4 + 2 + 2 + 2 + extrabytes ;
877
878                                                 /* fmt : size, WAV format type, channels. */
879                                                 psf_binheader_writef (psf, "422", fmt_size, WAVE_FORMAT_MS_ADPCM, psf->sf.channels) ;
880
881                                                 /* fmt : samplerate, bytespersec. */
882                                                 psf_binheader_writef (psf, "44", psf->sf.samplerate, bytespersec) ;
883
884                                                 /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
885                                                 psf_binheader_writef (psf, "22222", blockalign, 4, extrabytes, framesperblock, 7) ;
886
887                                                 msadpcm_write_adapt_coeffs (psf) ;
888                                                 } ;
889
890                                         add_fact_chunk = SF_TRUE ;
891                                         break ;
892
893
894                 case SF_FORMAT_G721_32 :
895                                         /* fmt chunk. */
896                                         fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
897
898                                         /* fmt : size, WAV format type, channels, samplerate, bytespersec */
899                                         psf_binheader_writef (psf, "42244", fmt_size, WAVE_FORMAT_G721_ADPCM,
900                                                                 psf->sf.channels, psf->sf.samplerate, psf->sf.samplerate * psf->sf.channels / 2) ;
901
902                                         /* fmt : blockalign, bitwidth, extrabytes, auxblocksize. */
903                                         psf_binheader_writef (psf, "2222", 64, 4, 2, 0) ;
904
905                                         add_fact_chunk = SF_TRUE ;
906                                         break ;
907
908                 /* Lite remove end */
909
910                 case SF_FORMAT_GSM610 :
911                                         {       int     blockalign, framesperblock, bytespersec ;
912
913                                                 blockalign              = WAV_W64_GSM610_BLOCKSIZE ;
914                                                 framesperblock  = WAV_W64_GSM610_SAMPLES ;
915                                                 bytespersec             = (psf->sf.samplerate * blockalign) / framesperblock ;
916
917                                                 /* fmt chunk. */
918                                                 fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
919
920                                                 /* fmt : size, WAV format type, channels. */
921                                                 psf_binheader_writef (psf, "422", fmt_size, WAVE_FORMAT_GSM610, psf->sf.channels) ;
922
923                                                 /* fmt : samplerate, bytespersec. */
924                                                 psf_binheader_writef (psf, "44", psf->sf.samplerate, bytespersec) ;
925
926                                                 /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
927                                                 psf_binheader_writef (psf, "2222", blockalign, 0, 2, framesperblock) ;
928                                                 } ;
929
930                                         add_fact_chunk = SF_TRUE ;
931                                         break ;
932
933                 default :       return SFE_UNIMPLEMENTED ;
934                 } ;
935
936         if (add_fact_chunk)
937                 psf_binheader_writef (psf, "tm48", fact_MARKER, 4, psf->sf.frames) ;
938
939         return 0 ;
940 } /* wav_write_fmt_chunk */
941
942 static int
943 wavex_write_fmt_chunk (SF_PRIVATE *psf)
944 {       WAV_PRIVATE     *wpriv ;
945         int subformat, fmt_size ;
946
947         if ((wpriv = psf->container_data) == NULL)
948                 return SFE_INTERNAL ;
949
950         subformat = SF_CODEC (psf->sf.format) ;
951
952         /* initial section (same for all, it appears) */
953         switch (subformat)
954         {       case SF_FORMAT_PCM_U8 :
955                 case SF_FORMAT_PCM_16 :
956                 case SF_FORMAT_PCM_24 :
957                 case SF_FORMAT_PCM_32 :
958                 case SF_FORMAT_FLOAT :
959                 case SF_FORMAT_DOUBLE :
960                 case SF_FORMAT_ULAW :
961                 case SF_FORMAT_ALAW :
962                         fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 + 4 + 4 + 2 + 2 + 8 ;
963
964                         /* fmt : format, channels, samplerate */
965                         psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_EXTENSIBLE, psf->sf.channels, psf->sf.samplerate) ;
966                         /*  fmt : bytespersec */
967                         psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
968                         /*  fmt : blockalign, bitwidth */
969                         psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
970
971                         /* cbSize 22 is sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX) */
972                         psf_binheader_writef (psf, "2", 22) ;
973
974                         /* wValidBitsPerSample, for our use same as bitwidth as we use it fully */
975                         psf_binheader_writef (psf, "2", psf->bytewidth * 8) ;
976
977                         /* For an Ambisonic file set the channel mask to zero.
978                         ** Otherwise use a default based on the channel count.
979                         */
980                         if (wpriv->wavex_ambisonic != SF_AMBISONIC_NONE)
981                                 psf_binheader_writef (psf, "4", 0) ;
982                         else if (wpriv->wavex_channelmask != 0)
983                                 psf_binheader_writef (psf, "4", wpriv->wavex_channelmask) ;
984                         else
985                         {       /*
986                                 ** Ok some liberty is taken here to use the most commonly used channel masks
987                                 ** instead of "no mapping". If you really want to use "no mapping" for 8 channels and less
988                                 ** please don't use wavex. (otherwise we'll have to create a new SF_COMMAND)
989                                 */
990                                 switch (psf->sf.channels)
991                                 {       case 1 :        /* center channel mono */
992                                                 psf_binheader_writef (psf, "4", 0x4) ;
993                                                 break ;
994
995                                         case 2 :        /* front left and right */
996                                                 psf_binheader_writef (psf, "4", 0x1 | 0x2) ;
997                                                 break ;
998
999                                         case 4 :        /* Quad */
1000                                                 psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x10 | 0x20) ;
1001                                                 break ;
1002
1003                                         case 6 :        /* 5.1 */
1004                                                 psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20) ;
1005                                                 break ;
1006
1007                                         case 8 :        /* 7.1 */
1008                                                 psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80) ;
1009                                                 break ;
1010
1011                                         default :       /* 0 when in doubt , use direct out, ie NO mapping*/
1012                                                 psf_binheader_writef (psf, "4", 0x0) ;
1013                                                 break ;
1014                                         } ;
1015                                 } ;
1016                         break ;
1017
1018                 case SF_FORMAT_MS_ADPCM : /* Todo, GUID exists might have different header as per wav_write_header */
1019                 default :
1020                         return SFE_UNIMPLEMENTED ;
1021                 } ;
1022
1023         /* GUID section, different for each */
1024
1025         switch (subformat)
1026         {       case SF_FORMAT_PCM_U8 :
1027                 case SF_FORMAT_PCM_16 :
1028                 case SF_FORMAT_PCM_24 :
1029                 case SF_FORMAT_PCM_32 :
1030                         wavex_write_guid (psf, wpriv->wavex_ambisonic == SF_AMBISONIC_NONE ?
1031                                                 &MSGUID_SUBTYPE_PCM : &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM) ;
1032                         break ;
1033
1034                 case SF_FORMAT_FLOAT :
1035                 case SF_FORMAT_DOUBLE :
1036                         wavex_write_guid (psf, wpriv->wavex_ambisonic == SF_AMBISONIC_NONE ?
1037                                                 &MSGUID_SUBTYPE_IEEE_FLOAT : &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT) ;
1038                         break ;
1039
1040                 case SF_FORMAT_ULAW :
1041                         wavex_write_guid (psf, &MSGUID_SUBTYPE_MULAW) ;
1042                         break ;
1043
1044                 case SF_FORMAT_ALAW :
1045                         wavex_write_guid (psf, &MSGUID_SUBTYPE_ALAW) ;
1046                         break ;
1047
1048 #if 0
1049                 /* This is dead code due to return in previous switch statement. */
1050                 case SF_FORMAT_MS_ADPCM : /* todo, GUID exists */
1051                         wavex_write_guid (psf, &MSGUID_SUBTYPE_MS_ADPCM) ;
1052                         break ;
1053                         return SFE_UNIMPLEMENTED ;
1054 #endif
1055
1056                 default : return SFE_UNIMPLEMENTED ;
1057                 } ;
1058
1059         psf_binheader_writef (psf, "tm48", fact_MARKER, 4, psf->sf.frames) ;
1060
1061         return 0 ;
1062 } /* wavex_write_fmt_chunk */
1063
1064
1065 static int
1066 wav_write_header (SF_PRIVATE *psf, int calc_length)
1067 {       sf_count_t      current ;
1068         uint32_t        uk ;
1069         int             k, error, has_data = SF_FALSE ;
1070
1071         current = psf_ftell (psf) ;
1072
1073         if (current > psf->dataoffset)
1074                 has_data = SF_TRUE ;
1075
1076         if (calc_length)
1077         {       psf->filelength = psf_get_filelen (psf) ;
1078
1079                 psf->datalength = psf->filelength - psf->dataoffset ;
1080
1081                 if (psf->dataend)
1082                         psf->datalength -= psf->filelength - psf->dataend ;
1083                 else if (psf->bytewidth > 0 && psf->sf.seekable == SF_TRUE)
1084                         psf->datalength = psf->sf.frames * psf->bytewidth * psf->sf.channels ;
1085                 } ;
1086
1087         /* Reset the current header length to zero. */
1088         psf->header [0] = 0 ;
1089         psf->headindex = 0 ;
1090         psf_fseek (psf, 0, SEEK_SET) ;
1091
1092         /*
1093         ** RIFX signifies big-endian format for all header and data.
1094         ** To prevent lots of code copying here, we'll set the psf->rwf_endian flag
1095         ** once here, and never specify endian-ness for all other header operations.
1096         */
1097
1098         /* RIFF/RIFX marker, length, WAVE and 'fmt ' markers. */
1099
1100         if (psf->endian == SF_ENDIAN_LITTLE)
1101                 psf_binheader_writef (psf, "etm8", RIFF_MARKER, (psf->filelength < 8) ? 8 : psf->filelength - 8) ;
1102         else
1103                 psf_binheader_writef (psf, "Etm8", RIFX_MARKER, (psf->filelength < 8) ? 8 : psf->filelength - 8) ;
1104
1105         /* WAVE and 'fmt ' markers. */
1106         psf_binheader_writef (psf, "mm", WAVE_MARKER, fmt_MARKER) ;
1107
1108         /* Write the 'fmt ' chunk. */
1109         switch (SF_CONTAINER (psf->sf.format))
1110         {       case SF_FORMAT_WAV :
1111                                 if ((error = wav_write_fmt_chunk (psf)) != 0)
1112                                         return error ;
1113                                 break ;
1114
1115                 case SF_FORMAT_WAVEX :
1116                                 if ((error = wavex_write_fmt_chunk (psf)) != 0)
1117                                         return error ;
1118                                 break ;
1119
1120                 default :
1121                                 return SFE_UNIMPLEMENTED ;
1122                 } ;
1123
1124         /* The LIST/INFO chunk. */
1125         if (psf->strings.flags & SF_STR_LOCATE_START)
1126                 wav_write_strings (psf, SF_STR_LOCATE_START) ;
1127
1128         if (psf->peak_info != NULL && psf->peak_info->peak_loc == SF_PEAK_START)
1129         {       psf_binheader_writef (psf, "m4", PEAK_MARKER, WAV_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
1130                 psf_binheader_writef (psf, "44", 1, time (NULL)) ;
1131                 for (k = 0 ; k < psf->sf.channels ; k++)
1132                         psf_binheader_writef (psf, "ft8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
1133                 } ;
1134
1135         if (psf->broadcast_16k != NULL)
1136                 wav_write_bext_chunk (psf) ;
1137
1138         if (psf->cart_16k != NULL)
1139                 wav_write_cart_chunk (psf) ;
1140
1141         if (psf->instrument != NULL)
1142         {       int             tmp ;
1143                 double  dtune = (double) (0x40000000) / 25.0 ;
1144
1145                 psf_binheader_writef (psf, "m4", smpl_MARKER, 9 * 4 + psf->instrument->loop_count * 6 * 4) ;
1146                 psf_binheader_writef (psf, "44", 0, 0) ; /* Manufacturer zero is everyone */
1147                 tmp = (int) (1.0e9 / psf->sf.samplerate) ; /* Sample period in nano seconds */
1148                 psf_binheader_writef (psf, "44", tmp, psf->instrument->basenote) ;
1149                 tmp = (uint32_t) (psf->instrument->detune * dtune + 0.5) ;
1150                 psf_binheader_writef (psf, "4", tmp) ;
1151                 psf_binheader_writef (psf, "44", 0, 0) ; /* SMTPE format */
1152                 psf_binheader_writef (psf, "44", psf->instrument->loop_count, 0) ;
1153
1154                 for (tmp = 0 ; tmp < psf->instrument->loop_count ; tmp++)
1155                 {       int type ;
1156
1157                         type = psf->instrument->loops [tmp].mode ;
1158                         type = (type == SF_LOOP_FORWARD ? 0 : type == SF_LOOP_BACKWARD ? 2 : type == SF_LOOP_ALTERNATING ? 1 : 32) ;
1159
1160                         psf_binheader_writef (psf, "44", tmp, type) ;
1161                         psf_binheader_writef (psf, "44", psf->instrument->loops [tmp].start, psf->instrument->loops [tmp].end - 1) ;
1162                         psf_binheader_writef (psf, "44", 0, psf->instrument->loops [tmp].count) ;
1163                         } ;
1164                 } ;
1165
1166         /* Write custom headers. */
1167         for (uk = 0 ; uk < psf->wchunks.used ; uk++)
1168                 psf_binheader_writef (psf, "m4b", (int) psf->wchunks.chunks [uk].mark32, psf->wchunks.chunks [uk].len, psf->wchunks.chunks [uk].data, make_size_t (psf->wchunks.chunks [uk].len)) ;
1169
1170         if (psf->headindex + 16 < psf->dataoffset)
1171         {       /* Add PAD data if necessary. */
1172                 k = psf->dataoffset - (psf->headindex + 16) ;
1173                 psf_binheader_writef (psf, "m4z", PAD_MARKER, k, make_size_t (k)) ;
1174                 } ;
1175
1176         psf_binheader_writef (psf, "tm8", data_MARKER, psf->datalength) ;
1177         psf_fwrite (psf->header, psf->headindex, 1, psf) ;
1178         if (psf->error)
1179                 return psf->error ;
1180
1181         if (has_data && psf->dataoffset != psf->headindex)
1182         {       psf_log_printf (psf, "Oooops : has_data && psf->dataoffset != psf->headindex\n") ;
1183                 return psf->error = SFE_INTERNAL ;
1184                 } ;
1185
1186         psf->dataoffset = psf->headindex ;
1187
1188         if (! has_data)
1189                 psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
1190         else if (current > 0)
1191                 psf_fseek (psf, current, SEEK_SET) ;
1192
1193         return psf->error ;
1194 } /* wav_write_header */
1195
1196
1197 static int
1198 wav_write_tailer (SF_PRIVATE *psf)
1199 {       int             k ;
1200
1201         /* Reset the current header buffer length to zero. */
1202         psf->header [0] = 0 ;
1203         psf->headindex = 0 ;
1204
1205         if (psf->bytewidth > 0 && psf->sf.seekable == SF_TRUE)
1206         {       psf->datalength = psf->sf.frames * psf->bytewidth * psf->sf.channels ;
1207                 psf->dataend = psf->dataoffset + psf->datalength ;
1208                 } ;
1209
1210         if (psf->dataend > 0)
1211                 psf_fseek (psf, psf->dataend, SEEK_SET) ;
1212         else
1213                 psf->dataend = psf_fseek (psf, 0, SEEK_END) ;
1214
1215         if (psf->dataend & 1)
1216                 psf_binheader_writef (psf, "z", 1) ;
1217
1218         /* Add a PEAK chunk if requested. */
1219         if (psf->peak_info != NULL && psf->peak_info->peak_loc == SF_PEAK_END)
1220         {       psf_binheader_writef (psf, "m4", PEAK_MARKER, WAV_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
1221                 psf_binheader_writef (psf, "44", 1, time (NULL)) ;
1222                 for (k = 0 ; k < psf->sf.channels ; k++)
1223                         psf_binheader_writef (psf, "f4", psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
1224                 } ;
1225
1226         if (psf->strings.flags & SF_STR_LOCATE_END)
1227                 wav_write_strings (psf, SF_STR_LOCATE_END) ;
1228
1229         /* Write the tailer. */
1230         if (psf->headindex > 0)
1231                 psf_fwrite (psf->header, psf->headindex, 1, psf) ;
1232
1233         return 0 ;
1234 } /* wav_write_tailer */
1235
1236 static void
1237 wav_write_strings (SF_PRIVATE *psf, int location)
1238 {       int     k, prev_head_index, saved_head_index ;
1239
1240         if (psf_location_string_count (psf, location) == 0)
1241                 return ;
1242
1243         prev_head_index = psf->headindex + 4 ;
1244
1245         psf_binheader_writef (psf, "m4m", LIST_MARKER, 0xBADBAD, INFO_MARKER) ;
1246
1247         for (k = 0 ; k < SF_MAX_STRINGS ; k++)
1248         {       if (psf->strings.data [k].type == 0)
1249                         break ;
1250                 if (psf->strings.data [k].type < 0 || psf->strings.data [k].flags != location)
1251                         continue ;
1252
1253                 switch (psf->strings.data [k].type)
1254                 {       case SF_STR_SOFTWARE :
1255                                 psf_binheader_writef (psf, "ms", ISFT_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
1256                                 break ;
1257
1258                         case SF_STR_TITLE :
1259                                 psf_binheader_writef (psf, "ms", INAM_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
1260                                 break ;
1261
1262                         case SF_STR_COPYRIGHT :
1263                                 psf_binheader_writef (psf, "ms", ICOP_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
1264                                 break ;
1265
1266                         case SF_STR_ARTIST :
1267                                 psf_binheader_writef (psf, "ms", IART_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
1268                                 break ;
1269
1270                         case SF_STR_COMMENT :
1271                                 psf_binheader_writef (psf, "ms", ICMT_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
1272                                 break ;
1273
1274                         case SF_STR_DATE :
1275                                 psf_binheader_writef (psf, "ms", ICRD_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
1276                                 break ;
1277
1278                         case SF_STR_GENRE :
1279                                 psf_binheader_writef (psf, "ms", IGNR_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
1280                                 break ;
1281
1282                         case SF_STR_ALBUM :
1283                                 psf_binheader_writef (psf, "ms", IPRD_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
1284                                 break ;
1285
1286                         case SF_STR_TRACKNUMBER :
1287                                 psf_binheader_writef (psf, "ms", ITRK_MARKER, psf->strings.storage + psf->strings.data [k].offset) ;
1288                                 break ;
1289
1290                         default :
1291                                 break ;
1292                         } ;
1293                 } ;
1294
1295         saved_head_index = psf->headindex ;
1296         psf->headindex = prev_head_index ;
1297         psf_binheader_writef (psf, "4", saved_head_index - prev_head_index - 4) ;
1298         psf->headindex = saved_head_index ;
1299
1300 } /* wav_write_strings */
1301
1302 static int
1303 wav_close (SF_PRIVATE *psf)
1304 {
1305         if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
1306         {       wav_write_tailer (psf) ;
1307
1308                 if (psf->file.mode == SFM_RDWR)
1309                 {       sf_count_t current = psf_ftell (psf) ;
1310
1311                         /*
1312                         **      If the mode is RDWR and the current position is less than the
1313                         **      filelength, truncate the file.
1314                         */
1315
1316                         if (current < psf->filelength)
1317                         {       psf_ftruncate (psf, current) ;
1318                                 psf->filelength = current ;
1319                                 } ;
1320                         } ;
1321
1322                 psf->write_header (psf, SF_TRUE) ;
1323                 } ;
1324
1325         return 0 ;
1326 } /* wav_close */
1327
1328 static int
1329 wav_command (SF_PRIVATE *psf, int command, void * UNUSED (data), int datasize)
1330 {       WAV_PRIVATE     *wpriv ;
1331
1332         if ((wpriv = psf->container_data) == NULL)
1333                 return SFE_INTERNAL ;
1334
1335         switch (command)
1336         {       case SFC_WAVEX_SET_AMBISONIC :
1337                         if ((SF_CONTAINER (psf->sf.format)) == SF_FORMAT_WAVEX)
1338                         {       if (datasize == SF_AMBISONIC_NONE)
1339                                         wpriv->wavex_ambisonic = SF_AMBISONIC_NONE ;
1340                                 else if (datasize == SF_AMBISONIC_B_FORMAT)
1341                                         wpriv->wavex_ambisonic = SF_AMBISONIC_B_FORMAT ;
1342                                 else
1343                                         return 0 ;
1344                                 } ;
1345                         return wpriv->wavex_ambisonic ;
1346
1347                 case SFC_WAVEX_GET_AMBISONIC :
1348                         return wpriv->wavex_ambisonic ;
1349
1350                 case SFC_SET_CHANNEL_MAP_INFO :
1351                         wpriv->wavex_channelmask = wavex_gen_channel_mask (psf->channel_map, psf->sf.channels) ;
1352                         return (wpriv->wavex_channelmask != 0) ;
1353
1354                 default :
1355                         break ;
1356         } ;
1357
1358         return 0 ;
1359 } /* wav_command */
1360
1361 static int
1362 wav_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
1363 {       sf_count_t      current_pos ;
1364         char            buffer [512] ;
1365         uint32_t        chunk_size, bytesread ;
1366
1367         current_pos = psf_fseek (psf, 0, SEEK_CUR) - 4 ;
1368
1369         bytesread = sizeof (chunk_length) ;
1370
1371         if (chunk_length <= 8)
1372         {       /* This case is for broken files generated by PEAK. */
1373                 psf_log_printf (psf, "%M : %u (weird length)\n", chunk, chunk_length) ;
1374                 psf_binheader_readf (psf, "mj", &chunk, chunk_length - 4) ;
1375                 psf_log_printf (psf, "  %M\n", chunk) ;
1376                 return 0 ;
1377                 } ;
1378
1379         if (psf->headindex + chunk_length > SIGNED_SIZEOF (psf->header))
1380         {       psf_log_printf (psf, "%M : %u (too long)\n", chunk, chunk_length) ;
1381                 psf_binheader_readf (psf, "j", chunk_length) ;
1382                 return 0 ;
1383                 } ;
1384
1385         if (current_pos + chunk_length > psf->filelength)
1386         {       psf_log_printf (psf, "%M : %u (should be %d)\n", chunk, chunk_length, (int) (psf->filelength - current_pos)) ;
1387                 chunk_length = psf->filelength - current_pos ;
1388                 }
1389         else
1390                 psf_log_printf (psf, "%M : %u\n", chunk, chunk_length) ;
1391
1392         while (bytesread < chunk_length)
1393         {       uint32_t thisread ;
1394
1395                 if ((thisread = psf_binheader_readf (psf, "m", &chunk)) == 0)
1396                         break ;
1397                 bytesread += thisread ;
1398
1399                 switch (chunk)
1400                 {       case adtl_MARKER :
1401                         case INFO_MARKER :
1402                                         /* These markers don't contain anything, not even a chunk lebgth. */
1403                                         psf_log_printf (psf, "  %M\n", chunk) ;
1404                                         continue ;
1405
1406                         case exif_MARKER :
1407                                         psf_log_printf (psf, "  %M\n", chunk) ;
1408                                         bytesread += exif_subchunk_parse (psf, chunk_length - bytesread) ;
1409                                         continue ;
1410
1411                         case data_MARKER :
1412                                         psf_log_printf (psf, "  %M inside a LIST block??? Backing out.\n", chunk) ;
1413                                         /* Jump back four bytes and return to caller. */
1414                                         psf_binheader_readf (psf, "j", -4) ;
1415                                         return 0 ;
1416
1417                         case 0 :
1418                                         /*
1419                                         **      Four zero bytes where a marker was expected. Assume this means
1420                                         **      the rest of the chunk is garbage.
1421                                         */
1422                                         psf_log_printf (psf, "    *** Found weird-ass zero marker. Jumping to end of chunk.\n") ;
1423                                         if (bytesread < chunk_length)
1424                                                 bytesread += psf_binheader_readf (psf, "j", chunk_length - bytesread + 4) ;
1425                                         psf_log_printf (psf, "    *** Offset is now : 0x%X\n", psf_fseek (psf, 0, SEEK_CUR)) ;
1426                                         return 0 ;
1427
1428                         default :
1429                                         break ;
1430                         } ;
1431
1432                 switch (chunk)
1433                 {       case ISFT_MARKER :
1434                         case ICOP_MARKER :
1435                         case IARL_MARKER :
1436                         case IART_MARKER :
1437                         case ICMT_MARKER :
1438                         case ICRD_MARKER :
1439                         case IENG_MARKER :
1440                         case IGNR_MARKER :
1441                         case INAM_MARKER :
1442                         case IPRD_MARKER :
1443                         case ISBJ_MARKER :
1444                         case ISRC_MARKER :
1445                         case IAUT_MARKER :
1446                         case ITRK_MARKER :
1447                                         bytesread += psf_binheader_readf (psf, "4", &chunk_size) ;
1448                                         chunk_size += (chunk_size & 1) ;
1449                                         if (chunk_size >= SIGNED_SIZEOF (buffer) || chunk_size >= chunk_length)
1450                                         {       psf_log_printf (psf, "  *** %M : %u (too big)\n", chunk, chunk_size) ;
1451                                                 psf_binheader_readf (psf, "j", chunk_length) ;
1452                                                 return 0 ;
1453                                                 } ;
1454
1455                                         bytesread += psf_binheader_readf (psf, "b", buffer, chunk_size) ;
1456                                         buffer [chunk_size] = 0 ;
1457                                         psf_log_printf (psf, "    %M : %s\n", chunk, buffer) ;
1458                                         break ;
1459
1460                         case labl_MARKER :
1461                                         {       int mark_id ;
1462
1463                                                 bytesread += psf_binheader_readf (psf, "44", &chunk_size, &mark_id) ;
1464                                                 chunk_size -= 4 ;
1465                                                 chunk_size += (chunk_size & 1) ;
1466                                                 if (chunk_size < 1 || chunk_size >= SIGNED_SIZEOF (buffer) || chunk_size >= chunk_length)
1467                                                 {       psf_log_printf (psf, "  *** %M : %u (too big)\n", chunk, chunk_size) ;
1468                                                         psf_binheader_readf (psf, "j", chunk_length) ;
1469                                                         break ;
1470                                                         } ;
1471
1472                                                 bytesread += psf_binheader_readf (psf, "b", buffer, chunk_size) ;
1473                                                 buffer [chunk_size] = 0 ;
1474                                                 psf_log_printf (psf, "    %M : %u : %s\n", chunk, mark_id, buffer) ;
1475                                                 } ;
1476                                         break ;
1477
1478
1479                         case DISP_MARKER :
1480                         case ltxt_MARKER :
1481                         case note_MARKER :
1482                                         bytesread += psf_binheader_readf (psf, "4", &chunk_size) ;
1483                                         chunk_size += (chunk_size & 1) ;
1484                                         if (chunk_size >= SIGNED_SIZEOF (buffer) || chunk_size >= chunk_length)
1485                                         {       psf_log_printf (psf, "  *** %M : %u (too big)\n", chunk, chunk_size) ;
1486                                                 psf_binheader_readf (psf, "j", chunk_length) ;
1487                                                 return 0 ;
1488                                                 } ;
1489
1490                                         bytesread += psf_binheader_readf (psf, "j", chunk_size) ;
1491                                         psf_log_printf (psf, "    %M : %u\n", chunk, chunk_size) ;
1492                                         break ;
1493
1494                         default :
1495                                         bytesread += psf_binheader_readf (psf, "4", &chunk_size) ;
1496                                         chunk_size += (chunk_size & 1) ;
1497                                         psf_log_printf (psf, "    *** %M : %u\n", chunk, chunk_size) ;
1498                                         if (bytesread + chunk_size > chunk_length)
1499                                         {       bytesread += psf_binheader_readf (psf, "j", chunk_length - bytesread + 4) ;
1500                                                 continue ;
1501                                                 }
1502                                         else
1503                                                 bytesread += psf_binheader_readf (psf, "j", chunk_size) ;
1504
1505                                         if (chunk_size >= chunk_length)
1506                                                 return 0 ;
1507                                         break ;
1508                         } ;
1509
1510                 switch (chunk)
1511                 {       case ISFT_MARKER :
1512                                         psf_store_string (psf, SF_STR_SOFTWARE, buffer) ;
1513                                         break ;
1514                         case ICOP_MARKER :
1515                                         psf_store_string (psf, SF_STR_COPYRIGHT, buffer) ;
1516                                         break ;
1517                         case INAM_MARKER :
1518                                         psf_store_string (psf, SF_STR_TITLE, buffer) ;
1519                                         break ;
1520                         case IART_MARKER :
1521                                         psf_store_string (psf, SF_STR_ARTIST, buffer) ;
1522                                         break ;
1523                         case ICMT_MARKER :
1524                                         psf_store_string (psf, SF_STR_COMMENT, buffer) ;
1525                                         break ;
1526                         case ICRD_MARKER :
1527                                         psf_store_string (psf, SF_STR_DATE, buffer) ;
1528                                         break ;
1529                         case IGNR_MARKER :
1530                                         psf_store_string (psf, SF_STR_GENRE, buffer) ;
1531                                         break ;
1532                         case IPRD_MARKER :
1533                                         psf_store_string (psf, SF_STR_ALBUM, buffer) ;
1534                                         break ;
1535                         case ITRK_MARKER :
1536                                         psf_store_string (psf, SF_STR_TRACKNUMBER, buffer) ;
1537                                         break ;
1538                         } ;
1539                 } ;
1540
1541         current_pos = psf_fseek (psf, 0, SEEK_CUR) - current_pos ;
1542
1543         if (current_pos - 4 != chunk_length)
1544                 psf_log_printf (psf, "**** Bad chunk length %d sbould be %D\n", chunk_length, current_pos - 4) ;
1545
1546         return 0 ;
1547 } /* wav_subchunk_parse */
1548
1549 static int
1550 wav_read_smpl_chunk (SF_PRIVATE *psf, uint32_t chunklen)
1551 {       char buffer [512] ;
1552         uint32_t thisread, bytesread = 0, dword, sampler_data, loop_count ;
1553         uint32_t note, start, end, type = -1, count ;
1554         int j, k ;
1555
1556         chunklen += (chunklen & 1) ;
1557
1558         bytesread += psf_binheader_readf (psf, "4", &dword) ;
1559         psf_log_printf (psf, "  Manufacturer : %X\n", dword) ;
1560
1561         bytesread += psf_binheader_readf (psf, "4", &dword) ;
1562         psf_log_printf (psf, "  Product      : %u\n", dword) ;
1563
1564         bytesread += psf_binheader_readf (psf, "4", &dword) ;
1565         psf_log_printf (psf, "  Period       : %u nsec\n", dword) ;
1566
1567         bytesread += psf_binheader_readf (psf, "4", &note) ;
1568         psf_log_printf (psf, "  Midi Note    : %u\n", note) ;
1569
1570         bytesread += psf_binheader_readf (psf, "4", &dword) ;
1571         if (dword != 0)
1572         {       snprintf (buffer, sizeof (buffer), "%f",
1573                                         (1.0 * 0x80000000) / ((uint32_t) dword)) ;
1574                 psf_log_printf (psf, "  Pitch Fract. : %s\n", buffer) ;
1575                 }
1576         else
1577                 psf_log_printf (psf, "  Pitch Fract. : 0\n") ;
1578
1579         bytesread += psf_binheader_readf (psf, "4", &dword) ;
1580         psf_log_printf (psf, "  SMPTE Format : %u\n", dword) ;
1581
1582         bytesread += psf_binheader_readf (psf, "4", &dword) ;
1583         snprintf (buffer, sizeof (buffer), "%02d:%02d:%02d %02d",
1584                                 (dword >> 24) & 0x7F, (dword >> 16) & 0x7F, (dword >> 8) & 0x7F, dword & 0x7F) ;
1585         psf_log_printf (psf, "  SMPTE Offset : %s\n", buffer) ;
1586
1587         bytesread += psf_binheader_readf (psf, "4", &loop_count) ;
1588         psf_log_printf (psf, "  Loop Count   : %u\n", loop_count) ;
1589
1590         if (loop_count == 0 && chunklen == bytesread)
1591                 return 0 ;
1592
1593         /* Sampler Data holds the number of data bytes after the CUE chunks which
1594         ** is not actually CUE data. Display value after CUE data.
1595         */
1596         bytesread += psf_binheader_readf (psf, "4", &sampler_data) ;
1597
1598         if ((psf->instrument = psf_instrument_alloc ()) == NULL)
1599                 return SFE_MALLOC_FAILED ;
1600
1601         psf->instrument->loop_count = loop_count ;
1602
1603         for (j = 0 ; loop_count > 0 && chunklen - bytesread >= 24 ; j ++)
1604         {       if ((thisread = psf_binheader_readf (psf, "4", &dword)) == 0)
1605                         break ;
1606                 bytesread += thisread ;
1607                 psf_log_printf (psf, "    Cue ID : %2u", dword) ;
1608
1609                 bytesread += psf_binheader_readf (psf, "4", &type) ;
1610                 psf_log_printf (psf, "  Type : %2u", type) ;
1611
1612                 bytesread += psf_binheader_readf (psf, "4", &start) ;
1613                 psf_log_printf (psf, "  Start : %5u", start) ;
1614
1615                 bytesread += psf_binheader_readf (psf, "4", &end) ;
1616                 psf_log_printf (psf, "  End : %5u", end) ;
1617
1618                 bytesread += psf_binheader_readf (psf, "4", &dword) ;
1619                 psf_log_printf (psf, "  Fraction : %5u", dword) ;
1620
1621                 bytesread += psf_binheader_readf (psf, "4", &count) ;
1622                 psf_log_printf (psf, "  Count : %5u\n", count) ;
1623
1624                 if (j < ARRAY_LEN (psf->instrument->loops))
1625                 {       psf->instrument->loops [j].start = start ;
1626                         psf->instrument->loops [j].end = end + 1 ;
1627                         psf->instrument->loops [j].count = count ;
1628
1629                         switch (type)
1630                         {       case 0 :
1631                                         psf->instrument->loops [j].mode = SF_LOOP_FORWARD ;
1632                                         break ;
1633                                 case 1 :
1634                                         psf->instrument->loops [j].mode = SF_LOOP_ALTERNATING ;
1635                                         break ;
1636                                 case 2 :
1637                                         psf->instrument->loops [j].mode = SF_LOOP_BACKWARD ;
1638                                         break ;
1639                                 default:
1640                                         psf->instrument->loops [j].mode = SF_LOOP_NONE ;
1641                                         break ;
1642                                 } ;
1643                         } ;
1644
1645                 loop_count -- ;
1646                 } ;
1647
1648         if (chunklen - bytesread == 0)
1649         {       if (sampler_data != 0)
1650                         psf_log_printf (psf, "  Sampler Data : %u (should be 0)\n", sampler_data) ;
1651                 else
1652                         psf_log_printf (psf, "  Sampler Data : %u\n", sampler_data) ;
1653                 }
1654         else
1655         {       if (sampler_data != chunklen - bytesread)
1656                 {       psf_log_printf (psf, "  Sampler Data : %u (should have been %u)\n", sampler_data, chunklen - bytesread) ;
1657                         sampler_data = chunklen - bytesread ;
1658                         }
1659                 else
1660                         psf_log_printf (psf, "  Sampler Data : %u\n", sampler_data) ;
1661
1662                 psf_log_printf (psf, "      ") ;
1663                 for (k = 0 ; k < (int) sampler_data ; k++)
1664                 {       char ch ;
1665
1666                         if (k > 0 && (k % 20) == 0)
1667                                 psf_log_printf (psf, "\n      ") ;
1668
1669                         if ((thisread = psf_binheader_readf (psf, "1", &ch)) == 0)
1670                                 break ;
1671                         bytesread += thisread ;
1672                         psf_log_printf (psf, "%02X ", ch & 0xFF) ;
1673                         } ;
1674
1675                 psf_log_printf (psf, "\n") ;
1676                 } ;
1677
1678         psf->instrument->basenote = note ;
1679         psf->instrument->gain = 1 ;
1680         psf->instrument->velocity_lo = psf->instrument->key_lo = 0 ;
1681         psf->instrument->velocity_hi = psf->instrument->key_hi = 127 ;
1682
1683         return 0 ;
1684 } /* wav_read_smpl_chunk */
1685
1686 /*
1687 ** The acid chunk goes a little something like this:
1688 **
1689 ** 4 bytes          'acid'
1690 ** 4 bytes (int)     length of chunk starting at next byte
1691 **
1692 ** 4 bytes (int)     type of file:
1693 **        this appears to be a bit mask,however some combinations
1694 **        are probably impossible and/or qualified as "errors"
1695 **
1696 **        0x01 On: One Shot         Off: Loop
1697 **        0x02 On: Root note is Set Off: No root
1698 **        0x04 On: Stretch is On,   Off: Strech is OFF
1699 **        0x08 On: Disk Based       Off: Ram based
1700 **        0x10 On: ??????????       Off: ????????? (Acidizer puts that ON)
1701 **
1702 ** 2 bytes (short)      root note
1703 **        if type 0x10 is OFF : [C,C#,(...),B] -> [0x30 to 0x3B]
1704 **        if type 0x10 is ON  : [C,C#,(...),B] -> [0x3C to 0x47]
1705 **         (both types fit on same MIDI pitch albeit different octaves, so who cares)
1706 **
1707 ** 2 bytes (short)      ??? always set to 0x8000
1708 ** 4 bytes (float)      ??? seems to be always 0
1709 ** 4 bytes (int)        number of beats
1710 ** 2 bytes (short)      meter denominator   //always 4 in SF/ACID
1711 ** 2 bytes (short)      meter numerator     //always 4 in SF/ACID
1712 **                      //are we sure about the order?? usually its num/denom
1713 ** 4 bytes (float)      tempo
1714 **
1715 */
1716
1717 static int
1718 wav_read_acid_chunk (SF_PRIVATE *psf, uint32_t chunklen)
1719 {       char buffer [512] ;
1720         uint32_t bytesread = 0 ;
1721         int     beats, flags ;
1722         short rootnote, q1, meter_denom, meter_numer ;
1723         float q2, tempo ;
1724
1725         chunklen += (chunklen & 1) ;
1726
1727         bytesread += psf_binheader_readf (psf, "422f", &flags, &rootnote, &q1, &q2) ;
1728
1729         snprintf (buffer, sizeof (buffer), "%f", q2) ;
1730
1731         psf_log_printf (psf, "  Flags     : 0x%04x (%s,%s,%s,%s,%s)\n", flags,
1732                         (flags & 0x01) ? "OneShot" : "Loop",
1733                         (flags & 0x02) ? "RootNoteValid" : "RootNoteInvalid",
1734                         (flags & 0x04) ? "StretchOn" : "StretchOff",
1735                         (flags & 0x08) ? "DiskBased" : "RAMBased",
1736                         (flags & 0x10) ? "??On" : "??Off") ;
1737
1738         psf_log_printf (psf, "  Root note : 0x%x\n  ????      : 0x%04x\n  ????      : %s\n",
1739                                 rootnote, q1, buffer) ;
1740
1741         bytesread += psf_binheader_readf (psf, "422f", &beats, &meter_denom, &meter_numer, &tempo) ;
1742         snprintf (buffer, sizeof (buffer), "%f", tempo) ;
1743         psf_log_printf (psf, "  Beats     : %d\n  Meter     : %d/%d\n  Tempo     : %s\n",
1744                                 beats, meter_numer, meter_denom, buffer) ;
1745
1746         psf_binheader_readf (psf, "j", chunklen - bytesread) ;
1747
1748         if ((psf->loop_info = calloc (1, sizeof (SF_LOOP_INFO))) == NULL)
1749                 return SFE_MALLOC_FAILED ;
1750
1751         psf->loop_info->time_sig_num    = meter_numer ;
1752         psf->loop_info->time_sig_den    = meter_denom ;
1753         psf->loop_info->loop_mode               = (flags & 0x01) ? SF_LOOP_NONE : SF_LOOP_FORWARD ;
1754         psf->loop_info->num_beats               = beats ;
1755         psf->loop_info->bpm                             = tempo ;
1756         psf->loop_info->root_key                = (flags & 0x02) ? rootnote : -1 ;
1757
1758         return 0 ;
1759 } /* wav_read_acid_chunk */
1760
1761 int
1762 wav_read_bext_chunk (SF_PRIVATE *psf, uint32_t chunksize)
1763 {
1764         SF_BROADCAST_INFO_16K * b ;
1765         uint32_t bytes = 0 ;
1766
1767         if (chunksize < WAV_BEXT_MIN_CHUNK_SIZE)
1768         {       psf_log_printf (psf, "bext : %u (should be >= %d)\n", chunksize, WAV_BEXT_MIN_CHUNK_SIZE) ;
1769                 psf_binheader_readf (psf, "j", chunksize) ;
1770                 return 0 ;
1771                 } ;
1772
1773         if (chunksize > WAV_BEXT_MAX_CHUNK_SIZE)
1774         {       psf_log_printf (psf, "bext : %u (should be < %d)\n", chunksize, WAV_BEXT_MAX_CHUNK_SIZE) ;
1775                 psf_binheader_readf (psf, "j", chunksize) ;
1776                 return 0 ;
1777                 } ;
1778
1779         if (chunksize >= sizeof (SF_BROADCAST_INFO_16K))
1780         {       psf_log_printf (psf, "bext : %u too big to be handled\n", chunksize) ;
1781                 psf_binheader_readf (psf, "j", chunksize) ;
1782                 return 0 ;
1783                 } ;
1784
1785         psf_log_printf (psf, "bext : %u\n", chunksize) ;
1786
1787         if ((psf->broadcast_16k = broadcast_var_alloc ()) == NULL)
1788         {       psf->error = SFE_MALLOC_FAILED ;
1789                 return psf->error ;
1790                 } ;
1791
1792         b = psf->broadcast_16k ;
1793
1794         bytes += psf_binheader_readf (psf, "b", b->description, sizeof (b->description)) ;
1795         bytes += psf_binheader_readf (psf, "b", b->originator, sizeof (b->originator)) ;
1796         bytes += psf_binheader_readf (psf, "b", b->originator_reference, sizeof (b->originator_reference)) ;
1797         bytes += psf_binheader_readf (psf, "b", b->origination_date, sizeof (b->origination_date)) ;
1798         bytes += psf_binheader_readf (psf, "b", b->origination_time, sizeof (b->origination_time)) ;
1799         bytes += psf_binheader_readf (psf, "442", &b->time_reference_low, &b->time_reference_high, &b->version) ;
1800         bytes += psf_binheader_readf (psf, "bj", &b->umid, sizeof (b->umid), 190) ;
1801
1802         if (chunksize > WAV_BEXT_MIN_CHUNK_SIZE)
1803         {       /* File has coding history data. */
1804
1805                 b->coding_history_size = chunksize - WAV_BEXT_MIN_CHUNK_SIZE ;
1806
1807                 /* We do not parse the coding history */
1808                 bytes += psf_binheader_readf (psf, "b", b->coding_history, b->coding_history_size) ;
1809                 } ;
1810
1811         if (bytes < chunksize)
1812                 psf_binheader_readf (psf, "j", chunksize - bytes) ;
1813
1814         return 0 ;
1815 } /* wav_read_bext_chunk */
1816
1817 int
1818 wav_write_bext_chunk (SF_PRIVATE *psf)
1819 {       SF_BROADCAST_INFO_16K *b ;
1820
1821         if (psf->broadcast_16k == NULL)
1822                 return -1 ;
1823
1824         b = psf->broadcast_16k ;
1825
1826         psf_binheader_writef (psf, "m4", bext_MARKER, WAV_BEXT_MIN_CHUNK_SIZE + b->coding_history_size) ;
1827
1828         /*
1829         **      Note that it is very important that the field widths of the SF_BROADCAST_INFO
1830         **      struct match those of the bext chunk fields.
1831         */
1832
1833         psf_binheader_writef (psf, "b", b->description, sizeof (b->description)) ;
1834         psf_binheader_writef (psf, "b", b->originator, sizeof (b->originator)) ;
1835         psf_binheader_writef (psf, "b", b->originator_reference, sizeof (b->originator_reference)) ;
1836         psf_binheader_writef (psf, "b", b->origination_date, sizeof (b->origination_date)) ;
1837         psf_binheader_writef (psf, "b", b->origination_time, sizeof (b->origination_time)) ;
1838         psf_binheader_writef (psf, "442", b->time_reference_low, b->time_reference_high, b->version) ;
1839         psf_binheader_writef (psf, "b", b->umid, sizeof (b->umid)) ;
1840         psf_binheader_writef (psf, "z", make_size_t (190)) ;
1841
1842         if (b->coding_history_size > 0)
1843                 psf_binheader_writef (psf, "b", b->coding_history, make_size_t (b->coding_history_size)) ;
1844
1845         return 0 ;
1846 } /* wav_write_bext_chunk */
1847
1848 int
1849 wav_read_cart_chunk (SF_PRIVATE *psf, uint32_t chunksize)
1850 {       SF_CART_INFO_16K *c ;
1851         uint32_t bytes = 0 ;
1852         int k ;
1853
1854         if (chunksize < WAV_CART_MIN_CHUNK_SIZE)
1855         {       psf_log_printf (psf, "cart : %u (should be >= %d)\n", chunksize, WAV_CART_MIN_CHUNK_SIZE) ;
1856                 psf_binheader_readf (psf, "j", chunksize) ;
1857                 return 0 ;
1858                 } ;
1859         if (chunksize > WAV_CART_MAX_CHUNK_SIZE)
1860         {       psf_log_printf (psf, "cart : %u (should be < %d)\n", chunksize, WAV_CART_MAX_CHUNK_SIZE) ;
1861                 psf_binheader_readf (psf, "j", chunksize) ;
1862                 return 0 ;
1863                 } ;
1864
1865         if (chunksize >= sizeof (SF_CART_INFO_16K))
1866         {       psf_log_printf (psf, "cart : %u too big to be handled\n", chunksize) ;
1867                 psf_binheader_readf (psf, "j", chunksize) ;
1868                 return 0 ;
1869                 } ;
1870
1871         psf_log_printf (psf, "cart : %u\n", chunksize) ;
1872
1873         if ((psf->cart_16k = cart_var_alloc ()) == NULL)
1874         {       psf->error = SFE_MALLOC_FAILED ;
1875                 return psf->error ;
1876                 } ;
1877
1878         c = psf->cart_16k ;
1879         bytes += psf_binheader_readf (psf, "b", c->version, sizeof (c->version)) ;
1880         bytes += psf_binheader_readf (psf, "b", c->title, sizeof (c->title)) ;
1881         bytes += psf_binheader_readf (psf, "b", c->artist, sizeof (c->artist)) ;
1882         bytes += psf_binheader_readf (psf, "b", c->cut_id, sizeof (c->cut_id)) ;
1883         bytes += psf_binheader_readf (psf, "b", c->client_id, sizeof (c->client_id)) ;
1884         bytes += psf_binheader_readf (psf, "b", c->category, sizeof (c->category)) ;
1885         bytes += psf_binheader_readf (psf, "b", c->classification, sizeof (c->classification)) ;
1886         bytes += psf_binheader_readf (psf, "b", c->out_cue, sizeof (c->out_cue)) ;
1887         bytes += psf_binheader_readf (psf, "b", c->start_date, sizeof (c->start_date)) ;
1888         bytes += psf_binheader_readf (psf, "b", c->start_time, sizeof (c->start_time)) ;
1889         bytes += psf_binheader_readf (psf, "b", c->end_date, sizeof (c->end_date)) ;
1890         bytes += psf_binheader_readf (psf, "b", c->end_time, sizeof (c->end_time)) ;
1891         bytes += psf_binheader_readf (psf, "b", c->producer_app_id, sizeof (c->producer_app_id)) ;
1892         bytes += psf_binheader_readf (psf, "b", c->producer_app_version, sizeof (c->producer_app_version)) ;
1893         bytes += psf_binheader_readf (psf, "b", c->user_def, sizeof (c->user_def)) ;
1894         bytes += psf_binheader_readf (psf, "e4", &c->level_reference, sizeof (c->level_reference)) ;
1895
1896         for (k = 0 ; k < ARRAY_LEN (c->post_timers) ; k++)
1897                 bytes += psf_binheader_readf (psf, "b4", &c->post_timers [k].usage, make_size_t (4), &c->post_timers [k].value) ;
1898
1899         bytes += psf_binheader_readf (psf, "b", c->reserved, sizeof (c->reserved)) ;
1900         bytes += psf_binheader_readf (psf, "b", c->url, sizeof (c->url)) ;
1901
1902         if (chunksize > WAV_CART_MIN_CHUNK_SIZE)
1903         {       /* File has tag text. */
1904                 c->tag_text_size = chunksize - WAV_CART_MIN_CHUNK_SIZE ;
1905                 bytes += psf_binheader_readf (psf, "b", c->tag_text, make_size_t (c->tag_text_size)) ;
1906                 } ;
1907
1908         return 0 ;
1909 } /* wav_read_cart_chunk */
1910
1911 int
1912 wav_write_cart_chunk (SF_PRIVATE *psf)
1913 {       SF_CART_INFO_16K *c ;
1914         int k ;
1915
1916         if (psf->cart_16k == NULL)
1917                 return -1 ;
1918
1919         c = psf->cart_16k ;
1920         psf_binheader_writef (psf, "m4", cart_MARKER, WAV_CART_MIN_CHUNK_SIZE + c->tag_text_size) ;
1921         /*
1922         **      Note that it is very important that the field widths of the SF_CART_INFO
1923         **      struct match those of the cart chunk fields.
1924         */
1925         psf_binheader_writef (psf, "b", c->version, sizeof (c->version)) ;
1926         psf_binheader_writef (psf, "b", c->title, sizeof (c->title)) ;
1927         psf_binheader_writef (psf, "b", c->artist, sizeof (c->artist)) ;
1928         psf_binheader_writef (psf, "b", c->cut_id, sizeof (c->cut_id)) ;
1929         psf_binheader_writef (psf, "b", c->client_id, sizeof (c->client_id)) ;
1930         psf_binheader_writef (psf, "b", c->category, sizeof (c->category)) ;
1931         psf_binheader_writef (psf, "b", c->classification, sizeof (c->classification)) ;
1932         psf_binheader_writef (psf, "b", c->out_cue, sizeof (c->out_cue)) ;
1933         psf_binheader_writef (psf, "b", c->start_date, sizeof (c->start_date)) ;
1934         psf_binheader_writef (psf, "b", c->start_time, sizeof (c->start_time)) ;
1935         psf_binheader_writef (psf, "b", c->end_date, sizeof (c->end_date)) ;
1936         psf_binheader_writef (psf, "b", c->end_time, sizeof (c->end_time)) ;
1937         psf_binheader_writef (psf, "b", c->producer_app_id, sizeof (c->producer_app_id)) ;
1938         psf_binheader_writef (psf, "b", c->producer_app_version, sizeof (c->producer_app_version)) ;
1939         psf_binheader_writef (psf, "b", c->user_def, sizeof (c->user_def)) ;
1940         psf_binheader_writef (psf, "4", c->level_reference, sizeof (c->level_reference)) ;
1941
1942         for (k = 0 ; k < ARRAY_LEN (c->post_timers) ; k++)
1943                 psf_binheader_writef (psf, "b4", c->post_timers [k].usage, make_size_t (4), c->post_timers [k].value) ;
1944
1945         psf_binheader_writef (psf, "z", sizeof (c->reserved)) ; // just write zeros, we don't have any other use for it
1946         psf_binheader_writef (psf, "b", c->url, sizeof (c->url)) ;
1947
1948         if (c->tag_text_size > 0)
1949                 psf_binheader_writef (psf, "b", c->tag_text, make_size_t (c->tag_text_size)) ;
1950
1951         return 0 ;
1952 } /* wav_write_cart_chunk */
1953
1954 static int
1955 exif_fill_and_sink (SF_PRIVATE *psf, char* buf, size_t bufsz, size_t toread)
1956 {
1957         size_t bytesread = 0 ;
1958
1959         buf [0] = 0 ;
1960         bufsz -= 1 ;
1961         if (toread < bufsz)
1962                 bufsz = toread ;
1963         bytesread = psf_binheader_readf (psf, "b", buf, bufsz) ;
1964         buf [bufsz] = 0 ;
1965
1966         if (bytesread == bufsz && toread > bufsz)
1967                 bytesread += psf_binheader_readf (psf, "j", toread - bufsz) ;
1968
1969         return bytesread ;
1970 } /* exif_fill_and_sink */
1971
1972 /*
1973 ** Exif specification for audio files, at JEITA CP-3451 Exif 2.2 section 5
1974 ** (Exif Audio File Specification) http://www.exif.org/Exif2-2.PDF
1975 */
1976 static int
1977 exif_subchunk_parse (SF_PRIVATE *psf, uint32_t length)
1978 {       uint32_t marker, dword, vmajor = -1, vminor = -1, bytesread = 0 ;
1979         char buf [4096] ;
1980         int thisread ;
1981
1982         while (bytesread < length)
1983         {
1984                 if ((thisread = psf_binheader_readf (psf, "m", &marker)) == 0)
1985                         break ;
1986                 bytesread += thisread ;
1987
1988                 switch (marker)
1989                 {
1990                         case 0 : /* camera padding? */
1991                                 break ;
1992
1993                         case ever_MARKER :
1994                                 bytesread += psf_binheader_readf (psf, "j4", 4, &dword) ;
1995                                 vmajor = 10 * (((dword >> 24) & 0xff) - '0') + (((dword >> 16) & 0xff) - '0') ;
1996                                 vminor = 10 * (((dword >> 8) & 0xff) - '0') + ((dword & 0xff) - '0') ;
1997                                 psf_log_printf (psf, "    EXIF Version : %u.%02u\n", vmajor, vminor) ;
1998                                 break ;
1999
2000                         case olym_MARKER :
2001                                 bytesread += psf_binheader_readf (psf, "4", &dword) ;
2002                                 psf_log_printf (psf, "%M : %u\n", marker, dword) ;
2003                                 if (bytesread + dword > length)
2004                                         break ;
2005                                 dword += (dword & 1) ;
2006                                 bytesread += psf_binheader_readf (psf, "j", dword) ;
2007                                 break ;
2008
2009                         case emnt_MARKER : /* design information: null-terminated string */
2010                         case emdl_MARKER : /* model name ; null-terminated string */
2011                         case ecor_MARKER : /* manufacturer: null-terminated string */
2012                         case etim_MARKER : /* creation time: null-terminated string in the format "hour:minute:second.subsecond" */
2013                         case erel_MARKER : /* relation info: null-terminated string (filename) */
2014                         case eucm_MARKER : /* user comment: 4-byte size follows, then possibly unicode data */
2015                                 bytesread += psf_binheader_readf (psf, "4", &dword) ;
2016                                 bytesread += sizeof (dword) ;
2017                                 dword += (dword & 1) ;
2018
2019                                 if (dword >= sizeof (buf))
2020                                 {       psf_log_printf (psf, "*** Marker '%M' is too big %u\n\n", marker, dword) ;
2021                                         return bytesread ;
2022                                         } ;
2023
2024                                 bytesread += exif_fill_and_sink (psf, buf, sizeof (buf), dword) ;
2025
2026                                 /* BAD - don't know what's going on here -- maybe a bug in the camera */
2027                                 /* field should be NULL-terminated but there's no room for it with the reported number */
2028                                 /*  example output:     emdl : 8 (EX-Z1050) */
2029                                 if (marker == emdl_MARKER && dword == strlen (buf) /* should be >= strlen+1*/)
2030                                 {       psf_log_printf (psf, "    *** field size too small for string (sinking 2 bytes)\n") ;
2031                                         bytesread += psf_binheader_readf (psf, "j", 2) ;
2032                                         } ;
2033
2034                                 psf_log_printf (psf, "    %M : %u (%s)\n", marker, dword, buf) ;
2035                                 if (dword > length)
2036                                         return bytesread ;
2037                                 break ;
2038
2039                         default :
2040                                 psf_log_printf (psf, "    *** %M (%u): -- ignored --\n", marker, marker) ;
2041                                 break ;
2042                         } ;
2043                 } ;
2044
2045         return bytesread ;
2046 } /* exif_subchunk_parse */
2047
2048 /*==============================================================================
2049 */
2050
2051 static int
2052 wav_set_chunk (SF_PRIVATE *psf, const SF_CHUNK_INFO * chunk_info)
2053 {       return psf_save_write_chunk (&psf->wchunks, chunk_info) ;
2054 } /* wav_set_chunk */
2055
2056 static SF_CHUNK_ITERATOR *
2057 wav_next_chunk_iterator (SF_PRIVATE *psf, SF_CHUNK_ITERATOR * iterator)
2058 {       return psf_next_chunk_iterator (&psf->rchunks, iterator) ;
2059 } /* wav_next_chunk_iterator */
2060
2061 static int
2062 wav_get_chunk_size (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info)
2063 {       int indx ;
2064
2065         if ((indx = psf_find_read_chunk_iterator (&psf->rchunks, iterator)) < 0)
2066                 return SFE_UNKNOWN_CHUNK ;
2067
2068         chunk_info->datalen = psf->rchunks.chunks [indx].len ;
2069
2070         return SFE_NO_ERROR ;
2071 } /* wav_get_chunk_size */
2072
2073 static int
2074 wav_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info)
2075 {       int indx ;
2076         sf_count_t pos ;
2077
2078         if ((indx = psf_find_read_chunk_iterator (&psf->rchunks, iterator)) < 0)
2079                 return SFE_UNKNOWN_CHUNK ;
2080
2081         if (chunk_info->data == NULL)
2082                 return SFE_BAD_CHUNK_DATA_PTR ;
2083
2084         chunk_info->id_size = psf->rchunks.chunks [indx].id_size ;
2085         memcpy (chunk_info->id, psf->rchunks.chunks [indx].id, sizeof (chunk_info->id) / sizeof (*chunk_info->id)) ;
2086
2087         pos = psf_ftell (psf) ;
2088         psf_fseek (psf, psf->rchunks.chunks [indx].offset, SEEK_SET) ;
2089         psf_fread (chunk_info->data, SF_MIN (chunk_info->datalen, psf->rchunks.chunks [indx].len), 1, psf) ;
2090         psf_fseek (psf, pos, SEEK_SET) ;
2091
2092         return SFE_NO_ERROR ;
2093 } /* wav_get_chunk_data */