~ubuntu-branches/ubuntu/gutsy/audacity/gutsy-backports

« back to all changes in this revision

Viewing changes to lib-src/libsndfile/src/w64.c

  • Committer: Bazaar Package Importer
  • Author(s): John Dong
  • Date: 2008-02-18 21:58:19 UTC
  • mfrom: (13.1.2 hardy)
  • Revision ID: james.westby@ubuntu.com-20080218215819-tmbcf1rx238r8gdv
Tags: 1.3.4-1.1ubuntu1~gutsy1
Automated backport upload; no source changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
** Copyright (C) 1999-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
3
 
**
4
 
** This program is free software; you can redistribute it and/or modify
5
 
** it under the terms of the GNU Lesser General Public License as published by
6
 
** the Free Software Foundation; either version 2.1 of the License, or
7
 
** (at your option) any later version.
8
 
**
9
 
** This program is distributed in the hope that it will be useful,
10
 
** but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
** GNU Lesser General Public License for more details.
13
 
**
14
 
** You should have received a copy of the GNU Lesser General Public License
15
 
** along with this program; if not, write to the Free Software
16
 
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
 
*/
18
 
 
19
 
#include        "sfconfig.h"
20
 
 
21
 
#include        <stdio.h>
22
 
#include        <string.h>
23
 
#include        <ctype.h>
24
 
#include        <time.h>
25
 
 
26
 
#include        "sndfile.h"
27
 
#include        "sfendian.h"
28
 
#include        "common.h"
29
 
#include        "wav_w64.h"
30
 
 
31
 
/*------------------------------------------------------------------------------
32
 
** W64 files use 16 byte markers as opposed to the four byte marker of
33
 
** WAV files.
34
 
** For comparison purposes, an integer is required, so make an integer
35
 
** hash for the 16 bytes using MAKE_HASH16 macro, but also create a 16
36
 
** byte array containing the complete 16 bytes required when writing the
37
 
** header.
38
 
*/
39
 
 
40
 
#define MAKE_HASH16(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc,xd,xe,xf)    \
41
 
                        (       (x0)                    ^ ((x1) << 1)   ^ ((x2) << 2)   ^ ((x3) << 3) ^ \
42
 
                                ((x4) << 4)     ^ ((x5) << 5)   ^ ((x6) << 6)   ^ ((x7) << 7) ^ \
43
 
                                ((x8) << 8)     ^ ((x9) << 9)   ^ ((xa) << 10)  ^ ((xb) << 11) ^ \
44
 
                                ((xc) << 12)    ^ ((xd) << 13)  ^ ((xe) << 14)  ^ ((xf) << 15)  )
45
 
 
46
 
#define MAKE_MARKER16(name,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc,xd,xe,xf)     \
47
 
                        static unsigned char name [16] = { (x0), (x1), (x2), (x3), (x4), (x5), \
48
 
                                (x6), (x7), (x8), (x9), (xa), (xb), (xc), (xd), (xe), (xf) }
49
 
 
50
 
#define riff_HASH16 MAKE_HASH16 ('r', 'i', 'f', 'f', 0x2E, 0x91, 0xCF, 0x11, 0xA5, \
51
 
                                                                0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00)
52
 
 
53
 
#define wave_HASH16     MAKE_HASH16 ('w', 'a', 'v', 'e', 0xF3, 0xAC, 0xD3, 0x11, \
54
 
                                                                0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A)
55
 
 
56
 
#define fmt_HASH16              MAKE_HASH16 ('f', 'm', 't', ' ', 0xF3, 0xAC, 0xD3, 0x11, \
57
 
                                                                0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A)
58
 
 
59
 
#define fact_HASH16     MAKE_HASH16 ('f', 'a', 'c', 't', 0xF3, 0xAC, 0xD3, 0x11, \
60
 
                                                                0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A)
61
 
 
62
 
