Coverage Report

Created: 2025-08-28 07:04

/src/libsndfile/src/wavlike.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** Copyright (C) 1999-2020 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  <string.h>
24
#include  <ctype.h>
25
#include  <time.h>
26
27
#include  "sndfile.h"
28
#include  "sfendian.h"
29
#include  "common.h"
30
#include  "wavlike.h"
31
32
33
1.72k
#define WAV_BEXT_MIN_CHUNK_SIZE   602
34
173
#define WAV_BEXT_MAX_CHUNK_SIZE   (10 * 1024)
35
36
6.10k
#define WAV_CART_MIN_CHUNK_SIZE   2048
37
203
#define WAV_CART_MAX_CHUNK_SIZE   0xffffffff
38
39
40
static int  exif_subchunk_parse (SF_PRIVATE *psf, uint32_t length) ;
41
42
43
/*  Known WAVEFORMATEXTENSIBLE GUIDS.  */
44
static const EXT_SUBFORMAT MSGUID_SUBTYPE_PCM =
45
{ 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
46
} ;
47
48
static const EXT_SUBFORMAT MSGUID_SUBTYPE_MS_ADPCM =
49
{ 0x00000002, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
50
} ;
51
52
static const EXT_SUBFORMAT MSGUID_SUBTYPE_IEEE_FLOAT =
53
{ 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
54
} ;
55
56
static const EXT_SUBFORMAT MSGUID_SUBTYPE_ALAW =
57
{ 0x00000006, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
58
} ;
59
60
static const EXT_SUBFORMAT MSGUID_SUBTYPE_MULAW =
61
{ 0x00000007, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
62
} ;
63
64
/*
65
** the next two are from
66
** http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html
67
*/
68
69
static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM =
70
{ 0x00000001, 0x0721, 0x11d3, { 0x86, 0x44, 0xc8, 0xc1, 0xca, 0x00, 0x00, 0x00 }
71
} ;
72
73
static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT =
74
{ 0x00000003, 0x0721, 0x11d3, { 0x86, 0x44, 0xc8, 0xc1, 0xca, 0x00, 0x00, 0x00 }
75
} ;
76
77
78
#if 0
79
/* maybe interesting one day to read the following through sf_read_raw */
80
/* http://www.bath.ac.uk/~masrwd/pvocex/pvocex.html */
81
static const EXT_SUBFORMAT MSGUID_SUBTYPE_PVOCEX =
82
{ 0x8312b9c2, 0x2e6e, 0x11d4, { 0xa8, 0x24, 0xde, 0x5b, 0x96, 0xc3, 0xab, 0x21 }
83
} ;
84
#endif
85
86
/* This stores which bit in dwChannelMask maps to which channel */
87
static const struct chanmap_s
88
{ int id ;
89
  const char * name ;
90
} channel_mask_bits [] =
91
{ /* WAVEFORMATEXTENSIBLE doesn't distinguish FRONT_LEFT from LEFT */
92
  { SF_CHANNEL_MAP_LEFT, "L" },
93
  { SF_CHANNEL_MAP_RIGHT, "R" },
94
  { SF_CHANNEL_MAP_CENTER, "C" },
95
  { SF_CHANNEL_MAP_LFE, "LFE" },
96
  { SF_CHANNEL_MAP_REAR_LEFT, "Ls" },
97
  { SF_CHANNEL_MAP_REAR_RIGHT, "Rs" },
98
  { SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER, "Lc" },
99
  { SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER, "Rc" },
100
  { SF_CHANNEL_MAP_REAR_CENTER, "Cs" },
101
  { SF_CHANNEL_MAP_SIDE_LEFT, "Sl" },
102
  { SF_CHANNEL_MAP_SIDE_RIGHT, "Sr" },
103
  { SF_CHANNEL_MAP_TOP_CENTER, "Tc" },
104
  { SF_CHANNEL_MAP_TOP_FRONT_LEFT, "Tfl" },
105
  { SF_CHANNEL_MAP_TOP_FRONT_CENTER, "Tfc" },
106
  { SF_CHANNEL_MAP_TOP_FRONT_RIGHT, "Tfr" },
107
  { SF_CHANNEL_MAP_TOP_REAR_LEFT, "Trl" },
108
  { SF_CHANNEL_MAP_TOP_REAR_CENTER, "Trc" },
109
  { SF_CHANNEL_MAP_TOP_REAR_RIGHT, "Trr" },
110
} ;
111
112
/*------------------------------------------------------------------------------
113
 * Private static functions.
114
 */
