~ubuntu-branches/ubuntu/feisty/muse/feisty

« back to all changes in this revision

Viewing changes to sf/wav.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2002-04-23 17:28:23 UTC
  • Revision ID: james.westby@ubuntu.com-20020423172823-w8yplzr81a759xa3
Tags: upstream-0.5.2
ImportĀ upstreamĀ versionĀ 0.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//=========================================================
 
2
//  MusE
 
3
//  Linux Music Editor
 
4
//  $Id: wav.cpp,v 1.2 2002/02/13 11:42:56 muse Exp $
 
5
//
 
6
//  (C) Copyright 2001 Werner Schweer (ws@seh.de)
 
7
//  based on libsndfile:
 
8
//  Copyright (C) 1999-2000 Erik de Castro Lopo <erikd@zip.com.au>
 
9
//=========================================================
 
10
 
 
11
#include        <stdio.h>
 
12
#include        <unistd.h>
 
13
#include        <string.h>
 
14
#include        <ctype.h>
 
15
 
 
16
#include        "sndfile.h"
 
17
#include        "config.h"
 
18
#include        "sfendian.h"
 
19
#include        "pcm.h"
 
20
#include        "wav.h"
 
21
 
 
22
/*---------------------------------------
 
23
** List of known WAV format tags
 
24
*/
 
25
 
 
26
enum
 
27
      { 
 
28
        WAVE_FORMAT_UNKNOWN                             = 0x0000,               /* Microsoft Corporation */
 
29
        WAVE_FORMAT_PCM                     = 0x0001,           /* Microsoft PCM format */
 
30
 
 
31
        WAVE_FORMAT_MS_ADPCM                    = 0x0002,               /* Microsoft ADPCM */
 
32
        WAVE_FORMAT_IEEE_FLOAT                  = 0x0003,               /* Micrososft 32 bit float format */
 
33
        
 
34
        WAVE_FORMAT_IBM_CVSD                    = 0x0005,               /* IBM Corporation */
 
35
        WAVE_FORMAT_ALAW                                = 0x0006,               /* Microsoft Corporation */
 
36
        WAVE_FORMAT_MULAW                               = 0x0007,               /* Microsoft Corporation */
 
37
        WAVE_FORMAT_OKI_ADPCM                   = 0x0010,               /* OKI */
 
38
        WAVE_FORMAT_IMA_ADPCM                   = 0x0011,               /* Intel Corporation */
 
39
        WAVE_FORMAT_MEDIASPACE_ADPCM    = 0x0012,               /* Videologic */
 
40
        WAVE_FORMAT_SIERRA_ADPCM                = 0x0013,               /* Sierra Semiconductor Corp */
 
41
        WAVE_FORMAT_G723_ADPCM                  = 0x0014,               /* Antex Electronics Corporation */
 
42
        WAVE_FORMAT_DIGISTD                             = 0x0015,               /* DSP Solutions, Inc. */
 
43
        WAVE_FORMAT_DIGIFIX                             = 0x0016,               /* DSP Solutions, Inc. */
 
44
        WAVE_FORMAT_DIALOGIC_OKI_ADPCM  = 0x0017,               /*  Dialogic Corporation  */
 
45
        WAVE_FORMAT_MEDIAVISION_ADPCM   = 0x0018,               /*  Media Vision, Inc. */
 
46
 
 
47
        WAVE_FORMAT_YAMAHA_ADPCM                = 0x0020,               /* Yamaha Corporation of America */
 
48
        WAVE_FORMAT_SONARC                              = 0x0021,               /* Speech Compression */
 
49
        WAVE_FORMAT_DSPGROUP_TRUESPEECH = 0x0022,               /* DSP Group, Inc */
 
50
        WAVE_FORMAT_ECHOSC1                             = 0x0023,               /* Echo Speech Corporation */
 
51
        WAVE_FORMAT_AUDIOFILE_AF18      = 0x0024,               /* Audiofile, Inc. */
 
52
        WAVE_FORMAT_APTX                                = 0x0025,               /* Audio Processing Technology */
 
53
        WAVE_FORMAT_AUDIOFILE_AF10      = 0x0026,               /* Audiofile, Inc. */
 
54
 
 
55
        WAVE_FORMAT_DOLBY_AC2                   = 0x0030,               /* Dolby Laboratories */
 
56
        WAVE_FORMAT_GSM610                              = 0x0031,               /* Microsoft Corporation */
 
57
        WAVE_FORMAT_MSNAUDIO                    = 0x0032,               /* Microsoft Corporation */
 
58
        WAVE_FORMAT_ANTEX_ADPCME                = 0x0033,               /* Antex Electronics Corporation */
 
59
        WAVE_FORMAT_CONTROL_RES_VQLPC   = 0x0034,               /* Control Resources Limited */
 
60
        WAVE_FORMAT_DIGIREAL                    = 0x0035,               /* DSP Solutions, Inc. */
 
61
        WAVE_FORMAT_DIGIADPCM                   = 0x0036,               /* DSP Solutions, Inc. */
 
62
        WAVE_FORMAT_CONTROL_RES_CR10    = 0x0037,               /* Control Resources Limited */
 
63
        WAVE_FORMAT_NMS_VBXADPCM                = 0x0038,               /* Natural MicroSystems */
 
64
        WAVE_FORMAT_ROCKWELL_ADPCM              = 0x003B,               /* Rockwell International */
 
65
        WAVE_FORMAT_ROCKWELL_DIGITALK   = 0x003C,               /* Rockwell International */
 
66
 
 
67
        WAVE_FORMAT_G721_ADPCM                  = 0x0040,               /* Antex Electronics Corporation */
 
68
        WAVE_FORMAT_MPEG                                = 0x0050,               /* Microsoft Corporation */
 
69
 
 
70
        WAVE_FORMAT_MPEGLAYER3                  = 0x0055,               /* MPEG 3 Layer 1 */
 
71
 
 
72
        IBM_FORMAT_MULAW                                = 0x0101,               /* IBM mu-law format */
 
73
        IBM_FORMAT_ALAW                                 = 0x0102,               /* IBM a-law format */
 
74
        IBM_FORMAT_ADPCM                                = 0x0103,               /* IBM AVC Adaptive Differential PCM format */
 
75
 
 
76
        WAVE_FORMAT_CREATIVE_ADPCM              = 0x0200,               /* Creative Labs, Inc */
 
77
 
 
78
        WAVE_FORMAT_FM_TOWNS_SND                = 0x0300,               /* Fujitsu Corp. */
 
79
        WAVE_FORMAT_OLIGSM                              = 0x1000,               /* Ing C. Olivetti & C., S.p.A. */
 
80
        WAVE_FORMAT_OLIADPCM                    = 0x1001,               /* Ing C. Olivetti & C., S.p.A. */
 
81
        WAVE_FORMAT_OLICELP                             = 0x1002,               /* Ing C. Olivetti & C., S.p.A. */
 
82
        WAVE_FORMAT_OLISBC                              = 0x1003,               /* Ing C. Olivetti & C., S.p.A. */
 
83
        WAVE_FORMAT_OLIOPR                              = 0x1004,               /* Ing C. Olivetti & C., S.p.A. */
 
84
 
 
85
        WAVE_FORMAT_EXTENSIBLE                  = 0xFFFE
 
86
      };
 
