~ubuntu-branches/ubuntu/raring/muse/raring-proposed

« back to all changes in this revision

Viewing changes to sf/wav.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2004-02-07 15:18:22 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040207151822-es27xxkzbcxkebjm
Tags: 0.6.3-1
* New upstream version.
* Added patches:
  + [10_alsa_init_fix] New, from upstream CVS.
    Initialize direction variable when setting Alsa parameters.
  + [10_canvas_translation_fix] New, from upstream CVS.
    Do not translate tooltips twice in canvas popup.
  + [10_checkbox_fix] New, from upstream CVS.
    Use proper set/test methods on metronome checkboxes.
  + [10_html_doc_cleanup] New.
    Fix links and HTML errors in documentation.
  + [20_allow_system_timer] New.
    The new upstream version fails by default if the real-time clock
    could not be accessed (usually the case when not running suid-root).
    This patch reverts the old behaviour of falling back to the more
    inaccurate system timer.
* Updated patches:
  + [11_PIC_fixes_fixup] Rediffed.
* Removed patches:
  + [20_no_atomic_asm] Merged upstream.
* debian/compat: Splice out debhelper compatibility level from rules file.
* debian/control: Build-depend on latest jack release by default.
  Closes: #228788
* debian/control: Bump standards version.
* debian/control: Use auto-generated debconf dependency via misc:Depends.
* debian/control: Minor tweaks to the long description.
* debian/control: Tighten fluidsynth build dependency to sane version.
* debian/muse.doc-base: New. Register HTML documentation with doc-base.
* debian/templates: Tiny rewording, and typo fix.
* debian/templates, debian/po/*: Switch to po-debconf for translations.

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