115
116
static int
117
wavex_guid_equal (const EXT_SUBFORMAT * first, const EXT_SUBFORMAT * second)
118
125k
{ return !memcmp (first, second, sizeof (EXT_SUBFORMAT)) ;
119
125k
} /* wavex_guid_equal */
120
121
122
123
int
124
wavlike_read_fmt_chunk (SF_PRIVATE *psf, int fmtsize)
125
160k
{ WAVLIKE_PRIVATE * wpriv ;
126
160k
  WAV_FMT *wav_fmt ;
127
160k
  int bytesread, k, bytespersec = 0 ;
128
129
160k
  if ((wpriv = psf->container_data) == NULL)
130
0
    return SFE_INTERNAL ;
131
160k
  wav_fmt = &wpriv->wav_fmt ;
132
133
160k
  memset (wav_fmt, 0, sizeof (WAV_FMT)) ;
134
135
160k
  if (fmtsize < 16)
136
65
    return SFE_WAV_FMT_SHORT ;
137
138
  /* assume psf->rwf_endian is already properly set */
139
140
  /* Read the minimal WAV file header here. */
141
160k
  bytesread = psf_binheader_readf (psf, "224422",
142
160k
          &(wav_fmt->format), &(wav_fmt->min.channels),
143
160k
          &(wav_fmt->min.samplerate), &(wav_fmt->min.bytespersec),
144
160k
          &(wav_fmt->min.blockalign), &(wav_fmt->min.bitwidth)) ;
145
146
160k
  psf_log_printf (psf, "  Format        : 0x%X => %s\n", wav_fmt->format, wavlike_format_str (wav_fmt->format)) ;
147
160k
  psf_log_printf (psf, "  Channels      : %d\n", wav_fmt->min.channels) ;
148
160k
  psf_log_printf (psf, "  Sample Rate   : %d\n", wav_fmt->min.samplerate) ;
149
150
160k
  if (wav_fmt->format == WAVE_FORMAT_PCM && wav_fmt->min.blockalign == 0
151
160k
    && wav_fmt->min.bitwidth > 0 && wav_fmt->min.channels > 0)
152
5.72k
  { wav_fmt->min.blockalign = wav_fmt->min.bitwidth / 8 + (wav_fmt->min.bitwidth % 8 > 0 ? 1 : 0) ;
153
5.72k
    wav_fmt->min.blockalign *= wav_fmt->min.channels ;
154
5.72k
    psf_log_printf (psf, "  Block Align   : 0 (should be %d)\n", wav_fmt->min.blockalign) ;
155
5.72k
    }
156
154k
  else
157
154k
    psf_log_printf (psf, "  Block Align   : %d\n", wav_fmt->min.blockalign) ;
158
159
160k
  if (wav_fmt->format == WAVE_FORMAT_PCM && wav_fmt->min.bitwidth == 24 &&
160
160k
      wav_fmt->min.blockalign == 4 * wav_fmt->min.channels)
161
4.10k
  { psf_log_printf (psf, "  Bit Width     : 24\n") ;
162
163
4.10k
    psf_log_printf (psf, "\n"
164
4.10k
      "  Ambiguous information in 'fmt ' chunk. Possible file types:\n"
165
4.10k
      "    0) Invalid IEEE float file generated by Syntrillium's Cooledit!\n"
166
4.10k
      "    1) File generated by ALSA's arecord containing 24 bit samples in 32 bit containers.\n"
167
4.10k
      "    2) 24 bit file with incorrect Block Align value.\n"
168
4.10k
      "\n") ;
169
170
4.10k
    wpriv->fmt_is_broken = 1 ;
171
4.10k
    }
172
156k
  else if (wav_fmt->min.bitwidth == 0)
173
30.3k
  { switch (wav_fmt->format)
174
30.3k
    { case WAVE_FORMAT_GSM610 :
175
2.74k
      case WAVE_FORMAT_IPP_ITU_G_723_1 :
176
6.96k
      case WAVE_FORMAT_MPEGLAYER3 :
177
6.96k
          psf_log_printf (psf, "  Bit Width     : %d\n", wav_fmt->min.bitwidth) ;
178
6.96k
          break ;
179
23.3k
      default :
180
23.3k
          psf_log_printf (psf, "  Bit Width     : %d (should not be 0)\n", wav_fmt->min.bitwidth) ;
181
30.3k
      }
182
30.3k
    }
183
126k
  else
184
126k
  { switch (wav_fmt->format)
185
126k
    { case WAVE_FORMAT_GSM610 :
186
6.94k
      case WAVE_FORMAT_IPP_ITU_G_723_1 :
187
12.4k
      case WAVE_FORMAT_MPEGLAYER3 :
188
12.4k
          psf_log_printf (psf, "  Bit Width     : %d (should be 0)\n", wav_fmt->min.bitwidth) ;
189
12.4k
          break ;
190
113k
      default :
191
113k
          psf_log_printf (psf, "  Bit Width     : %d\n", wav_fmt->min.bitwidth) ;
192
126k
      }
193
160k
    } ;
194
195
160k
  psf->sf.samplerate  = wav_fmt->min.samplerate ;
196
160k
  psf->sf.frames    = 0 ;         /* Correct this when reading data chunk. */
197
160k
  psf->sf.channels  = wav_fmt->min.channels ;
198
199
160k
  switch (wav_fmt->format)
200
160k
  { case WAVE_FORMAT_PCM :
201
53.7k
    case WAVE_FORMAT_IEEE_FLOAT :
202
53.7k
        bytespersec = wav_fmt->min.samplerate * wav_fmt->min.blockalign ;
203
53.7k
        if (wav_fmt->min.bytespersec != (unsigned) bytespersec)
204
47.9k
          psf_log_printf (psf, "  Bytes/sec     : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ;
205
5.88k
        else
206
5.88k
          psf_log_printf (psf, "  Bytes/sec     : %d\n", wav_fmt->min.bytespersec) ;
207
208
53.7k
        psf->bytewidth = BITWIDTH2BYTES (wav_fmt->min.bitwidth) ;
209
53.7k
        break ;
210
211
9.36k
    case WAVE_FORMAT_ALAW :
212
15.0k
    case WAVE_FORMAT_MULAW :
213
15.0k
        if (wav_fmt->min.bytespersec != wav_fmt->min.samplerate * wav_fmt->min.blockalign)
214
10.7k
          psf_log_printf (psf, "  Bytes/sec     : %d (should be %d)\n", wav_fmt->min.bytespersec, wav_fmt->min.samplerate * wav_fmt->min.blockalign) ;
215
4.38k
        else
216
4.38k
          psf_log_printf (psf, "  Bytes/sec     : %d\n", wav_fmt->min.bytespersec) ;
217
218
15.0k
        psf->bytewidth = 1 ;
219
15.0k
        if (fmtsize >= 18)
220
9.09k
        { bytesread += psf_binheader_readf (psf, "2", &(wav_fmt->size20.extrabytes)) ;
221
9.09k
          psf_log_printf (psf, "  Extra Bytes   : %d\n", wav_fmt->size20.extrabytes) ;
222
9.09k
          } ;
223
15.0k
        break ;
224
225
5.17k
    case WAVE_FORMAT_IMA_ADPCM :
226
5.17k
        if (wav_fmt->min.bitwidth != 4)
227
17
          return SFE_WAV_ADPCM_NOT4BIT ;
228
5.16k
        if (wav_fmt->min.channels < 1 || wav_fmt->min.channels > 2)
229
2
          return SFE_WAV_ADPCM_CHANNELS ;
230
231
5.16k
        bytesread += psf_binheader_readf (psf, "22", &(wav_fmt->ima.extrabytes), &(wav_fmt->ima.samplesperblock)) ;
232
5.16k
        psf_log_printf (psf, "  Extra Bytes   : %d\n", wav_fmt->ima.extrabytes) ;
233
5.16k
        if (wav_fmt->ima.samplesperblock < 1)
234
1
        { psf_log_printf (psf, "  Samples/Block : %d (should be > 0)\n", wav_fmt->ima.samplesperblock) ;
235
1
          return SFE_WAV_ADPCM_SAMPLES ;
236
1
          }
237
5.15k
        else
238
5.15k
          psf_log_printf (psf, "  Samples/Block : %d\n", wav_fmt->ima.samplesperblock) ;
239
240
5.15k
        bytespersec = (wav_fmt->ima.samplerate * wav_fmt->ima.blockalign) / wav_fmt->ima.samplesperblock ;
241
5.15k
        if (wav_fmt->ima.bytespersec != (unsigned) bytespersec)
242
2.32k
          psf_log_printf (psf, "  Bytes/sec     : %d (should be %d)\n", wav_fmt->ima.bytespersec, bytespersec) ;
243
2.83k
        else
244
2.83k
          psf_log_printf (psf, "  Bytes/sec     : %d\n", wav_fmt->ima.bytespersec) ;
245
246
5.15k
        break ;
247
248
13.6k
    case WAVE_FORMAT_MS_ADPCM :
249
13.6k
        if (wav_fmt->msadpcm.bitwidth != 4)
250
6
          return SFE_WAV_ADPCM_NOT4BIT ;
251
13.6k
        if (wav_fmt->msadpcm.channels < 1 || wav_fmt->msadpcm.channels > 2)
252
13
          return SFE_WAV_ADPCM_CHANNELS ;
253
254
13.6k
        bytesread += psf_binheader_readf (psf, "222", &(wav_fmt->msadpcm.extrabytes),
255
13.6k
                &(wav_fmt->msadpcm.samplesperblock), &(wav_fmt->msadpcm.numcoeffs)) ;
256
257
13.6k
        psf_log_printf (psf, "  Extra Bytes   : %d\n", wav_fmt->msadpcm.extrabytes) ;
258
13.6k
        if (wav_fmt->ima.samplesperblock < 1)
259
2
        { psf_log_printf (psf, "  Samples/Block : %d (should be > 0)\n", wav_fmt->ima.samplesperblock) ;
260
2
          return SFE_WAV_ADPCM_SAMPLES ;
261
2
          }
262
13.6k
        else
263
13.6k
          psf_log_printf (psf, "  Samples/Block : %d\n", wav_fmt->ima.samplesperblock) ;
264
265
13.6k
        bytespersec = (wav_fmt->min.samplerate * wav_fmt->min.blockalign) / wav_fmt->msadpcm.samplesperblock ;
266
13.6k
        if (wav_fmt->min.bytespersec == (unsigned) bytespersec)
267
3.45k
          psf_log_printf (psf, "  Bytes/sec     : %d\n", wav_fmt->min.bytespersec) ;
268
10.2k
        else if (wav_fmt->min.bytespersec == (wav_fmt->min.samplerate / wav_fmt->msadpcm.samplesperblock) * wav_fmt->min.blockalign)
269
4.89k
          psf_log_printf (psf, "  Bytes/sec     : %d (should be %d (MS BUG!))\n", wav_fmt->min.bytespersec, bytespersec) ;
270
5.31k
        else
271
5.31k
          psf_log_printf (psf, "  Bytes/sec     : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ;
272
273
13.6k
        if (wav_fmt->msadpcm.numcoeffs > ARRAY_LEN (wav_fmt->msadpcm.coeffs))
274
3.20k
        { psf_log_printf (psf, "  No. of Coeffs : %d (should be <= %d)\n", wav_fmt->msadpcm.numcoeffs, ARRAY_LEN (wav_fmt->msadpcm.coeffs)) ;
275
3.20k
          wav_fmt->msadpcm.numcoeffs = ARRAY_LEN (wav_fmt->msadpcm.coeffs) ;
276
3.20k
          }
277
10.4k
        else
278
10.4k
          psf_log_printf (psf, "  No. of Coeffs : %d\n", wav_fmt->msadpcm.numcoeffs) ;
279
280
13.6k
        psf_log_printf (psf, "    Index   Coeffs1   Coeffs2\n") ;
281
41.5k
        for (k = 0 ; k < wav_fmt->msadpcm.numcoeffs ; k++)
282
27.9k
        { char buffer [128] ;
283
284
27.9k
          bytesread +=
285
27.9k
            psf_binheader_readf (psf, "22", &(wav_fmt->msadpcm.coeffs [k].coeff1), &(wav_fmt->msadpcm.coeffs [k].coeff2)) ;
286
27.9k
          snprintf (buffer, sizeof (buffer), "     %2d     %7d   %7d\n", k, wav_fmt->msadpcm.coeffs [k].coeff1, wav_fmt->msadpcm.coeffs [k].coeff2) ;
287
27.9k
          psf_log_printf (psf, buffer) ;
288
27.9k
          } ;
289
13.6k
        break ;
290
291
9.68k
    case WAVE_FORMAT_GSM610 :
292
9.68k
        if (wav_fmt->gsm610.channels != 1 || wav_fmt->gsm610.blockalign != 65)
293
16
          return SFE_WAV_GSM610_FORMAT ;
294
295
9.66k
        bytesread +=
296
9.66k
        psf_binheader_readf (psf, "22", &(wav_fmt->gsm610.extrabytes), &(wav_fmt->gsm610.samplesperblock)) ;
297
298
9.66k
        if (wav_fmt->gsm610.samplesperblock != 320)
299
2
          return SFE_WAV_GSM610_FORMAT ;
300
301
9.66k
        bytespersec = (wav_fmt->gsm610.samplerate * wav_fmt->gsm610.blockalign) / wav_fmt->gsm610.samplesperblock ;
302
9.66k
        if (wav_fmt->gsm610.bytespersec != (unsigned) bytespersec)
303
7.52k
          psf_log_printf (psf, "  Bytes/sec     : %d (should be %d)\n", wav_fmt->gsm610.bytespersec, bytespersec) ;
304
2.14k
        else
305
2.14k
          psf_log_printf (psf, "  Bytes/sec     : %d\n", wav_fmt->gsm610.bytespersec) ;
306
307
9.66k
        psf_log_printf (psf, "  Extra Bytes   : %d\n", wav_fmt->gsm610.extrabytes) ;
308
9.66k
        psf_log_printf (psf, "  Samples/Block : %d\n", wav_fmt->gsm610.samplesperblock) ;
309
9.66k
        break ;
310
311
9.71k
    case WAVE_FORMAT_MPEGLAYER3 :
312
9.71k
        bytesread += psf_binheader_readf (psf, "24222", &(wav_fmt->mpeg3.extrabytes),
313
9.71k
          &(wav_fmt->mpeg3.id), &(wav_fmt->mpeg3.flags), &(wav_fmt->mpeg3.blocksize),
314
9.71k
          &(wav_fmt->mpeg3.samplesperblock), &(wav_fmt->mpeg3.codecdelay)) ;
315
316
9.71k
        psf_log_printf (psf, "  Bytes/sec     : %d\n", wav_fmt->mpeg3.bytespersec) ;
317
9.71k
        psf_log_printf (psf, "  Extra Bytes   : %d\n", wav_fmt->mpeg3.extrabytes) ;
318
9.71k
        if (wav_fmt->mpeg3.id != 1)
319
7.09k
          psf_log_printf (psf, "  ID            : %d (unknown, should be 1)\n", wav_fmt->mpeg3.id) ;
320
2.61k
        else
321
2.61k
          psf_log_printf (psf, "  ID            : MPEGLAYER3_ID_MPEG\n") ;
322
9.71k
        psf_log_printf (psf, "  Flags         : 0x%08x\n", wav_fmt->mpeg3.flags) ;
323
9.71k
        psf_log_printf (psf, "  Block Size    : %d\n", wav_fmt->mpeg3.blocksize) ;
324
9.71k
        psf_log_printf (psf, "  Samples/Block : %d\n", wav_fmt->mpeg3.samplesperblock) ;
325
9.71k
        psf_log_printf (psf, "  Codec Delay   : %d samples\n", wav_fmt->mpeg3.codecdelay) ;
326
9.71k
        break ;
327
328
30.4k
    case WAVE_FORMAT_EXTENSIBLE :
329
30.4k
        if (wav_fmt->ext.bytespersec != wav_fmt->ext.samplerate * wav_fmt->ext.blockalign)
330
23.8k
          psf_log_printf (psf, "  Bytes/sec     : %d (should be %d)\n", wav_fmt->ext.bytespersec, wav_fmt->ext.samplerate * wav_fmt->ext.blockalign) ;
331
6.63k
        else
332
6.63k
          psf_log_printf (psf, "  Bytes/sec     : %d\n", wav_fmt->ext.bytespersec) ;
333
334
30.4k
        bytesread +=
335
30.4k
        psf_binheader_readf (psf, "224", &(wav_fmt->ext.extrabytes), &(wav_fmt->ext.validbits),
336
30.4k
            &(wav_fmt->ext.channelmask)) ;
337
338
30.4k
        psf_log_printf (psf, "  Valid Bits    : %d\n", wav_fmt->ext.validbits) ;
339
340
30.4k
        if (wav_fmt->ext.channelmask == 0)
341
6.13k
          psf_log_printf (psf, "  Channel Mask  : 0x0 (should not be zero)\n") ;
342
24.3k
        else
343
24.3k
        { char buffer [512] ;
344
24.3k
          unsigned bit ;
345
346
24.3k
          wpriv->wavex_channelmask = wav_fmt->ext.channelmask ;
347
348
          /* It's probably wise to ignore the channel mask if it is all zero */
349
24.3k
          free (psf->channel_map) ;
350
351
24.3k
          if ((psf->channel_map = calloc (psf->sf.channels, sizeof (psf->channel_map [0]))) == NULL)
352
0
            return SFE_MALLOC_FAILED ;
353
354
          /* Terminate the buffer we're going to append_snprintf into. */
355
24.3k
          buffer [0] = 0 ;
356
357
243k
          for (bit = k = 0 ; bit < ARRAY_LEN (channel_mask_bits) && k < psf->sf.channels ; bit++)
358
219k
          {
359
219k
            if (wav_fmt->ext.channelmask & (1 << bit))
360
64.0k
            { if (k > psf->sf.channels)
361
0
              { psf_log_printf (psf, "*** More channel map bits than there are channels.\n") ;
362
0
                break ;
363
64.0k
                } ;
364
365
64.0k
              psf->channel_map [k++] = channel_mask_bits [bit].id ;
366
64.0k
              append_snprintf (buffer, sizeof (buffer), "%s, ", channel_mask_bits [bit].name) ;
367
219k
              } ;
368
219k
            } ;
369
370
          /* Remove trailing ", ". */
371
24.3k
          bit = strlen (buffer) ;
372
24.3k
          if (bit >= 2)
373
14.4k
          { buffer [--bit] = 0 ;
374
14.4k
            buffer [--bit] = 0 ;
375
14.4k
            } ;
376
377
24.3k
          if (k != psf->sf.channels)
378
10.1k
          { psf_log_printf (psf, "  Channel Mask  : 0x%X\n", wav_fmt->ext.channelmask) ;
379
10.1k
            psf_log_printf (psf, "*** Less channel map bits than there are channels.\n") ;
380
10.1k
            }
381
14.1k
          else
382
14.1k
            psf_log_printf (psf, "  Channel Mask  : 0x%X (%s)\n", wav_fmt->ext.channelmask, buffer) ;
383
30.4k
          } ;
384
385
30.4k
        bytesread += psf_binheader_readf (psf, "422", &(wav_fmt->ext.esf.esf_field1), &(wav_fmt->ext.esf.esf_field2), &(wav_fmt->ext.esf.esf_field3)) ;
386
387
        /* compare the esf_fields with each known GUID? and print? */
388
30.4k
        psf_log_printf (psf, "  Subformat\n") ;
389
30.4k
        psf_log_printf (psf, "    esf_field1 : 0x%X\n", wav_fmt->ext.esf.esf_field1) ;
390
30.4k
        psf_log_printf (psf, "    esf_field2 : 0x%X\n", wav_fmt->ext.esf.esf_field2) ;
391
30.4k
        psf_log_printf (psf, "    esf_field3 : 0x%X\n", wav_fmt->ext.esf.esf_field3) ;
392
30.4k
        psf_log_printf (psf, "    esf_field4 : ") ;
393
274k
        for (k = 0 ; k < 8 ; k++)
394
243k
        { bytesread += psf_binheader_readf (psf, "1", &(wav_fmt->ext.esf.esf_field4 [k])) ;
395
243k
          psf_log_printf (psf, "0x%X ", wav_fmt->ext.esf.esf_field4 [k] & 0xFF) ;
396
243k
          } ;
397
30.4k
        psf_log_printf (psf, "\n") ;
398
30.4k
        psf->bytewidth = BITWIDTH2BYTES (wav_fmt->ext.bitwidth) ;
399
400
        /* Compare GUIDs for known ones. */
401
30.4k
        if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_PCM))
402
6.05k
        { psf->sf.format = SF_FORMAT_WAVEX | u_bitwidth_to_subformat (psf->bytewidth * 8) ;
403
6.05k
          psf_log_printf (psf, "    format : pcm\n") ;
404
6.05k
          }
405
24.4k
        else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_MS_ADPCM))