87
 
 
88
/*------------------------------------------------------------------------------
 
89
 * Macros to handle big/little endian issues.
 
90
 */
 
91
 
 
92
#if (CPU_IS_LITTLE_ENDIAN == 1)
 
93
#       define  MAKE_MARKER(a,b,c,d)            ((a)|((b)<<8)|((c)<<16)|((d)<<24))
 
94
#elif (CPU_IS_BIG_ENDIAN == 1)
 
95
#       define  MAKE_MARKER(a,b,c,d)            (((a)<<24)|((b)<<16)|((c)<<8)|(d))
 
96
#else
 
97
#       error "Cannot determine endian-ness of processor."
 
98
#endif
 
99
 
 
100
#define RIFF_MARKER     (MAKE_MARKER ('R', 'I', 'F', 'F'))
 
101
#define WAVE_MARKER     (MAKE_MARKER ('W', 'A', 'V', 'E'))
 
102
#define fmt_MARKER      (MAKE_MARKER ('f', 'm', 't', ' '))
 
103
#define data_MARKER     (MAKE_MARKER ('d', 'a', 't', 'a'))
 
104
#define cue_MARKER      (MAKE_MARKER ('c', 'u', 'e', ' '))
 
105
#define LIST_MARKER     (MAKE_MARKER ('L', 'I', 'S', 'T'))
 
106
#define slnt_MARKER     (MAKE_MARKER ('s', 'l', 'n', 't'))
 
107
#define wavl_MARKER     (MAKE_MARKER ('w', 'a', 'v', 'l'))
 
108
#define INFO_MARKER     (MAKE_MARKER ('I', 'N', 'F', 'O'))
 
109
#define plst_MARKER     (MAKE_MARKER ('p', 'l', 's', 't'))
 
110
#define adtl_MARKER     (MAKE_MARKER ('a', 'd', 't', 'l'))
 
111
#define labl_MARKER     (MAKE_MARKER ('l', 'a', 'b', 'l'))
 
112
#define note_MARKER     (MAKE_MARKER ('n', 'o', 't', 'e'))
 
113
#define fact_MARKER     (MAKE_MARKER ('f', 'a', 'c', 't'))
 
114
#define smpl_MARKER     (MAKE_MARKER ('s', 'm', 'p', 'l'))
 
115
#define bext_MARKER     (MAKE_MARKER ('b', 'e', 'x', 't'))
 
116
#define MEXT_MARKER     (MAKE_MARKER ('M', 'E', 'X', 'T'))
 
117
#define DISP_MARKER     (MAKE_MARKER ('D', 'I', 'S', 'P'))
 
118
 
 
119
/*------------------------------------------------------------------------------
 
120
 * Private static functions.
 
121
 */
 
122
 
 
123
static void     le2h_wav_fmt (WAV_FMT *fmt);
 
124
static void     h2le_wav_fmt (WAV_FMT *fmt);
 
125
 
 
126
//---------------------------------------------------------
 
127
//   wav_open_read
 
128
//---------------------------------------------------------
 
129
 
 
130
int SndFile::wav_open_read()
 