#define data_HASH16     MAKE_HASH16 ('d', 'a', 't', 'a', 0xF3, 0xAC, 0xD3, 0x11, \
63
 
                                                                0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A)
64
 
 
65
 
#define ACID_HASH16     MAKE_HASH16 (0x6D, 0x07, 0x1C, 0xEA, 0xA3, 0xEF, 0x78, 0x4C, \
66
 
                                                                0x90, 0x57, 0x7F, 0x79, 0xEE, 0x25, 0x2A, 0xAE)
67
 
 
68
 
MAKE_MARKER16 (riff_MARKER16, 'r', 'i', 'f', 'f', 0x2E, 0x91, 0xCF, 0x11,
69
 
                                                                0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00) ;
70
 
 
71
 
 
72
 
MAKE_MARKER16 (wave_MARKER16, 'w', 'a', 'v', 'e', 0xF3, 0xAC, 0xD3, 0x11,
73
 
                                                                0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ;
74
 
 
75
 
MAKE_MARKER16 (fmt_MARKER16, 'f', 'm', 't', ' ', 0xF3, 0xAC, 0xD3, 0x11,
76
 
                                                                0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ;
77
 
 
78
 
MAKE_MARKER16 (fact_MARKER16, 'f', 'a', 'c', 't', 0xF3, 0xAC, 0xD3, 0x11,
79
 
                                                                0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ;
80
 
 
81
 
MAKE_MARKER16 (data_MARKER16, 'd', 'a', 't', 'a', 0xF3, 0xAC, 0xD3, 0x11,
82
 
                                                                0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ;
83
 
 
84
 
enum
85
 
{       HAVE_riff       = 0x01,
86
 
        HAVE_wave       = 0x02,
87
 
        HAVE_fmt        = 0x04,
88
 
        HAVE_fact       = 0x08,
89
 
        HAVE_data       = 0x20
90
 
} ;
91
 
 
92
 
/*------------------------------------------------------------------------------
93
 
 * Private static functions.
94
 
 */
95
 
 
96
 
static int      w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) ;
97
 
static int      w64_write_header (SF_PRIVATE *psf, int calc_length) ;
98
 
static int      w64_close (SF_PRIVATE *psf) ;
99
 
 
100
 
/*------------------------------------------------------------------------------
101
 
** Public function.
102
 
*/
103
 
 
104
 
int
105
 
w64_open        (SF_PRIVATE *psf)
106
 
{       int     subformat, error, blockalign = 0, framesperblock = 0 ;
107
 
 
108
 
        if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR &&psf->filelength > 0))
109
 
        {       if ((error = w64_read_header (psf, &blockalign, &framesperblock)))
110
 
                        return error ;
111
 
                } ;
112
 
 
113
 
        if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_W64)
114
 
                return  SFE_BAD_OPEN_FORMAT ;
115
 
 
116
 
        subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
117
 
 
118
 
        if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
119
 
        {       if (psf->is_pipe)
120
 
                        return SFE_NO_PIPE_WRITE ;
121
 
 
122
 
                psf->endian = SF_ENDIAN_LITTLE ;                /* All W64 files are little endian. */
123
 
 
124
 
                psf->blockwidth = psf->bytewidth * psf->sf.channels ;
125
 
 
126
 
                if (subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM)
127
 
                {       blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ;
128
 
                        framesperblock = -1 ;
129
 
 
130
 
                        /* FIXME : This block must go */
131
 
                        psf->filelength = SF_COUNT_MAX ;
132
 
                        psf->datalength = psf->filelength ;
133
 
                        if (psf->sf.frames <= 0)
134
 
                                psf->sf.frames = (psf->blockwidth) ? psf->filelength / psf->blockwidth : psf->filelength ;
135
 
                        /* EMXIF : This block must go */
136
 
                        } ;
137
 
 
138
 
                if ((error = w64_write_header (psf, SF_FALSE)))
139
 
                        return error ;
140
 
 
141
 
                psf->write_header = w64_write_header ;
142
 
                } ;
143
 
 
144
 
        psf->container_close = w64_close ;
145
 
 
146
 
        switch (subformat)
147
 
        {       case SF_FORMAT_PCM_U8 :
148
 
                                        error = pcm_init (psf) ;
149
 
                                        break ;
150
 
 
151
 
                case SF_FORMAT_PCM_16 :
152
 
                case SF_FORMAT_PCM_24 :
153
 
                case SF_FORMAT_PCM_32 :
154
 
                                        error = pcm_init (psf) ;
155
 
                                        break ;
156
 
 
157
 
                case SF_FORMAT_ULAW :
158
 
                                        error = ulaw_init (psf) ;
159
 
                                        break ;
160
 
 
161
 
                case SF_FORMAT_ALAW :
162
 
                                        error = alaw_init (psf) ;
163
 
                                        break ;
164
 
 
165
 
                /* Lite remove start */
166
 
                case SF_FORMAT_FLOAT :
167
 
                                        error = float32_init (psf) ;
168
 
                                        break ;
169
 
 
170
 
                case SF_FORMAT_DOUBLE :
171
 
                                        error = double64_init (psf) ;
172
 
                                        break ;
173
 
 
174
 
                case SF_FORMAT_IMA_ADPCM :
175
 
                                        error = wav_w64_ima_init (psf, blockalign, framesperblock) ;
176
 
                                        break ;
177
 
 
178
 
                case SF_FORMAT_MS_ADPCM :
179
 
                                        error = wav_w64_msadpcm_init (psf, blockalign, framesperblock) ;
180
 
                                        break ;
181
 
                /* Lite remove end */
182
 
 
183
 
                case SF_FORMAT_GSM610 :
184
 
                                        error = gsm610_init (psf) ;
185
 
                                        break ;
186
 
 
187
 
                default :       return SFE_UNIMPLEMENTED ;
188
 
                } ;
189
 
 
190
 
        return error ;
191
 
} /* w64_open */
192
 
 
193
 