406
2.88k
        { psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_MS_ADPCM) ;
407
2.88k
          psf_log_printf (psf, "    format : ms adpcm\n") ;
408
2.88k
          }
409
21.5k
        else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_IEEE_FLOAT))
410
3.42k
        { psf->sf.format = SF_FORMAT_WAVEX | ((psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT) ;
411
3.42k
          psf_log_printf (psf, "    format : IEEE float\n") ;
412
3.42k
          }
413
18.1k
        else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_ALAW))
414
3.82k
        { psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_ALAW) ;
415
3.82k
          psf_log_printf (psf, "    format : A-law\n") ;
416
3.82k
          }
417
14.2k
        else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_MULAW))
418
3.41k
        { psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_ULAW) ;
419
3.41k
          psf_log_printf (psf, "    format : u-law\n") ;
420
3.41k
          }
421
10.8k
        else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM))
422
5.29k
        { psf->sf.format = SF_FORMAT_WAVEX | u_bitwidth_to_subformat (psf->bytewidth * 8) ;
423
5.29k
          psf_log_printf (psf, "    format : pcm (Ambisonic B)\n") ;
424
5.29k
          wpriv->wavex_ambisonic = SF_AMBISONIC_B_FORMAT ;
425
5.29k
          }
426
5.56k
        else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT))