131
      {
 
132
      WAV_FMT wav_fmt;
 
133
        FACT_CHUNK fact_chunk;
 
134
        unsigned int dword, marker, RIFFsize;
 
135
        int parsestage = 0, error;
 
136
      int _fmt = 0;
 
137
 
 
138
        _seekable = true;
 
139
 
 
140
        for (;;) {
 
141
              fread (&marker, sizeof (marker), 1, _file);
 
142
                switch (marker) {       
 
143
                  case RIFF_MARKER:
 
144
                        if (parsestage != 0)
 
145
                                      return SFE_WAV_NO_RIFF;
 
146
                        fread (&dword, sizeof (dword), 1, _file);
 
147
                                RIFFsize = LE2H_INT(dword);     
 
148
                              if (_filelength  < RIFFsize + 2 * sizeof (dword)) {
 
149
                              dword = _filelength - 2 * sizeof (dword);
 
150
                                        RIFFsize = dword;
 
151
                                        }
 
152
                            parsestage = 1;
 
153
                        break;
 
154
                                        
 
155
                        case WAVE_MARKER:
 
156
                        if (parsestage != 1)
 
157
                                      return SFE_WAV_NO_WAVE;
 
158
                              parsestage = 2;
 
159
                                break;
 
160
                        
 
161
                        case fmt_MARKER:
 
162
                        if (parsestage != 2)
 
163
                                      return SFE_WAV_NO_FMT;
 
164
                              if ((error = read_fmt_chunk (&wav_fmt)))
 
165
                                      return error;
 
166
                        _fmt = wav_fmt.format;
 
167
                              parsestage = 3;
 
168
                        break;
 
169
                                        
 
170
                        case data_MARKER:
 
171
                        if (parsestage < 3)
 
172
                              return SFE_WAV_NO_DATA;
 
173
                        fread(&dword, sizeof (dword), 1, _file);
 
174
                              _datalength = LE2H_INT (dword);
 
175
                                _dataoffset = ftell (_file);
 
176
                        if (_filelength < _dataoffset + _datalength) {  
 
177
                              _datalength = _filelength - _dataoffset;
 
178
                                      }
 
179
 
 
180
                              if (_format == WAVE_FORMAT_MS_ADPCM && _datalength % 2) {
 
181
                                      ++_datalength;
 
182
                                        }
 
183
                
 
184
                              fseek(_file, _datalength, SEEK_CUR);
 
185
                                dword = ftell(_file);
 
186
                                if (dword != _dataoffset + _datalength) {
 
187
                              }
 
188
                              break;
 
189
 
 
190
                        case fact_MARKER:
 
191
                        fread (&dword, sizeof(dword), 1, _file);
 
192
                            dword = LE2H_INT(dword);
 
193
                              fread (&fact_chunk, sizeof (fact_chunk), 1, _file);
 
194
                        if (dword > sizeof (fact_chunk))
 
195
                              fseek (_file, (int) (dword - sizeof (fact_chunk)), SEEK_CUR);
 
196
                        fact_chunk.samples = LE2H_INT (fact_chunk.samples);
 
197
                        break;
 
198
 
 
199
                        case cue_MARKER:
 
200
                        case LIST_MARKER:
 
201
                        case INFO_MARKER:
 
202
                        case smpl_MARKER:
 
203
                        case bext_MARKER:
 
204
                        case MEXT_MARKER:
 
205
                        case DISP_MARKER:
 
206
                              fread(&dword, sizeof (dword), 1, _file);
 
207
                                dword = LE2H_INT(dword);
 
208
                                fseek(_file, (int) dword, SEEK_CUR);
 
209
                                break;
 
210
 
 
211
                        default:
 
212
                              if (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF)
 
213
                                   && isprint ((marker >> 8) & 0xFF) && isprint (marker & 0xFF)) {
 
214
                                    fread (&dword, sizeof (dword), 1, _file) ;
 
215
                                        fseek (_file, (int) dword, SEEK_CUR) ;
 
216
                                        break ;
 
217
                                        }
 
218
                              if ((dword = ftell (_file)) & 0x03) {     
 
219
                              fseek (_file, -3, SEEK_CUR) ;
 
220
                                        break ;
 
221
                                        }
 
222
                                break ;
 
223
                        }
 
224
 
 
225
                if (ferror (_file)) {
 
226
                        clearerr (_file) ;
 
227
                        break ;
 
228
                        }
 
229
                if (ftell (_file) >= (int) (_filelength - (2 * sizeof (dword))))
 
230
                        break;
 
231
                }
 
232
      if (!_dataoffset)
 
233
              return SFE_WAV_NO_DATA;
 
234
 
 
235
      current     = 0 ;
 
236
        endian      = SF_ENDIAN_LITTLE ;                /* All WAV files are little endian. */
 
237
        _sections = 1;
 
238
        
 
239
        fseek (_file, _dataoffset, SEEK_SET) ;
 
240
        
 
241
        if (_blockwidth) {      
 
242
            if (_filelength - _dataoffset < _datalength)
 
243
                  _samples = (_filelength - _dataoffset) / _blockwidth;
 
244
                else
 
245
                        _samples = _datalength / _blockwidth;
 
246
                }
 
247
 
 
248
        switch (_fmt) { 
 
249
            case  WAVE_FORMAT_PCM:
 
250
                case    WAVE_FORMAT_EXTENSIBLE:
 
251
                  break;
 
252
#if 0                                   
 
253
                case    WAVE_FORMAT_MULAW :
 
254
                      _format   = (SF_FORMAT_WAV | SF_FORMAT_ULAW) ;
 
255
                  fmt = new SndFileFormatUlaw(this);
 
256
                      return 0 ;
 
257
        
 
258
                case    WAVE_FORMAT_ALAW :
 
259
                        _format   = (SF_FORMAT_WAV | SF_FORMAT_ALAW) ;
 
260
                  fmt = new SndFileFormatAlaw(this);
 
261
                        return 0 ;
 
262
                
 
263
                case    WAVE_FORMAT_MS_ADPCM :
 
264
                    _format   = (SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM) ;
 
265
                  fmt = new SndFileFormatADPCM(this);
 
266
                      if ((error = ((SndFileFormatADPCM*)(fmt))->reader_init (&wav_fmt)))
 
267
                        return error ;
 
268
                      return 0 ;
 
269
 
 
270
                case    WAVE_FORMAT_IMA_ADPCM :
 
271
                      _format   = (SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM) ;
 
272
                  fmt = new SndFileFormatIMA(this);
 
273
                        if ((error = ((SndFileFormatIMA*)(fmt))->reader_init (&wav_fmt)))
 
274
                        return error ;
 
275
                        return 0 ;
 
276
#endif
 
277
                case    WAVE_FORMAT_IEEE_FLOAT :
 
278
                      _format   = (SF_FORMAT_WAV | SF_FORMAT_FLOAT) ;
 
279
 
 
280
                  fmt = new SndFileFormatWaveFloat(this);
 
281
                      return 0;
 
282
                
 
283
                default:        
 
284
                  return SFE_UNIMPLEMENTED;
 
285
                }
 
286
 
 
287
        _format = (SF_FORMAT_WAV | SF_FORMAT_PCM) ;
 