/*=========================================================================
194
 
** Private functions.
195
 
*/
196
 
 
197
 
static int
198
 
w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
199
 
{       WAV_FMT         wav_fmt ;
200
 
        int                     dword = 0, marker, format = 0 ;
201
 
        sf_count_t      chunk_size, bytesread = 0 ;
202
 
        int                     parsestage = 0, error, done = 0 ;
203
 
 
204
 
        /* Set position to start of file to begin reading header. */
205
 
        memset (&wav_fmt, 0, sizeof (wav_fmt)) ;
206
 
        psf_binheader_readf (psf, "p", 0) ;
207
 
 
208
 
        while (! done)
209
 
        {       /* Read the 4 byte marker and jump 12 bytes. */
210
 
                bytesread += psf_binheader_readf (psf, "h", &marker) ;
211
 
                chunk_size = 0 ;
212
 
 
213
 
                switch (marker)
214
 
                {       case riff_HASH16 :
215
 
                                        if (parsestage)
216
 
                                                return SFE_W64_NO_RIFF ;
217
 
 
218
 
                                        bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ;
219
 
 
220
 
                                        if (psf->filelength < chunk_size)
221
 
                                                psf_log_printf (psf, "riff : %D (should be %D)\n", chunk_size, psf->filelength) ;
222
 
                                        else
223
 
                                                psf_log_printf (psf, "riff : %D\n", chunk_size) ;
224
 
 
225
 
                                        parsestage |= HAVE_riff ;
226
 
                                        break ;
227
 
 
228
 
                        case ACID_HASH16:
229
 
                                        psf_log_printf (psf, "Looks like an ACID file. Exiting.\n") ;
230
 
                                        return SFE_UNIMPLEMENTED ;
231
 
 
232
 
                        case wave_HASH16 :
233
 
                                        if ((parsestage & HAVE_riff) != HAVE_riff)
234
 
                                                return SFE_W64_NO_WAVE ;
235
 
                                        psf_log_printf (psf, "wave\n") ;
236
 
                                        parsestage |= HAVE_wave ;
237
 
                                        break ;
238
 
 
239
 
                        case fmt_HASH16 :
240
 
                                        if ((parsestage & (HAVE_riff | HAVE_wave)) != (HAVE_riff | HAVE_wave))
241
 
                                                return SFE_W64_NO_FMT ;
242
 
 
243
 
                                        bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ;
244
 
                                        psf_log_printf (psf, " fmt : %D\n", chunk_size) ;
245
 
 
246
 
                                        /* size of 16 byte marker and 8 byte chunk_size value. */
247
 
                                        chunk_size -= 24 ;
248
 
 
249
 
                                        if ((error = wav_w64_read_fmt_chunk (psf, &wav_fmt, (int) chunk_size)))
250
 
                                                return error ;
251
 
 
252
 
                                        if (chunk_size % 8)
253
 
                                                psf_binheader_readf (psf, "j", 8 - (chunk_size % 8)) ;
254
 
 
255
 
                                        format          = wav_fmt.format ;
256
 
                                        parsestage |= HAVE_fmt ;
257
 
                                        break ;
258
 
 
259
 
                        case fact_HASH16:
260
 
                                        {       sf_count_t frames ;
261
 
 
262
 
                                                psf_binheader_readf (psf, "e88", &chunk_size, &frames) ;
263
 
                                                psf_log_printf (psf, "   fact : %D\n     frames : %D\n",
264
 
                                                                                chunk_size, frames) ;
265
 
                                                } ;
266
 
                                        break ;
267
 
 
268
 
 
269
 
                        case data_HASH16 :
270
 
                                        if ((parsestage & (HAVE_riff | HAVE_wave | HAVE_fmt)) != (HAVE_riff | HAVE_wave | HAVE_fmt))
271
 
                                                return SFE_W64_NO_DATA ;
272
 
 
273
 
                                        psf_binheader_readf (psf, "e8", &chunk_size) ;
274
 
 
275
 
                                        psf->dataoffset = psf_ftell (psf) ;
276
 
 
277
 
                                        psf->datalength = chunk_size - 24 ;
278
 
 
279
 
                                        if (chunk_size % 8)
280
 
                                                chunk_size += 8 - (chunk_size % 8) ;
281
 
 
282
 
                                        psf_log_printf (psf, "data : %D\n", chunk_size) ;
283
 
 
284
 
                                        parsestage |= HAVE_data ;
285
 
 
286
 
                                        if (! psf->sf.seekable)
287
 
                                                break ;
288
 
 
289
 
                                        /* Seek past data and continue reading header. */
290
 
                                        psf_fseek (psf, chunk_size, SEEK_CUR) ;
291
 
                                        break ;
292
 
 
293
 
                        default :
294
 
                                        if (psf_ftell (psf) & 0x0F)
295
 
                                        {       psf_log_printf (psf, "  Unknown chunk marker at position %d. Resynching.\n", dword - 4) ;
296
 
                                                psf_binheader_readf (psf, "j", -3) ;
297
 
                                                break ;
298
 
                                                } ;
299
 
                                        psf_log_printf (psf, "*** Unknown chunk marker : %X. Exiting parser.\n", marker) ;
300
 
                                        done = SF_TRUE ;
301
 
                                        break ;
302
 
                        } ;     /* switch (dword) */
303
 
 
304
 
                if (psf->sf.seekable == 0 && (parsestage & HAVE_data))
305
 
                        break ;
306
 
 
307
 
                if (psf_ftell (psf) >= (psf->filelength - (2 * SIGNED_SIZEOF (dword))))
308
 
                        break ;
309
 
                } ; /* while (1) */
310
 
 
311
 
        if (! psf->dataoffset)
312
 
                return SFE_W64_NO_DATA ;
313
 
 
314
 
        psf->endian = SF_ENDIAN_LITTLE ;                /* All WAV files are little endian. */
315
 
 
316
 
        if (psf_ftell (psf) != psf->dataoffset)
317
 
                psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
318
 
 
319
 
        if (psf->blockwidth)
320
 
        {       if (psf->filelength - psf->dataoffset < psf->datalength)
321
 
                        psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
322
 
                else
323
 
                        psf->sf.frames = psf->datalength / psf->blockwidth ;
324
 
                } ;
325
 
 
326
 
        switch (format)
327
 
        {       case WAVE_FORMAT_PCM :
328
 
                case WAVE_FORMAT_EXTENSIBLE :
329
 
                                        /* extensible might be FLOAT, MULAW, etc as well! */
330
 
                                        psf->sf.format = SF_FORMAT_W64 | u_bitwidth_to_subformat (psf->bytewidth * 8) ;
331
 
                                        break ;
332
 
 
333
 
                case WAVE_FORMAT_MULAW :
334
 
                                        psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ULAW) ;
335
 
                                        break ;
336
 
 
337
 
                case WAVE_FORMAT_ALAW :
338
 
                                        psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ALAW) ;
