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

« back to all changes in this revision

Viewing changes to lib-src/libsndfile/src/svx.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-2004 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 <stdarg.h>
25
 
 
26
 
#include "sndfile.h"
27
 
#include "sfendian.h"
28
 
#include "common.h"
29
 
 
30
 
 
31
 
/*------------------------------------------------------------------------------
32
 
 * Macros to handle big/little endian issues.
33
 
*/
34
 
 
35
 
#define FORM_MARKER     (MAKE_MARKER ('F', 'O', 'R', 'M'))
36
 
#define SVX8_MARKER     (MAKE_MARKER ('8', 'S', 'V', 'X'))
37
 
#define SV16_MARKER     (MAKE_MARKER ('1', '6', 'S', 'V'))
38
 
#define VHDR_MARKER     (MAKE_MARKER ('V', 'H', 'D', 'R'))
39
 
#define BODY_MARKER     (MAKE_MARKER ('B', 'O', 'D', 'Y'))
40
 
 
41
 
#define ATAK_MARKER     (MAKE_MARKER ('A', 'T', 'A', 'K'))
42
 
#define RLSE_MARKER     (MAKE_MARKER ('R', 'L', 'S', 'E'))
43
 
 
44
 
#define c_MARKER        (MAKE_MARKER ('(', 'c', ')', ' '))
45
 
#define NAME_MARKER     (MAKE_MARKER ('N', 'A', 'M', 'E'))
46
 
#define AUTH_MARKER     (MAKE_MARKER ('A', 'U', 'T', 'H'))
47
 
#define ANNO_MARKER     (MAKE_MARKER ('A', 'N', 'N', 'O'))
48
 
#define CHAN_MARKER     (MAKE_MARKER ('C', 'H', 'A', 'N'))
49
 
 
50
 
/*------------------------------------------------------------------------------
51
 
 * Typedefs for file chunks.
52
 
*/
53
 
 
54
 
typedef struct
55
 
{       unsigned int    oneShotHiSamples, repeatHiSamples, samplesPerHiCycle ;
56
 
        unsigned short  samplesPerSec ;
57
 
        unsigned char   octave, compression ;
58
 
        unsigned int    volume ;
59
 
} VHDR_CHUNK ;
60
 
 
61
 
enum {
62
 
        HAVE_FORM       = 0x01,
63
 
 
64
 
        HAVE_SVX        = 0x02,
65
 
        HAVE_VHDR       = 0x04,
66
 
        HAVE_BODY       = 0x08
67
 
} ;
68
 
 
69
 
/*------------------------------------------------------------------------------
70
 
 * Private static functions.
71
 
*/
72
 
 
73
 
static int      svx_close       (SF_PRIVATE *psf) ;
74
 
static int      svx_write_header (SF_PRIVATE *psf, int calc_length) ;
75
 
static int      svx_read_header (SF_PRIVATE *psf) ;
76
 
 
77
 
/*------------------------------------------------------------------------------
78
 
** Public function.
79
 
*/
80
 
 
81
 
int
82
 
svx_open        (SF_PRIVATE *psf)
83
 
{       int error ;
84
 
 
85
 
        if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
86
 
        {       if ((error = svx_read_header (psf)))
87
 
                        return error ;
88
 
 
89
 
                psf->endian = SF_ENDIAN_BIG ;                   /* All SVX files are big endian. */
90
 
 
91
 
                psf->blockwidth = psf->sf.channels * psf->bytewidth ;
92
 
                if (psf->blockwidth)
93
 
                        psf->sf.frames = psf->datalength / psf->blockwidth ;
94
 
 
95
 
                psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
96
 
                } ;
97
 
 
98
 
        if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
99
 
        {       if (psf->is_pipe)
100
 
                        return SFE_NO_PIPE_WRITE ;
101
 
 
102
 
                if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SVX)
103
 
                        return  SFE_BAD_OPEN_FORMAT ;
104
 
 
105
 
                psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
106
 
 
107
 
                if (psf->endian == SF_ENDIAN_LITTLE || (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU))
108
 
                        return SFE_BAD_ENDIAN ;
109
 
 
110
 
                psf->endian = SF_ENDIAN_BIG ;                   /* All SVX files are big endian. */
111
 
 
112
 
                error = svx_write_header (psf, SF_FALSE) ;
113
 
                if (error)
114
 
                        return error ;
115
 
 
116
 
                psf->write_header = svx_write_header ;
117
 
                } ;
118
 
 
119
 
        psf->container_close = svx_close ;
120
 
 
121
 
        if ((error = pcm_init (psf)))
122
 
                return error ;
123
 
 
124
 
        return 0 ;
125
 
} /* svx_open */
126
 
 
127
 