288
        switch (_bytewidth) {   
 
289
            case  1:
 
290
                  fmt = new SndFileFormatWavePCM1(this);
 
291
                      break;
 
292
                case  2:
 
293
                  fmt = new SndFileFormatWavePCM2(this);
 
294
                      break;
 
295
                case  3:
 
296
                  fmt = new SndFileFormatWavePCM3(this);
 
297
                        break;
 
298
                case  4:
 
299
                  fmt = new SndFileFormatWavePCM4(this);
 
300
                        break;
 
301
                default:
 
302
                  return SFE_UNIMPLEMENTED;
 
303
                }
 
304
        return 0;
 
305
      }
 
306
 
 
307
//---------------------------------------------------------
 
308
//   wav_open_write
 
309
//---------------------------------------------------------
 
310
 
 
311
int SndFile::wav_open_write()
 
312
      { 
 
313
      WAV_FMT wav_fmt;
 
314
        unsigned int dword, subformat;
 
315
        int error;
 
316
        
 
317
        if ((_format & SF_FORMAT_TYPEMASK) != SF_FORMAT_WAV)
 
318
              return SFE_BAD_OPEN_FORMAT;
 
319
        
 
320
        endian      = SF_ENDIAN_LITTLE;     // All WAV files are little endian.
 
321
        _seekable = true;
 
322
        error       = 0;
 
323
 
 
324
        subformat = _format & SF_FORMAT_SUBMASK;
 
325
        if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW)
 
326
                _bytewidth = 1;
 
327
        else
 
328
                _bytewidth = BITWIDTH2BYTES (_pcmbitwidth);
 
329
 
 
330
        _blockwidth             = _bytewidth * _channels;
 
331
        wav_fmt.min.channels    = _channels;
 
332
        wav_fmt.min.samplerate  = _samplerate;
 
333
        wav_fmt.min.bytespersec = _samplerate * _bytewidth * _channels;
 
334
        wav_fmt.min.blockalign  = _bytewidth * _channels;
 
335
        wav_fmt.min.bitwidth    = _pcmbitwidth;
 
336
 
 
337
 
 
338
        switch (_format & SF_FORMAT_SUBMASK) {
 
339
            case        SF_FORMAT_PCM:
 
340
                      wav_fmt.format = WAVE_FORMAT_PCM;
 
341
                        _dataoffset  = 7 * sizeof (dword) + sizeof (MIN_WAV_FMT);
 
342
                        _datalength  = _blockwidth * _samples;
 
343
                        _filelength  = _datalength + _dataoffset;
 
344
                        write_header (&wav_fmt, sizeof (MIN_WAV_FMT), 0);
 
345
                        break;
 
346
 
 
347
                case    SF_FORMAT_FLOAT:
 
348
                  wav_fmt.format = WAVE_FORMAT_IEEE_FLOAT;
 
349
                  _dataoffset  = 9 * sizeof (dword) + sizeof (MIN_WAV_FMT) + sizeof (FACT_CHUNK);
 
350
                        _datalength  = _blockwidth * _samples;
 
351
                        _filelength  = _datalength + _dataoffset;
 
352
                        write_header (&wav_fmt, sizeof (MIN_WAV_FMT), 1);
 
353
                        break;
 
354
 
 
355
                case    SF_FORMAT_ULAW:
 
356
                  wav_fmt.format = WAVE_FORMAT_MULAW;
 
357
                        wav_fmt.size20.bitwidth = 8;
 
358
                        wav_fmt.size20.extrabytes = 2;
 
359
                        wav_fmt.size20.dummy = 0;
 
360
                        _dataoffset  = 9 * sizeof (dword) + sizeof (WAV_FMT_SIZE20) + sizeof (FACT_CHUNK);
 
361
                        _datalength  = _blockwidth * _samples;
 
362
                        _filelength  = _datalength + _dataoffset;
 
363
                        write_header (&wav_fmt, sizeof (WAV_FMT_SIZE20), 1);
 
364
                        break;
 
365
                                        
 
366
                case    SF_FORMAT_ALAW:
 
367
                  wav_fmt.format = WAVE_FORMAT_ALAW;
 
368
                  wav_fmt.size20.bitwidth = 8;
 
369
                        wav_fmt.size20.extrabytes = 2;
 
370
                        wav_fmt.size20.dummy = 0;
 
371
                        _dataoffset  = 9 * sizeof (dword) + sizeof (WAV_FMT_SIZE20) + sizeof (FACT_CHUNK);
 
372
                        _datalength  = _blockwidth * _samples;
 
373
                        _filelength  = _datalength + _dataoffset;
 
374
                        write_header (&wav_fmt, sizeof (WAV_FMT_SIZE20), 1);
 
375
                        break;
 
376
 
 
377
                case    SF_FORMAT_IMA_ADPCM:
 
378
                  wav_fmt.format = WAVE_FORMAT_IMA_ADPCM;
 
379
//                      if ((error = wav_ima_writer_init (&wav_fmt)))
 
380
//                            return error;
 
381
                  _dataoffset  = 9 * sizeof (dword) + sizeof (IMA_ADPCM_WAV_FMT) + sizeof (FACT_CHUNK);
 
382
                        if (_samples % wav_fmt.ima.samplesperblock)
 
383
                              _datalength  = ((_samples / wav_fmt.ima.samplesperblock) + 1) * wav_fmt.ima.samplesperblock;
 
384
                        else
 
385
                                _datalength  = _samples;
 
386
                        _filelength  = _datalength + _dataoffset;
 
387
                        write_header (&wav_fmt, sizeof (IMA_ADPCM_WAV_FMT), 1);
 
388
                        break;
 
389
 
 
390
                case    SF_FORMAT_MS_ADPCM :
 
391
                  wav_fmt.format = WAVE_FORMAT_MS_ADPCM;
 
392
//                      msadpcm_writer_init (&wav_fmt);
 
393
                        _dataoffset  = 9 * sizeof (dword) + sizeof (MS_ADPCM_WAV_FMT) + sizeof (FACT_CHUNK);
 
394
                        if (_samples % wav_fmt.msadpcm.samplesperblock)
 
395
                              _datalength  = ((_samples / wav_fmt.msadpcm.samplesperblock) + 1) * wav_fmt.msadpcm.samplesperblock;
 
396
                        else
 
397
                                _datalength  = _samples;
 
398
                        _filelength  = _datalength + _dataoffset;
 
399
                        write_header (&wav_fmt, sizeof (MS_ADPCM_WAV_FMT), 1);
 
400
                        break;
 
401
 
 
402
                default:        
 
403
                  return SFE_UNIMPLEMENTED;
 
404
                }
 