427
5.30k
        { psf->sf.format = SF_FORMAT_WAVEX | ((psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT) ;
428
5.30k
          psf_log_printf (psf, "    format : IEEE float (Ambisonic B)\n") ;
429
5.30k
          wpriv->wavex_ambisonic = SF_AMBISONIC_B_FORMAT ;
430
5.30k
          }
431
259
        else
432
259
          return SFE_UNIMPLEMENTED ;
433
434
30.2k
        break ;
435
436
30.2k
    case WAVE_FORMAT_G721_ADPCM :
437
13.0k
        psf_log_printf (psf, "  Bytes/sec     : %d\n", wav_fmt->g72x.bytespersec) ;
438
13.0k
        if (fmtsize >= 20)
439
8.10k
        { bytesread += psf_binheader_readf (psf, "22", &(wav_fmt->g72x.extrabytes), &(wav_fmt->g72x.auxblocksize)) ;
440
8.10k
          if (wav_fmt->g72x.extrabytes == 0)
441
3.13k
            psf_log_printf (psf, "  Extra Bytes   : %d (should be 2)\n", wav_fmt->g72x.extrabytes) ;
442
4.96k
          else
443
4.96k
            psf_log_printf (psf, "  Extra Bytes   : %d\n", wav_fmt->g72x.extrabytes) ;
444
8.10k
          psf_log_printf (psf, "  Aux Blk Size  : %d\n", wav_fmt->g72x.auxblocksize) ;
445
8.10k
          }
446
4.95k
        else if (fmtsize == 18)
447
2.63k
        { bytesread += psf_binheader_readf (psf, "2", &(wav_fmt->g72x.extrabytes)) ;
448
2.63k
          psf_log_printf (psf, "  Extra Bytes   : %d%s\n", wav_fmt->g72x.extrabytes, wav_fmt->g72x.extrabytes != 0 ? " (should be 0)" : "") ;
449
2.63k
          }
450
2.32k
        else
451
2.32k
          psf_log_printf (psf, "*** 'fmt ' chunk should be bigger than this!\n") ;
452
13.0k
        break ;
453
454
9.88k
    case WAVE_FORMAT_NMS_VBXADPCM :
455
9.88k
        if (wav_fmt->min.channels != 1 || wav_fmt->min.bitwidth < 2 || wav_fmt->min.bitwidth * 20 + 2 != wav_fmt->min.blockalign)
456
20
          return SFE_WAV_NMS_FORMAT ;
457
458
9.86k
        bytespersec = (wav_fmt->min.samplerate * wav_fmt->min.blockalign) / 160 ;
459
9.86k
        if (wav_fmt->min.bytespersec == (unsigned) bytespersec)
460
3.29k
          psf_log_printf (psf, "  Bytes/sec     : %d\n", wav_fmt->min.bytespersec) ;
461
6.56k
        else
462
6.56k
          psf_log_printf (psf, "  Bytes/sec     : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ;
463
9.86k
        if (fmtsize >= 18)
464
5.41k
        { bytesread += psf_binheader_readf (psf, "2", &(wav_fmt->size20.extrabytes)) ;
465
5.41k
          psf_log_printf (psf, "  Extra Bytes   : %d\n", wav_fmt->size20.extrabytes) ;
466
5.41k
          } ;
467
9.86k
        break ;
468
469
92
    default :
470
92
        psf_log_printf (psf, "*** No 'fmt ' chunk dumper for this format!\n") ;
471
92
        return SFE_WAV_BAD_FMT ;
472
160k
    } ;
473
474
160k
  if (bytesread > fmtsize)
475
16
  { psf_log_printf (psf, "*** wavlike_read_fmt_chunk (bytesread > fmtsize)\n") ;
476
16
    return SFE_WAV_BAD_FMT ;
477
16
    }
478
160k
  else
479
160k
    psf_binheader_readf (psf, "j", fmtsize - bytesread) ;
480
481
160k
  psf->blockwidth = wav_fmt->min.channels * psf->bytewidth ;
482
483
160k
  return 0 ;
484
160k
} /* wavlike_read_fmt_chunk */
485
486
void
487
wavlike_write_guid (SF_PRIVATE *psf, const EXT_SUBFORMAT * subformat)
488
0
{
489
0
  psf_binheader_writef (psf, "422b", BHW4 (subformat->esf_field1),
490
0
          BHW2 (subformat->esf_field2), BHW2 (subformat->esf_field3),
491
0
          BHWv (subformat->esf_field4), BHWz (8)) ;
492
0
} /* wavlike_write_guid */
493
494
495
int
496
wavlike_gen_channel_mask (const int *chan_map, int channels)
497
0
{ int chan, mask = 0, bit = -1, last_bit = -1 ;
498
499
0
  if (chan_map == NULL)
500
0
    return 0 ;
501
502
0
  for (chan = 0 ; chan < channels ; chan ++)
503
0
  { int k ;
504
505
0
    for (k = bit + 1 ; k < ARRAY_LEN (channel_mask_bits) ; k++)
506
0
      if (chan_map [chan] == channel_mask_bits [k].id)
507
0
      { bit = k ;
508
0
        break ;
509
0
        } ;
510
511
    /* Check for bad sequence. */
512
0
    if (bit <= last_bit)
513
0
      return 0 ;
514
515
0
    mask += 1 << bit ;
516
0
    last_bit = bit ;
517
0
    } ;
518
519
0
  return mask ;
520
0
} /* wavlike_gen_channel_mask */
521
522
void
523
wavlike_analyze (SF_PRIVATE *psf)
524
52
{ unsigned char buffer [4096] ;
525
52
  AUDIO_DETECT ad ;
526
52
  int format = 0 ;
527
528
52
  if (psf->is_pipe)
529
0
  { psf_log_printf (psf, "*** Error : Reading from a pipe. Can't analyze data section to figure out real data format.\n\n") ;
530
0
    return ;
531
52
    } ;
532
533
52
  psf_log_printf (psf, "---------------------------------------------------\n"
534
52
            "Format is known to be broken. Using detection code.\n") ;
535
536
  /* Code goes here. */
537
52
  ad.endianness = SF_ENDIAN_LITTLE ;
538
52
  ad.channels = psf->sf.channels ;
539
540
52
  psf_fseek (psf, 3 * 4 * 50, SEEK_SET) ;
541
542
2.20k
  while (psf_fread (buffer, 1, sizeof (buffer), psf) == sizeof (buffer))
543
2.16k
  { format = audio_detect (psf, &ad, buffer, sizeof (buffer)) ;
544
2.16k
    if (format != 0)
545
15
      break ;
546
2.16k
    } ;
547
548
  /* Seek to start of DATA section. */
549
52
  psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
550
551
52
  if (format == 0)
552
37
  { psf_log_printf (psf, "wavlike_analyze : detection failed.\n") ;
553
37
    return ;
554
37
    } ;
555
556
15
  switch (format)
557
15
  { case SF_FORMAT_PCM_32 :
558
15
    case SF_FORMAT_FLOAT :
559
15
      psf_log_printf (psf, "wavlike_analyze : found format : 0x%X\n", format) ;
560
15
      psf->sf.format = (psf->sf.format & ~SF_FORMAT_SUBMASK) + format ;
561
15
      psf->bytewidth = 4 ;
562
15
      psf->blockwidth = psf->sf.channels * psf->bytewidth ;
563
15
      break ;
564
565
0
    case SF_FORMAT_PCM_24 :
566
0
      psf_log_printf (psf, "wavlike_analyze : found format : 0x%X\n", format) ;
567
0
      psf->sf.format = (psf->sf.format & ~SF_FORMAT_SUBMASK) + format ;
568
0
      psf->bytewidth = 3 ;
569
0
      psf->blockwidth = psf->sf.channels * psf->bytewidth ;
570
0
      break ;
571
572
0
    default :
573
0
      psf_log_printf (psf, "wavlike_analyze : unhandled format : 0x%X\n", format) ;
574
0
      break ;
575
15
    } ;
576
577
15
  return ;
578
15
} /* wavlike_analyze */
579
580
/*==============================================================================
581
*/
582
583
typedef struct
584
{ int     ID ;
585
  const char  *name ;
586
} WAV_FORMAT_DESC ;
587
588
#define STR(x)      #x
589
#define FORMAT_TYPE(x)  { x, STR (x) }
590
591
static WAV_FORMAT_DESC wave_descs [] =
592
{ FORMAT_TYPE (WAVE_FORMAT_PCM),
593
  FORMAT_TYPE (WAVE_FORMAT_MS_ADPCM),
594
  FORMAT_TYPE (WAVE_FORMAT_IEEE_FLOAT),
595
  FORMAT_TYPE (WAVE_FORMAT_VSELP),
596
  FORMAT_TYPE (WAVE_FORMAT_IBM_CVSD),
597
  FORMAT_TYPE (WAVE_FORMAT_ALAW),
598
  FORMAT_TYPE (WAVE_FORMAT_MULAW),
599
  FORMAT_TYPE (WAVE_FORMAT_OKI_ADPCM),
600
  FORMAT_TYPE (WAVE_FORMAT_IMA_ADPCM),
601
  FORMAT_TYPE (WAVE_FORMAT_MEDIASPACE_ADPCM),
602
  FORMAT_TYPE (WAVE_FORMAT_SIERRA_ADPCM),
603
  FORMAT_TYPE (WAVE_FORMAT_G723_ADPCM),
604
  FORMAT_TYPE (WAVE_FORMAT_DIGISTD),
605
  FORMAT_TYPE (WAVE_FORMAT_DIGIFIX),
606
  FORMAT_TYPE (WAVE_FORMAT_DIALOGIC_OKI_ADPCM),
607
  FORMAT_TYPE (WAVE_FORMAT_MEDIAVISION_ADPCM),
608
  FORMAT_TYPE (WAVE_FORMAT_CU_CODEC),
609
  FORMAT_TYPE (WAVE_FORMAT_YAMAHA_ADPCM),
610
  FORMAT_TYPE (WAVE_FORMAT_SONARC),
611
  FORMAT_TYPE (WAVE_FORMAT_DSPGROUP_TRUESPEECH),
612
  FORMAT_TYPE (WAVE_FORMAT_ECHOSC1),
613
  FORMAT_TYPE (WAVE_FORMAT_AUDIOFILE_AF36),
614
  FORMAT_TYPE (WAVE_FORMAT_APTX),
615
  FORMAT_TYPE (WAVE_FORMAT_AUDIOFILE_AF10),
616
  FORMAT_TYPE (WAVE_FORMAT_PROSODY_1612),
617
  FORMAT_TYPE (WAVE_FORMAT_LRC),
618
  FORMAT_TYPE (WAVE_FORMAT_DOLBY_AC2),
619
  FORMAT_TYPE (WAVE_FORMAT_GSM610),
620
  FORMAT_TYPE (WAVE_FORMAT_MSNAUDIO),
621
  FORMAT_TYPE (WAVE_FORMAT_ANTEX_ADPCME),
622
  FORMAT_TYPE (WAVE_FORMAT_CONTROL_RES_VQLPC),
623
  FORMAT_TYPE (WAVE_FORMAT_DIGIREAL),
624
  FORMAT_TYPE (WAVE_FORMAT_DIGIADPCM),
625
  FORMAT_TYPE (WAVE_FORMAT_CONTROL_RES_CR10),
626
  FORMAT_TYPE (WAVE_FORMAT_NMS_VBXADPCM),
627
  FORMAT_TYPE (WAVE_FORMAT_ROLAND_RDAC),
628
  FORMAT_TYPE (WAVE_FORMAT_ECHOSC3),
629
  FORMAT_TYPE (WAVE_FORMAT_ROCKWELL_ADPCM),
630
  FORMAT_TYPE (WAVE_FORMAT_ROCKWELL_DIGITALK),
631
  FORMAT_TYPE (WAVE_FORMAT_XEBEC),
632
  FORMAT_TYPE (WAVE_FORMAT_G721_ADPCM),
633
  FORMAT_TYPE (WAVE_FORMAT_G728_CELP),
634
  FORMAT_TYPE (WAVE_FORMAT_MSG723),
635
  FORMAT_TYPE (WAVE_FORMAT_MPEG),
636
  FORMAT_TYPE (WAVE_FORMAT_RT24),
637
  FORMAT_TYPE (WAVE_FORMAT_PAC),
638
  FORMAT_TYPE (WAVE_FORMAT_MPEGLAYER3),
639
  FORMAT_TYPE (WAVE_FORMAT_LUCENT_G723),
640
  FORMAT_TYPE (WAVE_FORMAT_CIRRUS),
641
  FORMAT_TYPE (WAVE_FORMAT_ESPCM),
642
  FORMAT_TYPE (WAVE_FORMAT_VOXWARE),
643
  FORMAT_TYPE (WAVE_FORMAT_CANOPUS_ATRAC),
644
  FORMAT_TYPE (WAVE_FORMAT_G726_ADPCM),
645
  FORMAT_TYPE (WAVE_FORMAT_G722_ADPCM),
646
  FORMAT_TYPE (WAVE_FORMAT_DSAT),
647
  FORMAT_TYPE (WAVE_FORMAT_DSAT_DISPLAY),
648
  FORMAT_TYPE (WAVE_FORMAT_VOXWARE_BYTE_ALIGNED),
649
  FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC8),
650
  FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC10),
651
  FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC16),
652
  FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC20),
653
  FORMAT_TYPE (WAVE_FORMAT_VOXWARE_RT24),
654
  FORMAT_TYPE (WAVE_FORMAT_VOXWARE_RT29),
655
  FORMAT_TYPE (WAVE_FORMAT_VOXWARE_RT29HW),
656
  FORMAT_TYPE (WAVE_FORMAT_VOXWARE_VR12),
657
  FORMAT_TYPE (WAVE_FORMAT_VOXWARE_VR18),
658
  FORMAT_TYPE (WAVE_FORMAT_VOXWARE_TQ40),
659
  FORMAT_TYPE (WAVE_FORMAT_SOFTSOUND),
660
  FORMAT_TYPE (WAVE_FORMAT_VOXARE_TQ60),
661
  FORMAT_TYPE (WAVE_FORMAT_MSRT24),
662
  FORMAT_TYPE (WAVE_FORMAT_G729A),
663
  FORMAT_TYPE (WAVE_FORMAT_MVI_MV12),
664
  FORMAT_TYPE (WAVE_FORMAT_DF_G726),