/*------------------------------------------------------------------------------
128
 
*/
129
 
 
130
 
static int
131
 
svx_read_header (SF_PRIVATE *psf)
132
 
{       VHDR_CHUNK              vhdr ;
133
 
        unsigned int    FORMsize, vhdrsize, dword, marker ;
134
 
        int                             filetype = 0, parsestage = 0, done = 0 ;
135
 
        int                     bytecount = 0, channels ;
136
 
 
137
 
        memset (&vhdr, 0, sizeof (vhdr)) ;
138
 
        psf_binheader_readf (psf, "p", 0) ;
139
 
 
140
 
        /* Set default number of channels. Currently can't handle stereo SVX files. */
141
 
        psf->sf.channels = 1 ;
142
 
 
143
 
        psf->sf.format = SF_FORMAT_SVX ;
144
 
 
145
 
        while (! done)
146
 
        {       psf_binheader_readf (psf, "m", &marker) ;
147
 
                switch (marker)
148
 
                {       case FORM_MARKER :
149
 
                                        if (parsestage)
150
 
                                                return SFE_SVX_NO_FORM ;
151
 
 
152
 
                                        psf_binheader_readf (psf, "E4", &FORMsize) ;
153
 
 
154
 
                                        if (FORMsize != psf->filelength - 2 * sizeof (dword))
155
 
                                        {       dword = psf->filelength - 2 * sizeof (dword) ;
156
 
                                                psf_log_printf (psf, "FORM : %d (should be %d)\n", FORMsize, dword) ;
157
 
                                                FORMsize = dword ;
158
 
                                                }
159
 
                                        else
160
 
                                                psf_log_printf (psf, "FORM : %d\n", FORMsize) ;
161
 
                                        parsestage |= HAVE_FORM ;
162
 
                                        break ;
163
 
 
164
 
                        case SVX8_MARKER :
165
 
                        case SV16_MARKER :
166
 
                                        if (! (parsestage & HAVE_FORM))
167
 
                                                return SFE_SVX_NO_FORM ;
168
 
                                        filetype = marker ;
169
 
                                        psf_log_printf (psf, " %M\n", marker) ;
170
 
                                        parsestage |= HAVE_SVX ;
171
 
                                        break ;
172
 
 
173
 
                        case VHDR_MARKER :
174
 
                                        if (! (parsestage & (HAVE_FORM | HAVE_SVX)))
175
 
                                                return SFE_SVX_NO_FORM ;
176
 
 
177
 
                                        psf_binheader_readf (psf, "E4", &vhdrsize) ;
178
 
 
179
 
                                        psf_log_printf (psf, " VHDR : %d\n", vhdrsize) ;
180
 
 
181
 
                                        psf_binheader_readf (psf, "E4442114", &(vhdr.oneShotHiSamples), &(vhdr.repeatHiSamples),
182
 
                                                &(vhdr.samplesPerHiCycle), &(vhdr.samplesPerSec), &(vhdr.octave), &(vhdr.compression),
183
 
                                                &(vhdr.volume)) ;
184
 
 
185
 
                                        psf_log_printf (psf, "  OneShotHiSamples  : %d\n", vhdr.oneShotHiSamples) ;
186
 
                                        psf_log_printf (psf, "  RepeatHiSamples   : %d\n", vhdr.repeatHiSamples) ;
187
 
                                        psf_log_printf (psf, "  samplesPerHiCycle : %d\n", vhdr.samplesPerHiCycle) ;
188
 
                                        psf_log_printf (psf, "  Sample Rate       : %d\n", vhdr.samplesPerSec) ;
189
 
                                        psf_log_printf (psf, "  Octave            : %d\n", vhdr.octave) ;
190
 
 
191
 
                                        psf_log_printf (psf, "  Compression       : %d => ", vhdr.compression) ;
192
 
 
193
 
                                        switch (vhdr.compression)
194
 
                                        {       case 0 : psf_log_printf (psf, "None.\n") ;
195
 
                                                                break ;
196
 
                                                case 1 : psf_log_printf (psf, "Fibonacci delta\n") ;
197
 
                                                                break ;
198
 
                                                case 2 : psf_log_printf (psf, "Exponential delta\n") ;
199
 
                                                                break ;
200
 
                                                } ;
201
 
 
202
 
                                        psf_log_printf (psf, "  Volume            : %d\n", vhdr.volume) ;
203
 
 
204
 
                                        psf->sf.samplerate      = vhdr.samplesPerSec ;
205
 
 
206
 
                                        if (filetype == SVX8_MARKER)
207
 
                                        {       psf->sf.format |= SF_FORMAT_PCM_S8 ;
208
 
                                                psf->bytewidth = 1 ;
209
 
                                                }
210
 
                                        else if (filetype == SV16_MARKER)
211
 
                                        {       psf->sf.format |= SF_FORMAT_PCM_16 ;
212
 
                                                psf->bytewidth = 2 ;
213
 
                                                } ;
214
 
 
215
 
                                        parsestage |= HAVE_VHDR ;
216
 
                                        break ;
217
 
 
218
 
                        case BODY_MARKER :
219
 
                                        if (! (parsestage & HAVE_VHDR))
220
 
                                                return SFE_SVX_NO_BODY ;
221
 
 
222
 
                                        psf_binheader_readf (psf, "E4", &dword) ;
223
 
                                        psf->datalength = dword ;
224
 
 
225
 
                                        psf->dataoffset = psf_ftell (psf) ;
226
 
 
227
 
                                        if (psf->datalength > psf->filelength - psf->dataoffset)
228
 
                                        {       psf_log_printf (psf, " BODY : %D (should be %D)\n", psf->datalength, psf->filelength - psf->dataoffset) ;
229
 
                                                psf->datalength = psf->filelength - psf->dataoffset ;
230
 
                                                }
231
 
                                        else
232
 
                                                psf_log_printf (psf, " BODY : %D\n", psf->datalength) ;
233
 
 
234
 
                                        parsestage |= HAVE_BODY ;
235
 
 
236
 
                                        if (! psf->sf.seekable)
237
 
                                                break ;
238
 
 
239
 
                                        psf_fseek (psf, psf->datalength, SEEK_CUR) ;
240
 
                                        break ;
241
 
 
242
 
                        case NAME_MARKER :
243
 
                                        if (! (parsestage & HAVE_SVX))
244
 
                                                return SFE_SVX_NO_FORM ;
245
 
 
246
 
                                        psf_binheader_readf (psf, "E4", &dword) ;
247
 
 
248
 
                                        psf_log_printf (psf, " %M : %d\n", marker, dword) ;
249
 
 
250
 
                                        if (strlen (psf->filename) != dword)
251
 
                                        {       if (dword > sizeof (psf->filename) - 1)
252
 
                                                        return SFE_SVX_BAD_NAME_LENGTH ;
253
 
 
254
 
                                                psf_binheader_readf (psf, "b", psf->filename, dword) ;
255
 
                                                psf->filename [dword] = 0 ;
256
 
                                                }
257
 
                                        else
258
 
                                                psf_binheader_readf (psf, "j", dword) ;
259
 
                                        break ;
260
 
 
261
 
                        case ANNO_MARKER :
262
 
                                        if (! (parsestage & HAVE_SVX))
263
 
                                                return SFE_SVX_NO_FORM ;
264
 
 
265
 
                                        psf_binheader_readf (psf, "E4", &dword) ;
266
 
 
267
 
                                        psf_log_printf (psf, " %M : %d\n", marker, dword) ;
268
 
 
269
 
                                        psf_binheader_readf (psf, "j", dword) ;
270
 
                                        break ;
271
 
 
272
 
                        case CHAN_MARKER :
273
 
                                        if (! (parsestage & HAVE_SVX))
274
 
                                                return SFE_SVX_NO_FORM ;
275
 
 
276
 
                                        psf_binheader_readf (psf, "E4", &dword) ;
277
 
 
278
 
                                        psf_log_printf (psf, " %M : %d\n", marker, dword) ;
279
 
 
280
 
                                        bytecount += psf_binheader_readf (psf, "E4", &channels) ;
281
 
                                        psf->sf.channels = channels ;
282
 
 
283
 
                                        psf_log_printf (psf, "  Channels : %d\n", channels) ;
284
 
 
285
 
                                        psf_binheader_readf (psf, "j", dword - bytecount) ;
286
 
                                        break ;
287
 
 
288
 
 
289
 
                        case AUTH_MARKER :
290
 
                        case c_MARKER :
291
 
                                        if (! (parsestage & HAVE_SVX))
292
 
                                                return SFE_SVX_NO_FORM ;
293
 
 
294
 
                                        psf_binheader_readf (psf, "E4", &dword) ;
295
 
 
296
 
                                        psf_log_printf (psf, " %M : %d\n", marker, dword) ;
297
 
 
298
 
                                        psf_binheader_readf (psf, "j", dword) ;
299
 
                                        break ;
300
 
 
301
 
                        default :
302
 
                                        if (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF)
303
 
                                                && isprint ((marker >> 8) & 0xFF) && isprint (marker & 0xFF))
304
 
                                        {       psf_binheader_readf (psf, "E4", &dword) ;
305
 
 
306
 
                                                psf_log_printf (psf, "%M : %d (unknown marker)\n", marker, dword) ;
307
 
 
308
 
                                                psf_binheader_readf (psf, "j", dword) ;
309
 
                                                break ;
310
 
                                                } ;
311
 
                                        if ((dword = psf_ftell (psf)) & 0x03)
312
 
                                        {       psf_log_printf (psf, "  Unknown chunk marker at position %d. Resynching.\n", dword - 4) ;
313
 
 
314
 
                                                psf_binheader_readf (psf, "j", -3) ;
315
 
                                                break ;
316
 
                                                } ;
317
 
                                        psf_log_printf (psf, "*** Unknown chunk marker : %X. Exiting parser.\n", marker) ;
318
 
                                        done = 1 ;
319
 
                        } ;     /* switch (marker) */
320
 
 
321
 
                if (! psf->sf.seekable && (parsestage & HAVE_BODY))
322
 
                        break ;
323
 
 
324
 
                if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (dword))