405
 
 
406
        dword = data_MARKER;
 
407
        fwrite(&dword, sizeof (dword), 1, _file);
 
408
 
 
409
        dword = H2LE_INT (_datalength);
 
410
        fwrite (&dword, sizeof (dword), 1, _file);
 
411
        
 
412
        if ((_format & SF_FORMAT_SUBMASK) == SF_FORMAT_FLOAT) { 
 
413
            _format = (SF_FORMAT_WAV | SF_FORMAT_FLOAT) ;
 
414
            fmt = new SndFileFormatWaveFloat(this);
 
415
                return 0;
 
416
            }
 
417
#if 0   
 
418
        if ((_format & SF_FORMAT_SUBMASK) == SF_FORMAT_IMA_ADPCM) {
 
419
              _format    = (SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM);
 
420
            fmt = new SndFileFormatIMA(this);
 
421
                return 0;
 
422
                }
 
423
 
 
424
        if ((_format & SF_FORMAT_SUBMASK) == SF_FORMAT_MS_ADPCM) {
 
425
              _format    = (SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM);
 
426
            fmt = new SndFileFormatADPCM(this);
 
427
                return 0;
 
428
                }
 
429
        if ((_format & SF_FORMAT_SUBMASK) == SF_FORMAT_ULAW) {
 
430
              _format    = (SF_FORMAT_WAV | SF_FORMAT_ULAW);
 
431
            fmt = new SndFileFormatUlaw(this);
 
432
                return 0;
 
433
                }
 
434
        if ((_format & SF_FORMAT_SUBMASK) == SF_FORMAT_ALAW) {
 
435
            _format    = (SF_FORMAT_WAV | SF_FORMAT_ALAW);
 
436
            fmt = new SndFileFormatAlaw(this);
 
437
                return 0;
 
438
                }
 
439
#endif
 
440
        if ((_format & SF_FORMAT_SUBMASK) != SF_FORMAT_PCM)
 
441
                return SFE_UNIMPLEMENTED ;
 
442
 
 
443
        switch (_bytewidth) {   
 
444
            case  1:
 
445
                  fmt = new SndFileFormatWavePCM1(this);
 
446
                      break;
 
447
                case  2:
 
448
                  fmt = new SndFileFormatWavePCM2(this);
 
449
                      break;
 
450
                case  3:
 
451
                  fmt = new SndFileFormatWavePCM3(this);
 
452
                        break;
 
453
                case  4:
 
454
                  fmt = new SndFileFormatWavePCM4(this);
 
455
                        break;
 
456
                default:
 
457
                  return SFE_UNIMPLEMENTED;
 
458
                }
 
459
        return 0;
 
460
      }
 
461
 
 
462
//---------------------------------------------------------
 
463
//   close
 
464
//---------------------------------------------------------
 
465
 
 
466
void SndFileFormatWave::close ()
 
467
      { 
 
468
        if (sfile->mode() == SF_MODE_WRITE) {   
 
469
            /*  Now we know for certain the length of the file we can
 
470
                 *  re-write correct values for the RIFF and data chunks.
 
471
                 */
 
472
                fseek(sfile->file(), 0, SEEK_END);
 
473
                sfile->setFilelength(ftell(sfile->file()));
 
474
 
 
475
                /* Fix RIFF size. */
 
476
                unsigned int dword = H2LE_INT (sfile->filelength() - 2 * sizeof (dword));
 
477
                fseek (sfile->file(), sizeof (dword), SEEK_SET);
 
478
                fwrite (&dword, sizeof (dword), 1, sfile->file());
 
479
                
 
480
                sfile->setDatalength(sfile->filelength() - sfile->dataoffset());
 
481
                sfile->setSamples(sfile->datalength() / (sfile->channels() * sfile->bytewidth()));
 
482
                fseek (sfile->file(), (int) (sfile->dataoffset() - sizeof (dword)), SEEK_SET);
 
483
                dword = H2LE_INT (sfile->datalength());
 
484
                fwrite (&dword, sizeof (dword), 1, sfile->file());
 
485
                }
 
486
      }
 
487
 
 
488
//---------------------------------------------------------
 
489
//   read_fmt_chunk
 
490
//---------------------------------------------------------
 
491
 
 
492
int SndFile::read_fmt_chunk(WAV_FMT *wav_fmt)
 
