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