339
 
                                        break ;
340
 
 
341
 
                case WAVE_FORMAT_MS_ADPCM :
342
 
                                        psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM) ;
343
 
                                        *blockalign = wav_fmt.msadpcm.blockalign ;
344
 
                                        *framesperblock = wav_fmt.msadpcm.samplesperblock ;
345
 
                                        break ;
346
 
 
347
 
                case WAVE_FORMAT_IMA_ADPCM :
348
 
                                        psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM) ;
349
 
                                        *blockalign = wav_fmt.ima.blockalign ;
350
 
                                        *framesperblock = wav_fmt.ima.samplesperblock ;
351
 
                                        break ;
352
 
 
353
 
                case WAVE_FORMAT_GSM610 :
354
 
                                        psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_GSM610) ;
355
 
                                        break ;
356
 
 
357
 
                case WAVE_FORMAT_IEEE_FLOAT :
358
 
                                        psf->sf.format = SF_FORMAT_W64 ;
359
 
                                        psf->sf.format |= (psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT ;
360
 
                                        break ;
361
 
 
362
 
                default : return SFE_UNIMPLEMENTED ;
363
 
                } ;
364
 
 
365
 
        return 0 ;
366
 
} /* w64_read_header */
367
 
 
368
 
static int
369
 