493
      { 
 
494
      unsigned int dword, bytesread, structsize, bytespersec = 0;
 
495
        
 
496
        memset (wav_fmt, 0, sizeof (WAV_FMT));
 
497
        bytesread = 0;
 
498
 
 
499
        fread(&dword, sizeof (dword), 1, _file);
 
500
        structsize = LE2H_INT (dword);
 
501
        
 
502
        if (structsize < 16)
 
503
                return SFE_WAV_FMT_SHORT ;
 
504
        if (structsize > sizeof (WAV_FMT))
 
505
                return SFE_WAV_FMT_TOO_BIG;
 
506
                                        
 
507
        fread(wav_fmt, structsize, 1, _file);
 
508
        bytesread += structsize;
 
509
        if (CPU_IS_BIG_ENDIAN)
 
510
                le2h_wav_fmt (wav_fmt);
 
511
 
 
512
        _samplerate             = wav_fmt->min.samplerate;
 
513
        _samples                = 0;        /* Correct this when reading data chunk. */
 
514
        _channels               = wav_fmt->min.channels;
 
515
        
 
516
        switch (wav_fmt->format) {
 
517
            case WAVE_FORMAT_PCM:
 
518
                case WAVE_FORMAT_IEEE_FLOAT:
 
519
                      bytespersec = wav_fmt->min.samplerate * wav_fmt->min.blockalign;
 
520
                      _pcmbitwidth = wav_fmt->min.bitwidth;
 
521
                        _bytewidth = BITWIDTH2BYTES (wav_fmt->min.bitwidth);
 
522
                        break;
 
523
 
 
524
                case WAVE_FORMAT_ALAW:
 
525
                case WAVE_FORMAT_MULAW:
 
526
                      _pcmbitwidth = 16;
 
527
                  _bytewidth      = 1;
 
528
                      break;
 
529
 
 
530
                case WAVE_FORMAT_MS_ADPCM:
 
531
                  if (wav_fmt->msadpcm.bitwidth != 4)
 
532
                              return SFE_WAV_ADPCM_NOT4BIT;
 
533
                      if (wav_fmt->msadpcm.channels < 1 || wav_fmt->msadpcm.channels > 2)
 
534
                              return SFE_WAV_ADPCM_CHANNELS;
 
535
 
 
536
                      bytespersec = (wav_fmt->msadpcm.samplerate * wav_fmt->msadpcm.blockalign) / wav_fmt->msadpcm.samplesperblock;
 
537
                      _pcmbitwidth = 16;
 
538
                      _bytewidth      = 2;
 
539
                        if (wav_fmt->msadpcm.numcoeffs > sizeof (MS_ADPCM_WAV_FMT) / sizeof (int)) {
 
540
                              wav_fmt->msadpcm.numcoeffs = sizeof (MS_ADPCM_WAV_FMT) / sizeof (int);
 
541
                              }
 
542
                        break;
 
543
                                
 
544
                case WAVE_FORMAT_IMA_ADPCM :
 
545
                        if (wav_fmt->ima.bitwidth != 4)
 
546
                              return SFE_WAV_ADPCM_NOT4BIT;
 
547
                      if (wav_fmt->ima.channels < 1 || wav_fmt->ima.channels > 2)
 
548
                              return SFE_WAV_ADPCM_CHANNELS;
 
549
                      bytespersec = (wav_fmt->ima.samplerate * wav_fmt->ima.blockalign) / wav_fmt->ima.samplesperblock;
 
550
                      _pcmbitwidth = 16;
 
551
                        _bytewidth      = 2;
 
552
                        break;
 
553
                                
 
554
                case WAVE_FORMAT_EXTENSIBLE :
 
555
                        _pcmbitwidth = wav_fmt->ext.bitwidth ;
 
556
                        _bytewidth      = BITWIDTH2BYTES (wav_fmt->ext.bitwidth) ;
 
557
                        break;
 
558
 
 
559
                default:
 
560
                  break;
 
561
                }
 
562
        _blockwidth = wav_fmt->min.channels * _bytewidth;
 
563
        return 0;
 
564
      }
 
565
 
 
566
//---------------------------------------------------------
 
567
//   write_header
 
568
//---------------------------------------------------------
 
569
 
 
570
int SndFile::write_header(WAV_FMT *wav_fmt, unsigned int size, int do_fact)
 
571
      { 
 
572
      FACT_CHUNK        fact_chunk ;
 
573
        unsigned int dword, RIFFsize ;
 
574
 
 
575
        RIFFsize   = _filelength - 2 * sizeof (dword) ;
 
576
 
 
577
        dword = RIFF_MARKER ;
 
578
        fwrite (&dword, sizeof (dword), 1, _file) ;
 
579
        dword = H2LE_INT (RIFFsize) ;
 
580
        fwrite (&dword, sizeof (dword), 1, _file) ;
 
581
        
 
582
        dword = WAVE_MARKER ;
 
583
        fwrite (&dword, sizeof (dword), 1, _file) ;
 
584
        dword = fmt_MARKER ;
 
585
        fwrite (&dword, sizeof (dword), 1, _file) ;
 
586
        
 
587
        dword = H2LE_INT (size) ;
 
588
        fwrite (&dword, sizeof (dword), 1, _file) ;
 
589
        if (CPU_IS_BIG_ENDIAN)
 
590
                h2le_wav_fmt (wav_fmt) ;        
 
591
        fwrite (wav_fmt, size, 1, _file) ;
 
592
        
 
593
        if (do_fact) {  
 
594
            dword = fact_MARKER ;
 
595
                fwrite (&dword, sizeof (dword), 1, _file) ;
 
596
                dword = H2LE_INT (sizeof (FACT_CHUNK)) ;
 
597
                fwrite (&dword, sizeof (dword), 1, _file) ;
 
598
                fact_chunk.samples = H2LE_INT (_samples) ;
 
599
                fwrite (&fact_chunk, sizeof (fact_chunk), 1, _file) ;
 
600
                }
 
601
 
 
602
        return 0;
 
603
      }
 
604
 
 
605
static void     le2h_wav_fmt (WAV_FMT *fmt)
 