665
  FORMAT_TYPE (WAVE_FORMAT_DF_GSM610),
666
  FORMAT_TYPE (WAVE_FORMAT_ONLIVE),
667
  FORMAT_TYPE (WAVE_FORMAT_SBC24),
668
  FORMAT_TYPE (WAVE_FORMAT_DOLBY_AC3_SPDIF),
669
  FORMAT_TYPE (WAVE_FORMAT_ZYXEL_ADPCM),
670
  FORMAT_TYPE (WAVE_FORMAT_PHILIPS_LPCBB),
671
  FORMAT_TYPE (WAVE_FORMAT_PACKED),
672
  FORMAT_TYPE (WAVE_FORMAT_RHETOREX_ADPCM),
673
  FORMAT_TYPE (IBM_FORMAT_MULAW),
674
  FORMAT_TYPE (IBM_FORMAT_ALAW),
675
  FORMAT_TYPE (IBM_FORMAT_ADPCM),
676
  FORMAT_TYPE (WAVE_FORMAT_VIVO_G723),
677
  FORMAT_TYPE (WAVE_FORMAT_VIVO_SIREN),
678
  FORMAT_TYPE (WAVE_FORMAT_DIGITAL_G723),
679
  FORMAT_TYPE (WAVE_FORMAT_CREATIVE_ADPCM),
680
  FORMAT_TYPE (WAVE_FORMAT_CREATIVE_FASTSPEECH8),
681
  FORMAT_TYPE (WAVE_FORMAT_CREATIVE_FASTSPEECH10),
682
  FORMAT_TYPE (WAVE_FORMAT_QUARTERDECK),
683
  FORMAT_TYPE (WAVE_FORMAT_FM_TOWNS_SND),
684
  FORMAT_TYPE (WAVE_FORMAT_BZV_DIGITAL),
685
  FORMAT_TYPE (WAVE_FORMAT_VME_VMPCM),
686
  FORMAT_TYPE (WAVE_FORMAT_OLIGSM),
687
  FORMAT_TYPE (WAVE_FORMAT_OLIADPCM),
688
  FORMAT_TYPE (WAVE_FORMAT_OLICELP),
689
  FORMAT_TYPE (WAVE_FORMAT_OLISBC),
690
  FORMAT_TYPE (WAVE_FORMAT_OLIOPR),
691
  FORMAT_TYPE (WAVE_FORMAT_LH_CODEC),
692
  FORMAT_TYPE (WAVE_FORMAT_NORRIS),
693
  FORMAT_TYPE (WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS),
694
  FORMAT_TYPE (WAVE_FORMAT_DVM),
695
  FORMAT_TYPE (WAVE_FORMAT_INTERWAV_VSC112),
696
  FORMAT_TYPE (WAVE_FORMAT_IPP_ITU_G_723_1),
697
  FORMAT_TYPE (WAVE_FORMAT_EXTENSIBLE),