w64_write_header (SF_PRIVATE *psf, int calc_length)
370
 
{       sf_count_t      fmt_size, current ;
371
 
        size_t          fmt_pad = 0 ;
372
 
        int             subformat, add_fact_chunk = SF_FALSE ;
373
 
 
374
 
        current = psf_ftell (psf) ;
375
 
 
376
 
        if (calc_length)
377
 
        {       psf->filelength = psf_get_filelen (psf) ;
378
 
 
379
 
                psf->datalength = psf->filelength - psf->dataoffset ;
380
 
                if (psf->dataend)
381
 
                        psf->datalength -= psf->filelength - psf->dataend ;
382
 
 
383
 
                if (psf->bytewidth)
384
 
                        psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
385
 
                } ;
386
 
 
387
 
        /* Reset the current header length to zero. */
388
 
        psf->header [0] = 0 ;
389
 
        psf->headindex = 0 ;
390
 
        psf_fseek (psf, 0, SEEK_SET) ;
391
 
 
392
 
        /* riff marker, length, wave and 'fmt ' markers. */
393
 
        psf_binheader_writef (psf, "eh8hh", riff_MARKER16, psf->filelength - 8, wave_MARKER16, fmt_MARKER16) ;
394
 
 
395
 
        subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
396
 
 
397
 
        switch (subformat)
398
 
        {       case    SF_FORMAT_PCM_U8 :
399
 
                case    SF_FORMAT_PCM_16 :
400
 
                case    SF_FORMAT_PCM_24 :
401
 
                case    SF_FORMAT_PCM_32 :
402
 
                                        fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ;
403
 
                                        fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
404
 
                                        fmt_size += fmt_pad ;
405
 
 
406
 
                                        /* fmt : format, channels, samplerate */
407
 
                                        psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_PCM, psf->sf.channels, psf->sf.samplerate) ;
408
 
                                        /*  fmt : bytespersec */
409
 
                                        psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
410
 
                                        /*  fmt : blockalign, bitwidth */
411
 
                                        psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
412
 
                                        break ;
413
 
 
414
 
                case SF_FORMAT_FLOAT :
415
 
                case SF_FORMAT_DOUBLE :
416
 
                                        fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ;
417
 
                                        fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
418
 
                                        fmt_size += fmt_pad ;
419
 
 
420
 
                                        /* fmt : format, channels, samplerate */
421
 
                                        psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_IEEE_FLOAT, psf->sf.channels, psf->sf.samplerate) ;