606
      { 
 
607
      int         k ;
 
608
 
 
609
        fmt->min.format      = ENDSWAP_SHORT (fmt->min.format) ;
 
610
        fmt->min.channels    = ENDSWAP_SHORT (fmt->min.channels) ;
 
611
        fmt->min.samplerate  = ENDSWAP_INT   (fmt->min.samplerate) ;
 
612
        fmt->min.bytespersec = ENDSWAP_INT   (fmt->min.bytespersec) ;
 
613
        fmt->min.blockalign  = ENDSWAP_SHORT (fmt->min.blockalign) ;
 
614
        fmt->min.bitwidth    = ENDSWAP_SHORT (fmt->min.bitwidth) ;
 
615
 
 
616
        switch (fmt->format)
 
617
        {       case WAVE_FORMAT_MS_ADPCM :     
 
618
                                fmt->msadpcm.extrabytes      = ENDSWAP_SHORT (fmt->msadpcm.extrabytes) ;
 
619
                                fmt->msadpcm.samplesperblock = ENDSWAP_SHORT (fmt->msadpcm.samplesperblock) ;
 
620
                                fmt->msadpcm.numcoeffs       = ENDSWAP_SHORT (fmt->msadpcm.numcoeffs) ;
 
621
                                for (k = 0 ; k < fmt->msadpcm.numcoeffs  ; k++)
 
622
                                {       fmt->msadpcm.coeffs [k].coeff1 = ENDSWAP_SHORT (fmt->msadpcm.coeffs [k].coeff1) ;
 
623
                                        fmt->msadpcm.coeffs [k].coeff2 = ENDSWAP_SHORT (fmt->msadpcm.coeffs [k].coeff2) ;
 
624
                                        } ;
 
625
                                break ;
 
626
                                
 
627
                case WAVE_FORMAT_IMA_ADPCM :    
 
628
                                fmt->ima.extrabytes      = ENDSWAP_SHORT (fmt->ima.extrabytes) ;
 
629
                                fmt->ima.samplesperblock = ENDSWAP_SHORT (fmt->ima.samplesperblock) ;
 
630
                                break ;
 
631
                                
 
632
                case WAVE_FORMAT_ALAW : 
 
633
                case WAVE_FORMAT_MULAW :        
 
634
                                fmt->size20.extrabytes = ENDSWAP_SHORT (fmt->size20.extrabytes) ;
 
635
                                fmt->size20.dummy      = ENDSWAP_SHORT (fmt->size20.dummy) ;
 
636
                                break ;
 
637
                                
 
638
                default : break ;
 
639
                } ;
 
640
 
 
641
      }
 
642
 
 
643
static void     h2le_wav_fmt (WAV_FMT *fmt)
 
644
      {
 
645
      int k ;
 
646
 
 
647
        switch (fmt->format)
 
648
        {       case WAVE_FORMAT_MS_ADPCM :     
 
649
                                for (k = 0 ; k < fmt->msadpcm.numcoeffs  ; k++)
 
650
                                {       fmt->msadpcm.coeffs [k].coeff1 = ENDSWAP_SHORT (fmt->msadpcm.coeffs [k].coeff1) ;
 
651
                                        fmt->msadpcm.coeffs [k].coeff2 = ENDSWAP_SHORT (fmt->msadpcm.coeffs [k].coeff2) ;
 
652
                                        } ;
 
653
                                fmt->msadpcm.numcoeffs       = ENDSWAP_SHORT (fmt->msadpcm.numcoeffs) ;
 
654
                                fmt->msadpcm.extrabytes      = ENDSWAP_SHORT (fmt->msadpcm.extrabytes) ;
 
655
                                fmt->msadpcm.samplesperblock = ENDSWAP_SHORT (fmt->msadpcm.samplesperblock) ;
 
656
                                break ;
 
657
                                
 
658
                case WAVE_FORMAT_IMA_ADPCM :    
 
659
                                fmt->ima.extrabytes      = ENDSWAP_SHORT (fmt->ima.extrabytes) ;
 
660
                                fmt->ima.samplesperblock = ENDSWAP_SHORT (fmt->ima.samplesperblock) ;
 
661
                                break ;
 
662
                                
 
663
                case WAVE_FORMAT_ALAW : 
 
664
                case WAVE_FORMAT_MULAW :        
 
665
                                fmt->size20.extrabytes = ENDSWAP_SHORT (fmt->size20.extrabytes) ;
 
666
                                fmt->size20.dummy      = ENDSWAP_SHORT (fmt->size20.dummy) ;
 
667
                                break ;
 
668
                                
 
669
                default : break ;
 
670
                } ;
 
671
 
 
672
        fmt->min.format      = ENDSWAP_SHORT (fmt->min.format) ;
 
673
        fmt->min.channels    = ENDSWAP_SHORT (fmt->min.channels) ;
 
674
        fmt->min.samplerate  = ENDSWAP_INT   (fmt->min.samplerate) ;
 
675
        fmt->min.bytespersec = ENDSWAP_INT   (fmt->min.bytespersec) ;
 
676
        fmt->min.blockalign  = ENDSWAP_SHORT (fmt->min.blockalign) ;
 
677
        fmt->min.bitwidth    = ENDSWAP_SHORT (fmt->min.bitwidth) ;
 
678
      }
 
679
 
 
680
#if 0
 
681
static const char* wav_format_str (int k)
 