325
 
                        break ;
326
 
                } ; /* while (1) */
327
 
 
328
 
        if (vhdr.compression)
329
 
                return SFE_SVX_BAD_COMP ;
330
 
 
331
 
        if (psf->dataoffset <= 0)
332
 
                return SFE_SVX_NO_DATA ;
333
 
 
334
 
        return 0 ;
335
 
} /* svx_read_header */
336
 
 
337
 
static int
338
 
svx_close (SF_PRIVATE *psf)
339
 
{
340
 
        if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
341
 
                svx_write_header (psf, SF_TRUE) ;
342
 
 
343
 
        return 0 ;
344
 
} /* svx_close */
345
 
 
346
 
static int
347
 
svx_write_header (SF_PRIVATE *psf, int calc_length)
348
 
{       static  char    annotation      [] = "libsndfile by Erik de Castro Lopo\0\0\0" ;
349
 
        sf_count_t      current ;
350
 
 
351
 
        current = psf_ftell (psf) ;
352
 
 
353
 
        if (calc_length)
354
 
        {       psf->filelength = psf_get_filelen (psf) ;
355
 
 
356
 
                psf->datalength = psf->filelength - psf->dataoffset ;
357
 
 
358
 
                if (psf->dataend)
359
 
                        psf->datalength -= psf->filelength - psf->dataend ;
360
 
 
361
 
                psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
362
 
                } ;
363
 
 
364
 
        psf->header [0] = 0 ;
365
 
        psf->headindex = 0 ;
366
 
        psf_fseek (psf, 0, SEEK_SET) ;
367
 
 
368
 
        /* FORM marker and FORM size. */
369
 
        psf_binheader_writef (psf, "Etm8", FORM_MARKER, (psf->filelength < 8) ?
370
 
                        psf->filelength * 0 : psf->filelength - 8) ;
371
 
 
372
 
        psf_binheader_writef (psf, "m", (psf->bytewidth == 1) ? SVX8_MARKER : SV16_MARKER) ;
373
 
 
374
 
        /* VHDR chunk. */
375
 
        psf_binheader_writef (psf, "Em4", VHDR_MARKER, sizeof (VHDR_CHUNK)) ;
376
 
        /* VHDR : oneShotHiSamples, repeatHiSamples, samplesPerHiCycle */
377
 
        psf_binheader_writef (psf, "E444", psf->sf.frames, 0, 0) ;
378
 
        /* VHDR : samplesPerSec, octave, compression */
379
 
        psf_binheader_writef (psf, "E211", psf->sf.samplerate, 1, 0) ;
380
 
        /* VHDR : volume */
381
 
        psf_binheader_writef (psf, "E4", (psf->bytewidth == 1) ? 0xFF : 0xFFFF) ;
382
 
 
383
 
        /* Filename and annotation strings. */
384
 
        psf_binheader_writef (psf, "Emsms", NAME_MARKER, psf->filename, ANNO_MARKER, annotation) ;
385
 
 
386
 
        /* BODY marker and size. */
387
 
        psf_binheader_writef (psf, "Etm8", BODY_MARKER, (psf->datalength < 0) ?
388
 
                        psf->datalength * 0 : psf->datalength) ;
389
 
 
390
 
        psf_fwrite (psf->header, psf->headindex, 1, psf) ;
391
 
 
392
 
        if (psf->error)
393
 
                return psf->error ;
394
 
 
395
 
        psf->dataoffset = psf->headindex ;
396
 
 
397
 
        if (current > 0)
398
 
                psf_fseek (psf, current, SEEK_SET) ;
399
 
 
400
 
        return psf->error ;
401
 
} /* svx_write_header */
402
 
 
403
 
 
404
 
/*
405
 
** Do not edit or modify anything in this comment block.
406
 
** The arch-tag line is a file identity tag for the GNU Arch 
407
 
** revision control system.
408
 
**
409
 
** arch-tag: a80ab6fb-7d75-4d32-a6b0-0061a3f05d95
410
 
*/