698
} ;
699
700
char const*
701
wavlike_format_str (int k)
702
160k
{ int lower, upper, mid ;
703
704
160k
  lower = -1 ;
705
160k
  upper = sizeof (wave_descs) / sizeof (WAV_FORMAT_DESC) ;
706
707
  /* binary search */
708
160k
  if ((wave_descs [0].ID <= k) && (k <= wave_descs [upper - 1].ID))
709
160k
  {
710
968k
    while (lower + 1 < upper)
711
968k
    { mid = (upper + lower) / 2 ;
712
713
968k
      if (k == wave_descs [mid].ID)
714
160k
        return wave_descs [mid].name ;
715
807k
      if (k < wave_descs [mid].ID)
716
492k
        upper = mid ;
717
315k
      else
718
315k
        lower = mid ;
719
807k
      } ;
720
83
    } ;
721
722
83
  return "Unknown format" ;
723
160k
} /* wavlike_format_str */
724
725
int
726
wavlike_srate2blocksize (int srate_chan_product)
727
0
{ if (srate_chan_product < 12000)
728
0
    return 256 ;
729
0
  if (srate_chan_product < 23000)
730
0
    return 512 ;
731
0
  if (srate_chan_product < 44000)
732
0
    return 1024 ;
733
0
  return 2048 ;
734
0
} /* srate2blocksize */
735
736
int
737
wavlike_read_bext_chunk (SF_PRIVATE *psf, uint32_t chunksize)
738
827
{
739
827
  SF_BROADCAST_INFO_16K * b ;
740
827
  uint32_t bytes = 0 ;
741
742
827
  if (chunksize < WAV_BEXT_MIN_CHUNK_SIZE)
743
688
  { psf_log_printf (psf, "bext : %u (should be >= %d)\n", chunksize, WAV_BEXT_MIN_CHUNK_SIZE) ;
744
688
    psf_binheader_readf (psf, "j", chunksize) ;
745
688
    return 0 ;
746
688
    } ;
747
748
139
  if (chunksize > WAV_BEXT_MAX_CHUNK_SIZE)
749
34
  { psf_log_printf (psf, "bext : %u (should be < %d)\n", chunksize, WAV_BEXT_MAX_CHUNK_SIZE) ;
750
34
    psf_binheader_readf (psf, "j", chunksize) ;
751
34
    return 0 ;
752
105
    } ;
753
754
105
  if (chunksize >= sizeof (SF_BROADCAST_INFO_16K))
755
0
  { psf_log_printf (psf, "bext : %u too big to be handled\n", chunksize) ;
756
0
    psf_binheader_readf (psf, "j", chunksize) ;
757
0
    return 0 ;
758
105
    } ;
759
760
105
  psf_log_printf (psf, "bext : %u\n", chunksize) ;
761
762
105
  if (!psf->broadcast_16k)
763
17
  { psf->broadcast_16k = broadcast_var_alloc () ;
764
17
    if (!psf->broadcast_16k)
765
0
    { psf->error = SFE_MALLOC_FAILED ;
766
0
      return psf->error ;
767
0
      }
768
17
    }
769
88
  else
770
88
  { psf_log_printf (psf, "bext : found more than one bext chunk, using last one.\n") ;
771
88
    memset (psf->broadcast_16k, 0, sizeof (SF_BROADCAST_INFO_16K)) ;
772
88
    }
773
774
105
  b = psf->broadcast_16k ;
775
776
105
  bytes += psf_binheader_readf (psf, "b", b->description, sizeof (b->description)) ;
777
105
  bytes += psf_binheader_readf (psf, "b", b->originator, sizeof (b->originator)) ;
778
105
  bytes += psf_binheader_readf (psf, "b", b->originator_reference, sizeof (b->originator_reference)) ;
779
105
  bytes += psf_binheader_readf (psf, "b", b->origination_date, sizeof (b->origination_date)) ;
780
105
  bytes += psf_binheader_readf (psf, "b", b->origination_time, sizeof (b->origination_time)) ;
781
105
  bytes += psf_binheader_readf (psf, "442", &b->time_reference_low, &b->time_reference_high, &b->version) ;
782
105
  bytes += psf_binheader_readf (psf, "b", &b->umid, sizeof (b->umid)) ;
783
105
  bytes += psf_binheader_readf (psf, "22", &b->loudness_value, &b->loudness_range) ;
784
105
  bytes += psf_binheader_readf (psf, "222", &b->max_true_peak_level, &b->max_momentary_loudness, &b->max_shortterm_loudness) ;
785
105
  bytes += psf_binheader_readf (psf, "j", 180) ;
786
787
105
  if (chunksize > WAV_BEXT_MIN_CHUNK_SIZE)
788
104
  { /* File has coding history data. */
789
790
104
    b->coding_history_size = chunksize - WAV_BEXT_MIN_CHUNK_SIZE ;
791
792
    /* We do not parse the coding history */
793
104
    bytes += psf_binheader_readf (psf, "b", BHWv (b->coding_history), BHWz (b->coding_history_size)) ;
794
104
    } ;
795
796
105
  if (bytes < chunksize)
797
14
    psf_binheader_readf (psf, "j", BHWj (chunksize - bytes)) ;
798
799
105
  return 0 ;
800
105
} /* wavlike_read_bext_chunk */
801
802
int
803
wavlike_write_bext_chunk (SF_PRIVATE *psf)
804
0
{ SF_BROADCAST_INFO_16K *b ;
805
806
0
  if (psf->broadcast_16k == NULL)
807
0
    return -1 ;
808
809
0
  b = psf->broadcast_16k ;
810
811
0
  psf_binheader_writef (psf, "m4", BHWm (bext_MARKER), BHW4 (WAV_BEXT_MIN_CHUNK_SIZE + b->coding_history_size)) ;
812
813
  /*
814
  **  Note that it is very important that the field widths of the SF_BROADCAST_INFO
815
  **  struct match those of the bext chunk fields.
816
  */
817
818
0
  psf_binheader_writef (psf, "b", BHWv (b->description), BHWz (sizeof (b->description))) ;
819
0
  psf_binheader_writef (psf, "b", BHWv (b->originator), BHWz (sizeof (b->originator))) ;
820
0
  psf_binheader_writef (psf, "b", BHWv (b->originator_reference), BHWz (sizeof (b->originator_reference))) ;
821
0
  psf_binheader_writef (psf, "b", BHWv (b->origination_date), BHWz (sizeof (b->origination_date))) ;
822
0
  psf_binheader_writef (psf, "b", BHWv (b->origination_time), BHWz (sizeof (b->origination_time))) ;
823
0
  psf_binheader_writef (psf, "442", BHW4 (b->time_reference_low), BHW4 (b->time_reference_high), BHW2 (b->version)) ;
824
0
  psf_binheader_writef (psf, "b", BHWv (b->umid), BHWz (sizeof (b->umid))) ;
825
0
  psf_binheader_writef (psf, "22", BHW2 (b->loudness_value), BHW2 (b->loudness_range)) ;
826
0
  psf_binheader_writef (psf, "222", BHW2 (b->max_true_peak_level), BHW2 (b->max_momentary_loudness), BHW2 (b->max_shortterm_loudness)) ;
827
0
  psf_binheader_writef (psf, "z", BHWz (180)) ;
828
829
0
  if (b->coding_history_size > 0)
830
0
    psf_binheader_writef (psf, "b", BHWv (b->coding_history), BHWz (b->coding_history_size)) ;
831
832
0
  return 0 ;
833
0
} /* wavlike_write_bext_chunk */
834
835
int
836
wavlike_read_cart_chunk (SF_PRIVATE *psf, uint32_t chunksize)
837
3.01k
{ SF_CART_INFO_16K *c ;
838
3.01k
  uint32_t bytes = 0 ;
839
3.01k
  int k ;
840
841
3.01k
  if (chunksize < WAV_CART_MIN_CHUNK_SIZE)
842
2.81k
  { psf_log_printf (psf, "cart : %u (should be >= %d)\n", chunksize, WAV_CART_MIN_CHUNK_SIZE) ;
843
2.81k
    psf_binheader_readf (psf, "j", chunksize) ;
844
2.81k
    return 0 ;
845
2.81k
    } ;
846
203
  if (chunksize > WAV_CART_MAX_CHUNK_SIZE)
847
0
  { psf_log_printf (psf, "cart : %u (should be < %d)\n", chunksize, WAV_CART_MAX_CHUNK_SIZE) ;
848
0
    psf_binheader_readf (psf, "j", chunksize) ;
849
0
    return 0 ;
850
203
    } ;
851
852
  /*
853
  **  SF_CART_INFO_16K has an extra field 'tag_text_size' that isn't part
854
  **  of the chunk, so don't include it in the size check.
855
  */
856
203
  if (chunksize >= sizeof (SF_CART_INFO_16K) - 4)
857
40
  { psf_log_printf (psf, "cart : %u too big to be handled\n", chunksize) ;
858
40
    psf_binheader_readf (psf, "j", chunksize) ;
859
40
    return 0 ;
860
163
    } ;
861
862
163
  psf_log_printf (psf, "cart : %u\n", chunksize) ;
863
864
163
  if (psf->cart_16k)
865
130
  { psf_log_printf (psf, "  Found more than one cart chunk, using last one.\n") ;
866
130
    free (psf->cart_16k) ;
867
130
    psf->cart_16k = NULL ;
868
130
    } ;
869
870
163
  if ((psf->cart_16k = cart_var_alloc ()) == NULL)
871
0
  { psf->error = SFE_MALLOC_FAILED ;
872
0
    return psf->error ;
873
163
    } ;
874
875
163
  c = psf->cart_16k ;
876
163
  bytes += psf_binheader_readf (psf, "b", c->version, sizeof (c->version)) ;
877
163
  bytes += psf_binheader_readf (psf, "b", c->title, sizeof (c->title)) ;
878
163
  bytes += psf_binheader_readf (psf, "b", c->artist, sizeof (c->artist)) ;
879
163
  bytes += psf_binheader_readf (psf, "b", c->cut_id, sizeof (c->cut_id)) ;
880
163
  bytes += psf_binheader_readf (psf, "b", c->client_id, sizeof (c->client_id)) ;
881
163
  bytes += psf_binheader_readf (psf, "b", c->category, sizeof (c->category)) ;
882
163
  bytes += psf_binheader_readf (psf, "b", c->classification, sizeof (c->classification)) ;
883
163
  bytes += psf_binheader_readf (psf, "b", c->out_cue, sizeof (c->out_cue)) ;
884
163
  bytes += psf_binheader_readf (psf, "b", c->start_date, sizeof (c->start_date)) ;
885
163
  bytes += psf_binheader_readf (psf, "b", c->start_time, sizeof (c->start_time)) ;
886
163
  bytes += psf_binheader_readf (psf, "b", c->end_date, sizeof (c->end_date)) ;
887
163
  bytes += psf_binheader_readf (psf, "b", c->end_time, sizeof (c->end_time)) ;
888
163
  bytes += psf_binheader_readf (psf, "b", c->producer_app_id, sizeof (c->producer_app_id)) ;
889
163
  bytes += psf_binheader_readf (psf, "b", c->producer_app_version, sizeof (c->producer_app_version)) ;
890
163
  bytes += psf_binheader_readf (psf, "b", c->user_def, sizeof (c->user_def)) ;
891
163
  bytes += psf_binheader_readf (psf, "e4", &c->level_reference, sizeof (c->level_reference)) ;
892
893
1.46k
  for (k = 0 ; k < ARRAY_LEN (c->post_timers) ; k++)
894
1.30k
    bytes += psf_binheader_readf (psf, "b4", &c->post_timers [k].usage, make_size_t (4), &c->post_timers [k].value) ;
895
896
163
  bytes += psf_binheader_readf (psf, "b", c->reserved, sizeof (c->reserved)) ;
897
163
  bytes += psf_binheader_readf (psf, "b", c->url, sizeof (c->url)) ;
898
899
163
  if (chunksize > WAV_CART_MIN_CHUNK_SIZE)
900
110
  { /* File has tag text. */
901
110
    c->tag_text_size = chunksize - WAV_CART_MIN_CHUNK_SIZE ;
902
110
    bytes += psf_binheader_readf (psf, "b", c->tag_text, make_size_t (c->tag_text_size)) ;
903
110
    } ;
904
905
163
  if (bytes < chunksize)
906
30
    psf_log_printf (psf, "  %d trailing bytes in cart chunk.\n", chunksize - bytes) ;
907
908
163
  return 0 ;
909
163
} /* wavlike_read_cart_chunk */
910
911
int
912
wavlike_write_cart_chunk (SF_PRIVATE *psf)
913
0
{ SF_CART_INFO_16K *c ;
914
0
  int k ;
915
916
0
  if (psf->cart_16k == NULL)
917
0
    return -1 ;
918
919
0
  c = psf->cart_16k ;
920
0
  psf_binheader_writef (psf, "m4", BHWm (cart_MARKER), BHW4 (WAV_CART_MIN_CHUNK_SIZE + c->tag_text_size)) ;
921
  /*
922
  **  Note that it is very important that the field widths of the SF_CART_INFO
923
  **  struct match those of the cart chunk fields.
924
  */
925
0
  psf_binheader_writef (psf, "b", BHWv (c->version), BHWz (sizeof (c->version))) ;
926
0
  psf_binheader_writef (psf, "b", BHWv (c->title), BHWz (sizeof (c->title))) ;
927
0
  psf_binheader_writef (psf, "b", BHWv (c->artist), BHWz (sizeof (c->artist))) ;
928
0
  psf_binheader_writef (psf, "b", BHWv (c->cut_id), BHWz (sizeof (c->cut_id))) ;
929
0
  psf_binheader_writef (psf, "b", BHWv (c->client_id), BHWz (sizeof (c->client_id))) ;
930
0
  psf_binheader_writef (psf, "b", BHWv (c->category), BHWz (sizeof (c->category))) ;
931
0
  psf_binheader_writef (psf, "b", BHWv (c->classification), BHWz (sizeof (c->classification))) ;
932
0
  psf_binheader_writef (psf, "b", BHWv (c->out_cue), BHWz (sizeof (c->out_cue))) ;
933
0
  psf_binheader_writef (psf, "b", BHWv (c->start_date), BHWz (sizeof (c->start_date))) ;
934
0
  psf_binheader_writef (psf, "b", BHWv (c->start_time), BHWz (sizeof (c->start_time))) ;
935
0
  psf_binheader_writef (psf, "b", BHWv (c->end_date), BHWz (sizeof (c->end_date))) ;
936
0
  psf_binheader_writef (psf, "b", BHWv (c->end_time), BHWz (sizeof (c->end_time))) ;
937
0
  psf_binheader_writef (psf, "b", BHWv (c->producer_app_id), BHWz (sizeof (c->producer_app_id))) ;
938
0
  psf_binheader_writef (psf, "b", BHWv (c->producer_app_version), BHWz (sizeof (c->producer_app_version))) ;
939
0
  psf_binheader_writef (psf, "b", BHWv (c->user_def), BHWz (sizeof (c->user_def))) ;
940
0
  psf_binheader_writef (psf, "e4", BHW4 (c->level_reference)) ;
941
942
0
  for (k = 0 ; k < ARRAY_LEN (c->post_timers) ; k++)
943
0
    psf_binheader_writef (psf, "b4", BHWv (c->post_timers [k].usage), BHWz (4), BHW4 (c->post_timers [k].value)) ;
944
945
0
  psf_binheader_writef (psf, "z", BHWz (sizeof (c->reserved))) ;  // just write zeros, we don't have any other use for it
946
0
  psf_binheader_writef (psf, "b", BHWv (c->url), BHWz (sizeof (c->url))) ;
947
948
0
  if (c->tag_text_size > 0)
949
0
    psf_binheader_writef (psf, "b", BHWv (c->tag_text), BHWz (c->tag_text_size)) ;
950
951
0
  return 0 ;
952
0
} /* wavlike_write_cart_chunk */
953
954
int
955
wavlike_subchunk_parse (SF_PRIVATE *psf, int chunk, uint32_t chunk_length)
956
86.4k
{ sf_count_t  current_pos ;
957
86.4k
  char    buffer [2048] ;
958
86.4k
  uint32_t  chunk_size, bytesread = 0 ;
959
960
86.4k
  current_pos = psf_fseek (psf, 0, SEEK_CUR) ;
961
962
86.4k
  if (chunk_length <= 8)
963
1.24k
  { /* This case is for broken files generated by PEAK. */
964
1.24k
    psf_log_printf (psf, "%M : %u (weird length)\n", chunk, chunk_length) ;
965
1.24k
    psf_binheader_readf (psf, "mj", &chunk, chunk_length - 4) ;
966
1.24k
    psf_log_printf (psf, "  %M\n", chunk) ;
967
1.24k
    return 0 ;
968
85.1k
    } ;
969
970
85.1k
  if (current_pos + chunk_length > psf->filelength)
971
26.8k
  { psf_log_printf (psf, "%M : %u (should be %d)\n", chunk, chunk_length, (int) (psf->filelength - current_pos)) ;
972
26.8k
    chunk_length = psf->filelength - current_pos ;
973
26.8k
    }
974
58.3k
  else
975
58.3k
    psf_log_printf (psf, "%M : %u\n", chunk, chunk_length) ;
976
977
180k
  while (bytesread < chunk_length)
978
167k
  { uint32_t thisread ;
979
980
167k
    if ((thisread = psf_binheader_readf (psf, "m", &chunk)) == 0)
981
135
      break ;
982
167k
    bytesread += thisread ;
983
984
167k
    switch (chunk)
985
167k
    { case adtl_MARKER :
986
647
      case INFO_MARKER :
987
          /* These markers don't contain anything, not even a chunk length. */
988
647
          psf_log_printf (psf, "  %M\n", chunk) ;
989
647
          continue ;
990
991
26.5k
      case exif_MARKER :
992
26.5k
          psf_log_printf (psf, "  %M\n", chunk) ;
993
26.5k
          if (chunk_length > bytesread)
994
26.3k
            bytesread += exif_subchunk_parse (psf, chunk_length - bytesread) ;
995
26.5k
          continue ;
996
997
9.17k
      case data_MARKER :
998
9.17k
          psf_log_printf (psf, "  %M inside a LIST block??? Backing out.\n", chunk) ;
999
          /* Jump back four bytes and return to caller. */
1000
9.17k
          psf_binheader_readf (psf, "j", -4) ;
1001
9.17k
          return 0 ;
1002
1003
5.15k
      case 0 :
1004
          /*
1005
          **  Four zero bytes where a marker was expected. Assume this means
1006
          **  the rest of the chunk is garbage.
1007
          */
1008
5.15k
          psf_log_printf (psf, "    *** Found weird-ass zero marker. Jumping to end of chunk.\n") ;
1009
5.15k
          goto cleanup_subchunk_parse ;
1010
1011
125k
      default :
1012
125k
          break ;
1013
167k
      } ;
1014
1015
125k
    switch (chunk)
1016
125k
    { case ISFT_MARKER :
1017
2.69k
      case ICOP_MARKER :
1018
7.20k
      case IARL_MARKER :
1019
17.7k
      case IART_MARKER :
1020
26.3k
      case ICMT_MARKER :
1021
26.4k
      case ICRD_MARKER :
1022
28.6k
      case IENG_MARKER :
1023
31.5k
      case IGNR_MARKER :
1024
31.5k
      case INAM_MARKER :
1025
34.5k
      case IPRD_MARKER :
1026
34.6k
      case ISBJ_MARKER :
1027
34.7k
      case ISRC_MARKER :
1028
36.4k
      case IAUT_MARKER :
1029
36.4k
      case ITRK_MARKER :
1030
36.4k
          bytesread += psf_binheader_readf (psf, "4", &chunk_size) ;
1031
36.4k
          chunk_size += (chunk_size & 1) ;
1032
36.4k
          if (chunk_size >= SIGNED_SIZEOF (buffer) || bytesread + chunk_size > chunk_length)
1033
15.4k
          { psf_log_printf (psf, "  *** %M : %u (too big)\n", chunk, chunk_size) ;
1034
15.4k
            goto cleanup_subchunk_parse ;
1035
20.9k
            } ;
1036
1037
20.9k
          bytesread += psf_binheader_readf (psf, "b", buffer, chunk_size) ;
1038
20.9k
          buffer [chunk_size] = 0 ;
1039
20.9k
          psf_log_printf (psf, "    %M : %s\n", chunk, buffer) ;
1040
20.9k
          break ;
1041
1042
19.7k
      case labl_MARKER :
1043
19.7k
          { int mark_id ;
1044
1045
19.7k
            bytesread += psf_binheader_readf (psf, "44", &chunk_size, &mark_id) ;
1046
19.7k
            chunk_size -= 4 ;
1047
19.7k
            chunk_size += (chunk_size & 1) ;
1048
19.7k
            if (chunk_size < 1 || chunk_size >= SIGNED_SIZEOF (buffer) || bytesread + chunk_size > chunk_length)
1049
10.6k
            { psf_log_printf (psf, "  *** %M : %u (too big)\n", chunk, chunk_size) ;
1050
10.6k
              goto cleanup_subchunk_parse ;
1051
10.6k
              } ;
1052
1053
9.13k
            bytesread += psf_binheader_readf (psf, "b", buffer, chunk_size) ;
1054
9.13k
            buffer [chunk_size] = 0 ;
1055
1056
9.13k
            if (mark_id < 10) /* avoid swamping log buffer with labels */
1057
3.09k
              psf_log_printf (psf, "    %M : %u : %s\n", chunk, mark_id, buffer) ;
1058
6.04k
            else if (mark_id == 10)
1059
3.62k
              psf_log_printf (psf, "    (Skipping)\n") ;
1060
1061
9.13k
            if (psf->cues)
1062
491
            { unsigned int i = 0 ;
1063
1064
              /* find id to store label */
1065
902
              while (i < psf->cues->cue_count && psf->cues->cue_points [i].indx != mark_id)
1066
411
                i++ ;
1067
1068
491
              if (i < psf->cues->cue_count)
1069
195
                memcpy (psf->cues->cue_points [i].name, buffer, sizeof (psf->cues->cue_points [i].name)) ;
1070
491
              } ;
1071
9.13k
            } ;
1072
9.13k
          break ;
1073
1074
7.56k
      case DISP_MARKER :
1075
7.56k
      case ltxt_MARKER :
1076
7.99k
      case note_MARKER :
1077
7.99k
          bytesread += psf_binheader_readf (psf, "4", &chunk_size) ;
1078
7.99k
          chunk_size += (chunk_size & 1) ;
1079
7.99k
          if (chunk_size >= SIGNED_SIZEOF (buffer) || bytesread + chunk_size > chunk_length)
1080
5.81k
          { psf_log_printf (psf, "  *** %M : %u (too big)\n", chunk, chunk_size) ;
1081
5.81k
            goto cleanup_subchunk_parse ;
1082
5.81k
            } ;
1083
1084
2.18k
          psf_log_printf (psf, "    %M : %u\n", chunk, chunk_size) ;
1085
2.18k
          goto cleanup_subchunk_parse ;
1086
1087
61.5k
      default :
1088
61.5k
          bytesread += psf_binheader_readf (psf, "4", &chunk_size) ;
1089
61.5k
          chunk_size += (chunk_size & 1) ;
1090
61.5k
          if (bytesread + chunk_size > chunk_length)
1091
23.6k
          { psf_log_printf (psf, "  *** %M : %u (too big)\n", chunk, chunk_size) ;
1092
23.6k
            goto cleanup_subchunk_parse ;
1093
23.6k
            }
1094
37.9k
          else
1095
37.9k
          { psf_log_printf (psf, "    %M : %u\n", chunk, chunk_size) ;
1096
37.9k
            bytesread += psf_binheader_readf (psf, "j", chunk_size) ;
1097
37.9k
            } ;
1098
37.9k
          break ;
1099
125k
      } ;
1100
1101
68.0k
    switch (chunk)
1102
68.0k
    { case ISFT_MARKER :
1103
1.11k
          psf_store_string (psf, SF_STR_SOFTWARE, buffer) ;
1104
1.11k
          break ;
1105
1.56k
      case ICOP_MARKER :
1106
1.56k
          psf_store_string (psf, SF_STR_COPYRIGHT, buffer) ;
1107
1.56k
          break ;
1108
14
      case INAM_MARKER :
1109
14
          psf_store_string (psf, SF_STR_TITLE, buffer) ;
1110
14
          break ;
1111
4.40k
      case IART_MARKER :
1112
4.40k
          psf_store_string (psf, SF_STR_ARTIST, buffer) ;
1113
4.40k
          break ;
1114
5.51k
      case ICMT_MARKER :
1115
5.51k
          psf_store_string (psf, SF_STR_COMMENT, buffer) ;
1116
5.51k
          break ;
1117
132
      case ICRD_MARKER :
1118
132
          psf_store_string (psf, SF_STR_DATE, buffer) ;
1119
132
          break ;
1120
2.82k
      case IGNR_MARKER :
1121
2.82k
          psf_store_string (psf, SF_STR_GENRE, buffer) ;
1122
2.82k
          break ;
1123
2.74k
      case IPRD_MARKER :
1124
2.74k
          psf_store_string (psf, SF_STR_ALBUM, buffer) ;
1125
2.74k
          break ;
1126
11
      case ITRK_MARKER :
1127
11
          psf_store_string (psf, SF_STR_TRACKNUMBER, buffer) ;
1128
11
          break ;
1129
68.0k
      } ;
1130
68.0k
    } ;
1131
1132
76.0k
cleanup_subchunk_parse :
1133
1134
76.0k
  if (chunk_length > bytesread)
1135
52.9k
    bytesread += psf_binheader_readf (psf, "j", chunk_length - bytesread) ;
1136
1137
76.0k
  return 0 ;
1138
13.1k
} /* wavlike_subchunk_parse */
1139
1140
void
1141
wavlike_write_strings (SF_PRIVATE *psf, int location)
1142
0
{ int k, prev_head_index, saved_head_index ;
1143
1144
0
  if (psf_location_string_count (psf, location) == 0)
1145
0
    return ;
1146
1147
0
  prev_head_index = psf->header.indx + 4 ;
1148
1149
0
  psf_binheader_writef (psf, "m4m", BHWm (LIST_MARKER), BHW4 (0xBADBAD), BHWm (INFO_MARKER)) ;
1150
1151
0
  for (k = 0 ; k < SF_MAX_STRINGS ; k++)
1152
0
  { if (psf->strings.data [k].type == 0)
1153
0
      break ;
1154
0
    if (psf->strings.data [k].type < 0 || psf->strings.data [k].flags != location)
1155
0
      continue ;
1156
1157
0
    switch (psf->strings.data [k].type)
1158
0
    { case SF_STR_SOFTWARE :
1159
0
        psf_binheader_writef (psf, "ms", BHWm (ISFT_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
1160
0
        break ;
1161
1162
0
      case SF_STR_TITLE :
1163
0
        psf_binheader_writef (psf, "ms", BHWm (INAM_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
1164
0
        break ;
1165
1166
0
      case SF_STR_COPYRIGHT :
1167
0
        psf_binheader_writef (psf, "ms", BHWm (ICOP_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
1168
0
        break ;
1169
1170
0
      case SF_STR_ARTIST :
1171
0
        psf_binheader_writef (psf, "ms", BHWm (IART_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
1172
0
        break ;
1173
1174
0
      case SF_STR_COMMENT :
1175
0
        psf_binheader_writef (psf, "ms", BHWm (ICMT_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
1176
0
        break ;
1177
1178
0
      case SF_STR_DATE :
1179
0
        psf_binheader_writef (psf, "ms", BHWm (ICRD_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
1180
0
        break ;
1181
1182
0
      case SF_STR_GENRE :
1183
0
        psf_binheader_writef (psf, "ms", BHWm (IGNR_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
1184
0
        break ;
1185
1186
0
      case SF_STR_ALBUM :
1187
0
        psf_binheader_writef (psf, "ms", BHWm (IPRD_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
1188
0
        break ;
1189
1190
0
      case SF_STR_TRACKNUMBER :
1191
0
        psf_binheader_writef (psf, "ms", BHWm (ITRK_MARKER), BHWs (psf->strings.storage + psf->strings.data [k].offset)) ;
1192
0
        break ;
1193
1194
0
      default :
1195
0
        break ;
1196
0
      } ;
1197
0
    } ;
1198
1199
0
  saved_head_index = psf->header.indx ;
1200
0
  psf->header.indx = prev_head_index ;
1201
0
  psf_binheader_writef (psf, "4", BHW4 (saved_head_index - prev_head_index - 4)) ;
1202
0
  psf->header.indx = saved_head_index ;
1203
1204
0
} /* wavlike_write_strings */
1205
1206
int
1207
wavlike_read_peak_chunk (SF_PRIVATE * psf, size_t chunk_size)
1208
8.36k
{ char    buffer [256] ;
1209
8.36k
  uint32_t uk ;
1210
1211
8.36k
  if (chunk_size != WAVLIKE_PEAK_CHUNK_SIZE (psf->sf.channels))
1212
8
  { psf_binheader_readf (psf, "j", chunk_size) ;
1213
8
    psf_log_printf (psf, "*** File PEAK chunk size doesn't fit with number of channels (%d).\n", psf->sf.channels) ;
1214
8
    return SFE_WAV_BAD_PEAK ;
1215
8.35k
    } ;
1216
1217
8.35k
  if (psf->peak_info)
1218
8.29k
  { psf_log_printf (psf, "*** Found existing peak info, using last one.\n") ;
1219
8.29k
    free (psf->peak_info) ;
1220
8.29k
    psf->peak_info = NULL ;
1221
8.29k
    } ;
1222
8.35k
  if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
1223
0
    return SFE_MALLOC_FAILED ;
1224
1225
  /* read in rest of PEAK chunk. */
1226
8.35k
  psf_binheader_readf (psf, "44", & (psf->peak_info->version), & (psf->peak_info->timestamp)) ;
1227
1228
8.35k
  if (psf->peak_info->version != 1)
1229
6.16k
    psf_log_printf (psf, "  version    : %d *** (should be version 1)\n", psf->peak_info->version) ;
1230
2.19k
  else
1231
2.19k
    psf_log_printf (psf, "  version    : %d\n", psf->peak_info->version) ;
1232
1233
8.35k
  psf_log_printf (psf, "  time stamp : %d\n", psf->peak_info->timestamp) ;
1234
8.35k
  psf_log_printf (psf, "    Ch   Position       Value\n") ;
1235
1236
152k
  for (uk = 0 ; uk < (uint32_t) psf->sf.channels ; uk++)
1237
143k
  { float value ;
1238
143k
    uint32_t position ;
1239
1240
143k
    psf_binheader_readf (psf, "f4", &value, &position) ;
1241
143k
    psf->peak_info->peaks [uk].value = value ;
1242
143k
    psf->peak_info->peaks [uk].position = position ;
1243
1244
143k
    snprintf (buffer, sizeof (buffer), "    %2d   %-12" PRId64 "   %g\n",
1245
143k
        uk, psf->peak_info->peaks [uk].position, psf->peak_info->peaks [uk].value) ;
1246
143k
    buffer [sizeof (buffer) - 1] = 0 ;
1247
143k
    psf_log_printf (psf, "%s", buffer) ;
1248
143k
    } ;
1249
1250
8.35k
  return 0 ;
1251
8.35k
} /* wavlike_read_peak_chunk */
1252
1253
void
1254
wavlike_write_peak_chunk (SF_PRIVATE * psf)
1255
0
{ int k ;
1256
1257
0
  if (psf->peak_info == NULL)
1258
0
    return ;
1259
1260
0
  psf_binheader_writef (psf, "m4", BHWm (PEAK_MARKER), BHW4 (WAVLIKE_PEAK_CHUNK_SIZE (psf->sf.channels))) ;
1261
0
  psf_binheader_writef (psf, "44", BHW4 (1), BHW4 (time (NULL))) ;
1262
0
  for (k = 0 ; k < psf->sf.channels ; k++)
1263
0
    psf_binheader_writef (psf, "ft8", BHWf (psf->peak_info->peaks [k].value), BHW8 (psf->peak_info->peaks [k].position)) ;
1264
0
} /* wavlike_write_peak_chunk */
1265
1266
/*==============================================================================
1267
*/
1268
1269
static int
1270
exif_fill_and_sink (SF_PRIVATE *psf, char* buf, size_t bufsz, size_t toread)
1271
25.1k
{
1272
25.1k
  size_t bytesread = 0 ;
1273
1274
25.1k
  buf [0] = 0 ;
1275
25.1k
  bufsz -= 1 ;
1276
25.1k
  if (toread < bufsz)
1277
25.1k
    bufsz = toread ;
1278
25.1k
  bytesread = psf_binheader_readf (psf, "b", buf, bufsz) ;
1279
25.1k
  buf [bufsz] = 0 ;
1280
1281
25.1k
  if (bytesread == bufsz && toread > bufsz)
1282
0
    bytesread += psf_binheader_readf (psf, "j", toread - bufsz) ;
1283
1284
25.1k
  return bytesread ;
1285
25.1k
} /* exif_fill_and_sink */
1286
1287
/*
1288
** Exif specification for audio files, at JEITA CP-3451 Exif 2.2 section 5
1289
** (Exif Audio File Specification) http://www.exif.org/Exif2-2.PDF
1290
*/
1291
static int
1292
exif_subchunk_parse (SF_PRIVATE *psf, uint32_t length)
1293
26.3k
{ uint32_t marker, dword = 0, vmajor = -1, vminor = -1, bytesread = 0 ;
1294
26.3k
  char buf [4096] ;
1295
26.3k
  int thisread ;
1296
1297
282k
  while (bytesread < length)
1298
278k
  {
1299
278k
    if ((thisread = psf_binheader_readf (psf, "m", &marker)) == 0)
1300
39
      break ;
1301
278k
    bytesread += thisread ;
1302
1303
278k
    switch (marker)
1304
278k
    {
1305
23.9k
      case 0 : /* camera padding? */
1306
23.9k
        break ;
1307
1308
718
      case ever_MARKER :
1309
718
        bytesread += psf_binheader_readf (psf, "j4", 4, &dword) ;
1310
718
        vmajor = 10 * (((dword >> 24) & 0xff) - '0') + (((dword >> 16) & 0xff) - '0') ;
1311
718
        vminor = 10 * (((dword >> 8) & 0xff) - '0') + ((dword & 0xff) - '0') ;
1312
718
        psf_log_printf (psf, "    EXIF Version : %u.%02u\n", vmajor, vminor) ;
1313
718
        break ;
1314
1315
1.41k
      case olym_MARKER :
1316
1.41k
        bytesread += psf_binheader_readf (psf, "4", &dword) ;
1317
1.41k
        psf_log_printf (psf, "%M : %u\n", marker, dword) ;
1318
1.41k
        if (dword > length || bytesread + dword > length)
1319
909
          break ;
1320
503
        dword += (dword & 1) ;
1321
503
        bytesread += psf_binheader_readf (psf, "j", dword) ;
1322
503
        break ;
1323
1324
870
      case emnt_MARKER : /* design information: null-terminated string */
1325
44.4k
      case emdl_MARKER : /* model name ; null-terminated string */
1326
44.6k
      case ecor_MARKER : /* manufacturer: null-terminated string */
1327
44.8k
      case etim_MARKER : /* creation time: null-terminated string in the format "hour:minute:second.subsecond" */
1328
45.1k
      case erel_MARKER : /* relation info: null-terminated string (filename) */
1329
45.5k
      case eucm_MARKER : /* user comment: 4-byte size follows, then possibly unicode data */
1330
45.5k
        bytesread += psf_binheader_readf (psf, "4", &dword) ;
1331
45.5k
        bytesread += sizeof (dword) ;
1332
45.5k
        dword += (dword & 1) ;
1333
1334
45.5k
        if (dword >= sizeof (buf))
1335
20.3k
        { psf_log_printf (psf, "*** Marker '%M' is too big %u\n\n", marker, dword) ;
1336
20.3k
          return bytesread ;
1337
25.1k
          } ;
1338
1339
25.1k
        bytesread += exif_fill_and_sink (psf, buf, sizeof (buf), dword) ;
1340
1341
        /* BAD - don't know what's going on here -- maybe a bug in the camera */
1342
        /* field should be NULL-terminated but there's no room for it with the reported number */
1343
        /*  example output:     emdl : 8 (EX-Z1050) */
1344
25.1k
        if (marker == emdl_MARKER && dword == strlen (buf) /* should be >= strlen+1*/)
1345
5.81k
        { psf_log_printf (psf, "    *** field size too small for string (sinking 2 bytes)\n") ;
1346
5.81k
          bytesread += psf_binheader_readf (psf, "j", 2) ;
1347
5.81k
          } ;
1348
1349
25.1k
        psf_log_printf (psf, "    %M : %u (%s)\n", marker, dword, buf) ;
1350
25.1k
        if (dword > length)
1351
1.82k
          return bytesread ;
1352
23.3k
        break ;
1353
1354
206k
      default :
1355
206k
        psf_log_printf (psf, "    *** %M (%u): -- ignored --\n", marker, marker) ;
1356
206k
        break ;
1357
278k
      } ;
1358
256k
    } ;
1359
1360
4.14k
  return bytesread ;
1361
26.3k
} /* exif_subchunk_parse */
1362
1363
void
1364
wavlike_write_custom_chunks (SF_PRIVATE * psf)
1365
0
{ uint32_t k ;
1366
1367
0
  for (k = 0 ; k < psf->wchunks.used ; k++)
1368
0
    psf_binheader_writef (psf, "m4b", BHWm (psf->wchunks.chunks [k].mark32), BHW4 (psf->wchunks.chunks [k].len),
1369
0
              BHWv (psf->wchunks.chunks [k].data), BHWz (psf->wchunks.chunks [k].len)) ;
1370
1371
0
} /* wavlike_write_custom_chunks */