682
      {
 
683
      switch (k) {      
 
684
            case WAVE_FORMAT_UNKNOWN :
 
685
                        return "WAVE_FORMAT_UNKNOWN" ;
 
686
                case WAVE_FORMAT_PCM          :
 
687
                        return "WAVE_FORMAT_PCM         " ;
 
688
                case WAVE_FORMAT_MS_ADPCM :
 
689
                        return "WAVE_FORMAT_MS_ADPCM" ;
 
690
                case WAVE_FORMAT_IEEE_FLOAT :
 
691
                        return "WAVE_FORMAT_IEEE_FLOAT" ;
 
692
                case WAVE_FORMAT_IBM_CVSD :
 
693
                        return "WAVE_FORMAT_IBM_CVSD" ;
 
694
                case WAVE_FORMAT_ALAW :
 
695
                        return "WAVE_FORMAT_ALAW" ;
 
696
                case WAVE_FORMAT_MULAW :
 
697
                        return "WAVE_FORMAT_MULAW" ;
 
698
                case WAVE_FORMAT_OKI_ADPCM :
 
699
                        return "WAVE_FORMAT_OKI_ADPCM" ;
 
700
                case WAVE_FORMAT_IMA_ADPCM :
 
701
                        return "WAVE_FORMAT_IMA_ADPCM" ;
 
702
                case WAVE_FORMAT_MEDIASPACE_ADPCM :
 
703
                        return "WAVE_FORMAT_MEDIASPACE_ADPCM" ;
 
704
                case WAVE_FORMAT_SIERRA_ADPCM :
 
705
                        return "WAVE_FORMAT_SIERRA_ADPCM" ;
 
706
                case WAVE_FORMAT_G723_ADPCM :
 
707
                        return "WAVE_FORMAT_G723_ADPCM" ;
 
708
                case WAVE_FORMAT_DIGISTD :
 
709
                        return "WAVE_FORMAT_DIGISTD" ;
 
710
                case WAVE_FORMAT_DIGIFIX :
 
711
                        return "WAVE_FORMAT_DIGIFIX" ;
 
712
                case WAVE_FORMAT_DIALOGIC_OKI_ADPCM :
 
713
                        return "WAVE_FORMAT_DIALOGIC_OKI_ADPCM" ;
 
714
                case WAVE_FORMAT_MEDIAVISION_ADPCM :
 
715
                        return "WAVE_FORMAT_MEDIAVISION_ADPCM" ;
 
716
                case WAVE_FORMAT_YAMAHA_ADPCM :
 
717
                        return "WAVE_FORMAT_YAMAHA_ADPCM" ;
 
718
                case WAVE_FORMAT_SONARC :
 
719
                        return "WAVE_FORMAT_SONARC" ;
 
720
                case WAVE_FORMAT_DSPGROUP_TRUESPEECH  :
 
721
                        return "WAVE_FORMAT_DSPGROUP_TRUESPEECH " ;
 
722
                case WAVE_FORMAT_ECHOSC1 :
 
723
                        return "WAVE_FORMAT_ECHOSC1" ;
 
724
                case WAVE_FORMAT_AUDIOFILE_AF18   :
 
725
                        return "WAVE_FORMAT_AUDIOFILE_AF18  " ;
 
726
                case WAVE_FORMAT_APTX :
 
727
                        return "WAVE_FORMAT_APTX" ;
 
728
                case WAVE_FORMAT_AUDIOFILE_AF10   :
 
729
                        return "WAVE_FORMAT_AUDIOFILE_AF10  " ;
 
730
                case WAVE_FORMAT_DOLBY_AC2 :
 
731
                        return "WAVE_FORMAT_DOLBY_AC2" ;
 
732
                case WAVE_FORMAT_GSM610 :
 
733
                        return "WAVE_FORMAT_GSM610" ;
 
734
                case WAVE_FORMAT_MSNAUDIO :
 
735
                        return "WAVE_FORMAT_MSNAUDIO" ;
 
736
                case WAVE_FORMAT_ANTEX_ADPCME :
 
737
                        return "WAVE_FORMAT_ANTEX_ADPCME" ;
 
738
                case WAVE_FORMAT_CONTROL_RES_VQLPC :
 
739
                        return "WAVE_FORMAT_CONTROL_RES_VQLPC" ;
 
740
                case WAVE_FORMAT_DIGIREAL :
 
741
                        return "WAVE_FORMAT_DIGIREAL" ;
 
742
                case WAVE_FORMAT_DIGIADPCM :
 
743
                        return "WAVE_FORMAT_DIGIADPCM" ;
 
744
                case WAVE_FORMAT_CONTROL_RES_CR10 :
 
745
                        return "WAVE_FORMAT_CONTROL_RES_CR10" ;
 
746
                case WAVE_FORMAT_NMS_VBXADPCM :
 
747
                        return "WAVE_FORMAT_NMS_VBXADPCM" ;
 
748
                case WAVE_FORMAT_ROCKWELL_ADPCM :
 
749
                        return "WAVE_FORMAT_ROCKWELL_ADPCM" ;
 
750
                case WAVE_FORMAT_ROCKWELL_DIGITALK :
 
751
                        return "WAVE_FORMAT_ROCKWELL_DIGITALK" ;
 
752
                case WAVE_FORMAT_G721_ADPCM :
 
753
                        return "WAVE_FORMAT_G721_ADPCM" ;
 
754
                case WAVE_FORMAT_MPEG :
 
755
                        return "WAVE_FORMAT_MPEG" ;
 
756
                case WAVE_FORMAT_MPEGLAYER3 :
 
757
                        return "WAVE_FORMAT_MPEGLAYER3" ;
 
758
                case IBM_FORMAT_MULAW :
 
759
                        return "IBM_FORMAT_MULAW" ;
 
760
                case IBM_FORMAT_ALAW :
 
761
                        return "IBM_FORMAT_ALAW" ;
 
762
                case IBM_FORMAT_ADPCM :
 
763
                        return "IBM_FORMAT_ADPCM" ;
 
764
                case WAVE_FORMAT_CREATIVE_ADPCM :
 
765
                        return "WAVE_FORMAT_CREATIVE_ADPCM" ;
 
766
                case WAVE_FORMAT_FM_TOWNS_SND :
 
767
                        return "WAVE_FORMAT_FM_TOWNS_SND" ;
 
768
                case WAVE_FORMAT_OLIGSM :
 
769
                        return "WAVE_FORMAT_OLIGSM" ;
 
770
                case WAVE_FORMAT_OLIADPCM :
 
771
                        return "WAVE_FORMAT_OLIADPCM" ;
 
772
                case WAVE_FORMAT_OLICELP :
 
773
                        return "WAVE_FORMAT_OLICELP" ;
 
774
                case WAVE_FORMAT_OLISBC :
 
775
                        return "WAVE_FORMAT_OLISBC" ;
 
776
                case WAVE_FORMAT_OLIOPR :
 
777
                        return "WAVE_FORMAT_OLIOPR" ;
 
778
                case WAVE_FORMAT_EXTENSIBLE :
 
779
                        return "WAVE_FORMAT_EXTENSIBLE" ;
 
780
                break ;
 
781
                }
 
782
        return "Unknown format";
 
783
      }
 
784
#endif
 
785