2
** Copyright (C) 1999-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
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.
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.
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.
31
/*------------------------------------------------------------------------------
32
** W64 files use 16 byte markers as opposed to the four byte marker of
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
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) )
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) }
50
#define riff_HASH16 MAKE_HASH16 ('r', 'i', 'f', 'f', 0x2E, 0x91, 0xCF, 0x11, 0xA5, \
51
0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00)
53
#define wave_HASH16 MAKE_HASH16 ('w', 'a', 'v', 'e', 0xF3, 0xAC, 0xD3, 0x11, \
54
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A)
56
#define fmt_HASH16 MAKE_HASH16 ('f', 'm', 't', ' ', 0xF3, 0xAC, 0xD3, 0x11, \
57
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A)
59
#define fact_HASH16 MAKE_HASH16 ('f', 'a', 'c', 't', 0xF3, 0xAC, 0xD3, 0x11, \
60
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A)
62
#define data_HASH16 MAKE_HASH16 ('d', 'a', 't', 'a', 0xF3, 0xAC, 0xD3, 0x11, \
63
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A)
65
#define ACID_HASH16 MAKE_HASH16 (0x6D, 0x07, 0x1C, 0xEA, 0xA3, 0xEF, 0x78, 0x4C, \
66
0x90, 0x57, 0x7F, 0x79, 0xEE, 0x25, 0x2A, 0xAE)
68
MAKE_MARKER16 (riff_MARKER16, 'r', 'i', 'f', 'f', 0x2E, 0x91, 0xCF, 0x11,
69
0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00) ;
72
MAKE_MARKER16 (wave_MARKER16, 'w', 'a', 'v', 'e', 0xF3, 0xAC, 0xD3, 0x11,
73
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ;
75
MAKE_MARKER16 (fmt_MARKER16, 'f', 'm', 't', ' ', 0xF3, 0xAC, 0xD3, 0x11,
76
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ;
78
MAKE_MARKER16 (fact_MARKER16, 'f', 'a', 'c', 't', 0xF3, 0xAC, 0xD3, 0x11,
79
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ;
81
MAKE_MARKER16 (data_MARKER16, 'd', 'a', 't', 'a', 0xF3, 0xAC, 0xD3, 0x11,
82
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ;
92
/*------------------------------------------------------------------------------
93
* Private static functions.
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) ;
100
/*------------------------------------------------------------------------------
105
w64_open (SF_PRIVATE *psf)
106
{ int subformat, error, blockalign = 0, framesperblock = 0 ;
108
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR &&psf->filelength > 0))
109
{ if ((error = w64_read_header (psf, &blockalign, &framesperblock)))
113
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_W64)
114
return SFE_BAD_OPEN_FORMAT ;
116
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
118
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
120
return SFE_NO_PIPE_WRITE ;
122
psf->endian = SF_ENDIAN_LITTLE ; /* All W64 files are little endian. */
124
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
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 ;
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 */
138
if ((error = w64_write_header (psf, SF_FALSE)))
141
psf->write_header = w64_write_header ;
144
psf->container_close = w64_close ;
147
{ case SF_FORMAT_PCM_U8 :
148
error = pcm_init (psf) ;
151
case SF_FORMAT_PCM_16 :
152
case SF_FORMAT_PCM_24 :
153
case SF_FORMAT_PCM_32 :
154
error = pcm_init (psf) ;
157
case SF_FORMAT_ULAW :
158
error = ulaw_init (psf) ;
161
case SF_FORMAT_ALAW :
162
error = alaw_init (psf) ;
165
/* Lite remove start */
166
case SF_FORMAT_FLOAT :
167
error = float32_init (psf) ;
170
case SF_FORMAT_DOUBLE :
171
error = double64_init (psf) ;
174
case SF_FORMAT_IMA_ADPCM :
175
error = wav_w64_ima_init (psf, blockalign, framesperblock) ;
178
case SF_FORMAT_MS_ADPCM :
179
error = wav_w64_msadpcm_init (psf, blockalign, framesperblock) ;
181
/* Lite remove end */
183
case SF_FORMAT_GSM610 :
184
error = gsm610_init (psf) ;
187
default : return SFE_UNIMPLEMENTED ;
193
/*=========================================================================
194
** Private functions.
198
w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
200
int dword = 0, marker, format = 0 ;
201
sf_count_t chunk_size, bytesread = 0 ;
202
int parsestage = 0, error, done = 0 ;
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) ;
209
{ /* Read the 4 byte marker and jump 12 bytes. */
210
bytesread += psf_binheader_readf (psf, "h", &marker) ;
216
return SFE_W64_NO_RIFF ;
218
bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ;
220
if (psf->filelength < chunk_size)
221
psf_log_printf (psf, "riff : %D (should be %D)\n", chunk_size, psf->filelength) ;
223
psf_log_printf (psf, "riff : %D\n", chunk_size) ;
225
parsestage |= HAVE_riff ;
229
psf_log_printf (psf, "Looks like an ACID file. Exiting.\n") ;
230
return SFE_UNIMPLEMENTED ;
233
if ((parsestage & HAVE_riff) != HAVE_riff)
234
return SFE_W64_NO_WAVE ;
235
psf_log_printf (psf, "wave\n") ;
236
parsestage |= HAVE_wave ;
240
if ((parsestage & (HAVE_riff | HAVE_wave)) != (HAVE_riff | HAVE_wave))
241
return SFE_W64_NO_FMT ;
243
bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ;
244
psf_log_printf (psf, " fmt : %D\n", chunk_size) ;
246
/* size of 16 byte marker and 8 byte chunk_size value. */
249
if ((error = wav_w64_read_fmt_chunk (psf, &wav_fmt, (int) chunk_size)))
253
psf_binheader_readf (psf, "j", 8 - (chunk_size % 8)) ;
255
format = wav_fmt.format ;
256
parsestage |= HAVE_fmt ;
260
{ sf_count_t frames ;
262
psf_binheader_readf (psf, "e88", &chunk_size, &frames) ;
263
psf_log_printf (psf, " fact : %D\n frames : %D\n",
264
chunk_size, frames) ;
270
if ((parsestage & (HAVE_riff | HAVE_wave | HAVE_fmt)) != (HAVE_riff | HAVE_wave | HAVE_fmt))
271
return SFE_W64_NO_DATA ;
273
psf_binheader_readf (psf, "e8", &chunk_size) ;
275
psf->dataoffset = psf_ftell (psf) ;
277
psf->datalength = chunk_size - 24 ;
280
chunk_size += 8 - (chunk_size % 8) ;
282
psf_log_printf (psf, "data : %D\n", chunk_size) ;
284
parsestage |= HAVE_data ;
286
if (! psf->sf.seekable)
289
/* Seek past data and continue reading header. */
290
psf_fseek (psf, chunk_size, SEEK_CUR) ;
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) ;
299
psf_log_printf (psf, "*** Unknown chunk marker : %X. Exiting parser.\n", marker) ;
302
} ; /* switch (dword) */
304
if (psf->sf.seekable == 0 && (parsestage & HAVE_data))
307
if (psf_ftell (psf) >= (psf->filelength - (2 * SIGNED_SIZEOF (dword))))
311
if (! psf->dataoffset)
312
return SFE_W64_NO_DATA ;
314
psf->endian = SF_ENDIAN_LITTLE ; /* All WAV files are little endian. */
316
if (psf_ftell (psf) != psf->dataoffset)
317
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
320
{ if (psf->filelength - psf->dataoffset < psf->datalength)
321
psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
323
psf->sf.frames = psf->datalength / psf->blockwidth ;
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) ;
333
case WAVE_FORMAT_MULAW :
334
psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ULAW) ;
337
case WAVE_FORMAT_ALAW :
338
psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ALAW) ;
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 ;
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 ;
353
case WAVE_FORMAT_GSM610 :
354
psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_GSM610) ;
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 ;
362
default : return SFE_UNIMPLEMENTED ;
366
} /* w64_read_header */
369
w64_write_header (SF_PRIVATE *psf, int calc_length)
370
{ sf_count_t fmt_size, current ;
372
int subformat, add_fact_chunk = SF_FALSE ;
374
current = psf_ftell (psf) ;
377
{ psf->filelength = psf_get_filelen (psf) ;
379
psf->datalength = psf->filelength - psf->dataoffset ;
381
psf->datalength -= psf->filelength - psf->dataend ;
384
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
387
/* Reset the current header length to zero. */
388
psf->header [0] = 0 ;
390
psf_fseek (psf, 0, SEEK_SET) ;
392
/* riff marker, length, wave and 'fmt ' markers. */
393
psf_binheader_writef (psf, "eh8hh", riff_MARKER16, psf->filelength - 8, wave_MARKER16, fmt_MARKER16) ;
395
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
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 ;
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) ;
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 ;
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) ;
427
add_fact_chunk = SF_TRUE ;
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 ;
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) ;
442
add_fact_chunk = SF_TRUE ;
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 ;
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) ;
457
add_fact_chunk = SF_TRUE ;
460
/* Lite remove start */
461
case SF_FORMAT_IMA_ADPCM :
462
{ int blockalign, framesperblock, bytespersec ;
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 ;
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 ;
473
/* fmt : size, WAV format type, channels. */
474
psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_IMA_ADPCM, psf->sf.channels) ;
476
/* fmt : samplerate, bytespersec. */
477
psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ;
479
/* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
480
psf_binheader_writef (psf, "e2222", blockalign, 4, 2, framesperblock) ;
483
add_fact_chunk = SF_TRUE ;
486
case SF_FORMAT_MS_ADPCM :
487
{ int blockalign, framesperblock, bytespersec, extrabytes ;
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 ;
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 ;
499
/* fmt : size, W64 format type, channels. */
500
psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_MS_ADPCM, psf->sf.channels) ;
502
/* fmt : samplerate, bytespersec. */
503
psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ;
505
/* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
506
psf_binheader_writef (psf, "e22222", blockalign, 4, extrabytes, framesperblock, 7) ;
508
msadpcm_write_adapt_coeffs (psf) ;
511
add_fact_chunk = SF_TRUE ;
513
/* Lite remove end */
515
case SF_FORMAT_GSM610 :
518
bytespersec = (psf->sf.samplerate * WAV_W64_GSM610_BLOCKSIZE) / WAV_W64_GSM610_SAMPLES ;
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 ;
525
/* fmt : size, WAV format type, channels. */
526
psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_GSM610, psf->sf.channels) ;
528
/* fmt : samplerate, bytespersec. */
529
psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ;
531
/* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
532
psf_binheader_writef (psf, "e2222", WAV_W64_GSM610_BLOCKSIZE, 0, 2, WAV_W64_GSM610_SAMPLES) ;
535
add_fact_chunk = SF_TRUE ;
538
default : return SFE_UNIMPLEMENTED ;
541
/* Pad to 8 bytes with zeros. */
543
psf_binheader_writef (psf, "z", fmt_pad) ;
546
psf_binheader_writef (psf, "eh88", fact_MARKER16, (sf_count_t) (16 + 8 + 8), psf->sf.frames) ;
548
psf_binheader_writef (psf, "eh8", data_MARKER16, psf->datalength + 24) ;
549
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
554
psf->dataoffset = psf->headindex ;
557
psf_fseek (psf, current, SEEK_SET) ;
560
} /* w64_write_header */
563
w64_close (SF_PRIVATE *psf)
565
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
566
w64_write_header (psf, SF_TRUE) ;
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.
577
** arch-tag: 9aa4e141-538a-4dd9-99c9-b3f0f2dd4f4a