422
 
                                        /*  fmt : bytespersec */
423
 
                                        psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
424
 
                                        /*  fmt : blockalign, bitwidth */
425
 
                                        psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
426
 
 
427
 
                                        add_fact_chunk = SF_TRUE ;
428
 
                                        break ;
429
 
 
430
 
                case SF_FORMAT_ULAW :
431
 
                                        fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ;
432
 
                                        fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
433
 
                                        fmt_size += fmt_pad ;
434
 
 
435
 
                                        /* fmt : format, channels, samplerate */
436
 
                                        psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_MULAW, psf->sf.channels, psf->sf.samplerate) ;
437
 
                                        /*  fmt : bytespersec */
438
 
                                        psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
439
 
                                        /*  fmt : blockalign, bitwidth */
440
 
                                        psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ;
441
 
 
442
 
                                        add_fact_chunk = SF_TRUE ;
443
 
                                        break ;
444
 
 
445
 
                case SF_FORMAT_ALAW :
446
 
                                        fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ;
447
 
                                        fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
448
 
                                        fmt_size += fmt_pad ;
449
 
 
450
 
                                        /* fmt : format, channels, samplerate */
451
 
                                        psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_ALAW, psf->sf.channels, psf->sf.samplerate) ;
452
 
                                        /*  fmt : bytespersec */
453
 
                                        psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
454
 
                                        /*  fmt : blockalign, bitwidth */
455
 
                                        psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ;
456
 
 
457
 
                                        add_fact_chunk = SF_TRUE ;
458
 
                                        break ;
459
 
 
460
 
                /* Lite remove start */
461
 
                case SF_FORMAT_IMA_ADPCM :
462
 
                                        {       int             blockalign, framesperblock, bytespersec ;
463
 
 
464
 
                                                blockalign              = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ;
465
 
                                                framesperblock  = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ;
466
 
                                                bytespersec             = (psf->sf.samplerate * blockalign) / framesperblock ;
467
 
 
468
 
                                                /* fmt chunk. */
469
 
                                                fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
470
 
                                                fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
471
 
                                                fmt_size += fmt_pad ;
472
 
 
473
 
                                                /* fmt : size, WAV format type, channels. */
474
 
                                                psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_IMA_ADPCM, psf->sf.channels) ;
475
 
 
476
 
                                                /* fmt : samplerate, bytespersec. */
477
 
                                                psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ;
478
 
 
479
 
                                                /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
480
 
                                                psf_binheader_writef (psf, "e2222", blockalign, 4, 2, framesperblock) ;
481
 
                                                } ;
482
 
 
483
 
                                        add_fact_chunk = SF_TRUE ;
484
 
                                        break ;
485
 
 
486
 
                case SF_FORMAT_MS_ADPCM :
487
 
                                        {       int blockalign, framesperblock, bytespersec, extrabytes ;
488
 
 
489
 
                                                blockalign              = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ;
490
 
                                                framesperblock  = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ;
491
 
                                                bytespersec             = (psf->sf.samplerate * blockalign) / framesperblock ;
492
 
 
493
 
                                                /* fmt chunk. */
494
 
                                                extrabytes      = 2 + 2 + MSADPCM_ADAPT_COEFF_COUNT * (2 + 2) ;
495
 
                                                fmt_size        = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + extrabytes ;
496
 
                                                fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
497
 
                                                fmt_size += fmt_pad ;
498
 
 
499
 
                                                /* fmt : size, W64 format type, channels. */
500
 
                                                psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_MS_ADPCM, psf->sf.channels) ;
501
 
 
502
 
                                                /* fmt : samplerate, bytespersec. */
503
 
                                                psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ;
504
 
 
505
 
                                                /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
506
 
                                                psf_binheader_writef (psf, "e22222", blockalign, 4, extrabytes, framesperblock, 7) ;
507
 
 
508
 
                                                msadpcm_write_adapt_coeffs (psf) ;
509
 
                                                } ;
510
 
 
511
 
                                        add_fact_chunk = SF_TRUE ;
512
 
                                        break ;
513
 
                /* Lite remove end */
514
 
 
515
 
                case SF_FORMAT_GSM610 :
516
 
                                        {       int bytespersec ;
517
 
 
518
 
                                                bytespersec = (psf->sf.samplerate * WAV_W64_GSM610_BLOCKSIZE) / WAV_W64_GSM610_SAMPLES ;
519
 
 
520
 
                                                /* fmt chunk. */
521
 
                                                fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
522
 
                                                fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
523
 
                                                fmt_size += fmt_pad ;
524
 
 
525
 
                                                /* fmt : size, WAV format type, channels. */
526
 
                                                psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_GSM610, psf->sf.channels) ;
527
 
 
528
 
                                                /* fmt : samplerate, bytespersec. */
529
 
                                                psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ;
530
 
 
531
 
                                                /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
532
 
                                                psf_binheader_writef (psf, "e2222", WAV_W64_GSM610_BLOCKSIZE, 0, 2, WAV_W64_GSM610_SAMPLES) ;
533
 
                                                } ;
534
 
 
535
 
                                        add_fact_chunk = SF_TRUE ;
536
 
                                        break ;
537
 
 
538
 
                default :       return SFE_UNIMPLEMENTED ;
539
 
                } ;
540
 
 
541
 
        /* Pad to 8 bytes with zeros. */
542
 
        if (fmt_pad > 0)
543
 
                psf_binheader_writef (psf, "z", fmt_pad) ;
544
 
 
545
 
        if (add_fact_chunk)
546
 
                psf_binheader_writef (psf, "eh88", fact_MARKER16, (sf_count_t) (16 + 8 + 8), psf->sf.frames) ;
547
 
 
548
 
        psf_binheader_writef (psf, "eh8", data_MARKER16, psf->datalength + 24) ;
549
 
        psf_fwrite (psf->header, psf->headindex, 1, psf) ;
550
 
 
551
 
        if (psf->error)
552
 
                return psf->error ;
553
 
 
554
 
        psf->dataoffset = psf->headindex ;
555
 
 
556
 
        if (current > 0)
557
 
                psf_fseek (psf, current, SEEK_SET) ;
558
 
 
559
 
        return psf->error ;
560
 
} /* w64_write_header */
561
 
 
562
 
static int
563
 
w64_close (SF_PRIVATE *psf)
564
 
{
565
 
        if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
566
 
                w64_write_header (psf, SF_TRUE) ;
567
 
 
568
 
        return 0 ;
569
 
} /* w64_close */
570
 
 
571
 
 
572
 
/*
573
 
** Do not edit or modify anything in this comment block.
574
 
** The arch-tag line is a file identity tag for the GNU Arch
575
 
** revision control system.
576
 
**
577
 
** arch-tag: 9aa4e141-538a-4dd9-99c9-b3f0f2dd4f4a
578
 
*/