~ubuntu-branches/ubuntu/quantal/muse/quantal

« back to all changes in this revision

Viewing changes to sf/sndfile.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: sndfile.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 <stdarg.h>
 
13
#include <unistd.h>
 
14
#include <fcntl.h>
 
15
#include <string.h>
 
16
#include <ctype.h>
 
17
#include <sys/stat.h>
 
18
#include <mcheck.h>
 
19
#include <math.h>
 
20
#include <errno.h>
 
21
 
 
22
#include <qprogressdialog.h>
 
23
 
 
24
#include "sndfile.h"
 
25
#include "config.h"
 
26
#include "sfendian.h"
 
27
 
 
28
#if (CPU_IS_LITTLE_ENDIAN == 1)
 
29
#       define  MAKE_MARKER(a,b,c,d)            ((a)|((b)<<8)|((c)<<16)|((d)<<24))
 
30
#elif (CPU_IS_BIG_ENDIAN == 1)
 
31
#       define  MAKE_MARKER(a,b,c,d)            (((a)<<24)|((b)<<16)|((c)<<8)|(d))
 
32
#else
 
33
#       error "Cannot determine endian-ness of processor."
 
34
#endif
 
35
 
 
36
#if 0
 
37
struct ErrorStruct {    
 
38
      int   error ;
 
39
        char    *str ;
 
40
      };
 
41
 
 
42
static ErrorStruct SndfileErrors [] = {
 
43
        { SFE_NO_ERROR           , "No Error." },
 
44
        { SFE_BAD_FILE           , "File does not exist or is not a regular file (possibly a pipe?)." },
 
45
        { SFE_OPEN_FAILED                , "Could not open file." },
 
46
        { SFE_BAD_OPEN_FORMAT    , "Bad format specified for file open." },
 
47
        { SFE_BAD_SNDFILE_PTR    , "Not a valid SNDFILE* pointer." },
 
48
        { SFE_BAD_SF_INFO_PTR    , "NULL SF_INFO pointer passed to libsndfile." },
 
49
        { SFE_BAD_INT_FD                 , "Bad file descriptor." },
 
50
        { SFE_BAD_INT_PTR                , "Internal error, Bad pointer." },
 
51
        { SFE_MALLOC_FAILED      , "Internal malloc () failed." },
 
52
        { SFE_BAD_SEEK           , "Internal fseek() failed." },
 
53
        { SFE_NOT_SEEKABLE       , "Seek attempted on unseekable file type." },
 
54
        { SFE_UNIMPLEMENTED      , "File contains data in an unimplemented format." },
 
55
        { SFE_BAD_READ_ALIGN     , "Attempt to read a non-integer number of channels." },
 
56
        { SFE_BAD_WRITE_ALIGN    , "Attempt to write a non-integer number of channels." },
 
57
        { SFE_UNKNOWN_FORMAT     , "File contains data in an unknown format." },
 
58
        { SFE_NOT_READMODE       , "Read attempted on file currently open for write." },
 
59
        { SFE_NOT_WRITEMODE      , "Write attempted on file currently open for read." },
 
60
        { SFE_BAD_MODE_RW                , "This file format does not support read/write mode." },
 
61
        { SFE_BAD_SF_INFO                , "Internal error : SF_INFO struct incomplete." },
 
62
 
 
63
        { SFE_SHORT_READ                 , "Short read error." },
 
64
        { SFE_SHORT_WRITE                , "Short write error." },
 
65
        { SFE_INTERNAL           , "Unspecified internal error." },
 
66
        
 
67
        { SFE_WAV_NO_RIFF                , "Error in WAV file. No 'RIFF' chunk marker." },
 
68
        { SFE_WAV_NO_WAVE                , "Error in WAV file. No 'WAVE' chunk marker." },
 
69
        { SFE_WAV_NO_FMT                 , "Error in WAV file. No 'fmt ' chunk marker." },
 
70
        { SFE_WAV_FMT_SHORT      , "Error in WAV file. Short 'fmt ' chunk." },
 
71
 
 
72
        { SFE_WAV_FMT_TOO_BIG    , "Error in WAV file. 'fmt ' chunk too large." },
 
73
 
 
74
        { SFE_WAV_BAD_FORMAT     , "Error in WAV file. Errors in 'fmt ' chunk." },
 
75
        { SFE_WAV_BAD_BLOCKALIGN , "Error in WAV file. Block alignment in 'fmt ' chunk is incorrect." },
 
76
        { SFE_WAV_NO_DATA                , "Error in WAV file. No 'data' chunk marker." },
 
77
        { SFE_WAV_UNKNOWN_CHUNK  , "Error in WAV file. File contains an unknown chunk marker." },
 
78
        
 
79
        { SFE_WAV_ADPCM_NOT4BIT  , "Error in ADPCM WAV file. Invalid bit width."},
 
80
        { SFE_WAV_ADPCM_CHANNELS , "Error in ADPCM WAV file. Invalid number of channels."},
 
81
        { SFE_WAV_GSM610_FORMAT  , "Error in GSM610 WAV file. Invalid format chunk."},
 
82
 
 
83
        { SFE_AIFF_NO_FORM       , "Error in AIFF file, bad 'FORM' marker."},
 
84
        { SFE_AIFF_UNKNOWN_CHUNK , "Error in AIFF file, unknown chunk."},
 
85
        { SFE_COMM_CHUNK_SIZE    , "Error in AIFF file, bad 'COMM' chunk size."},
 
86
        { SFE_AIFF_NO_SSND       , "Error in AIFF file, bad 'SSND' chunk."},
 
87
        { SFE_AIFF_NO_DATA       , "Error in AIFF file, no sound data."},
 
88
        
 
89
        { SFE_AU_UNKNOWN_FORMAT  , "Error in AU file, unknown format."},
 
90
        { SFE_AU_NO_DOTSND       , "Error in AU file, missing '.snd' or 'dns.' marker."},
 
91
 
 
92
        { SFE_RAW_READ_BAD_SPEC  , "Error while opening RAW file for read. Must specify format, pcmbitwidth and channels."},
 
93
        { SFE_RAW_BAD_BITWIDTH   , "Error. RAW file bitwidth must be a multiple of 8."},
 
94
 
 
95
        { SFE_PAF_NO_MARKER      , "Error in PAF file, no marker."},
 
96
        { SFE_PAF_VERSION                , "Error in PAF file, bad version."},
 
97
        { SFE_PAF_UNKNOWN_FORMAT , "Error in PAF file, unknown format."},
 
98
        { SFE_PAF_SHORT_HEADER   , "Error in PAF file. File shorter than minimal header."},
 
99
        
 
100
        { SFE_SVX_NO_FORM                , "Error in 8SVX / 16SV file, no 'FORM' marker."},
 
101
        { SFE_SVX_NO_BODY                , "Error in 8SVX / 16SV file, no 'BODY' marker."},
 
102
        { SFE_SVX_NO_DATA                , "Error in 8SVX / 16SV file, no sound data."},
 
103
        { SFE_SVX_BAD_COMP       , "Error in 8SVX / 16SV file, unsupported compression format."},
 
104
        
 
105
        { SFE_NIST_BAD_HEADER    , "Error in NIST file, bad header."},
 
106
        { SFE_NIST_BAD_ENCODING  , "Error in NIST file, unsupported compression format."},
 
107
 
 
108
        { SFE_MAX_ERROR          , "Maximum error number." }
 
109
      };
 
110
#endif
 
111
 
 
112
 
 
113
static int is_au_snd_file (const QString ext)
 
114
      { 
 
115
        return ext == "au" || ext == "snd";
 
116
      }
 
117
 
 
118
static int guess_file_type (FILE *file, const QString ext)
 
119
      { 
 
120
      unsigned int buffer[3];
 
121
 
 
122
        fread(buffer, sizeof(buffer), 1, file);
 
123
        fseek(file, 0, SEEK_SET);
 
124
 
 
125
        if (buffer [0] == MAKE_MARKER ('R','I','F','F') && buffer [2] == MAKE_MARKER ('W','A','V','E'))
 
126
                return SF_FORMAT_WAV ;
 
127
                
 
128
        if (buffer[0] == MAKE_MARKER ('F','O','R','M')) {
 
129
            if (buffer [2] == MAKE_MARKER ('A','I','F','F') || buffer [2] == MAKE_MARKER ('A','I','F','C'))
 
130
                        return SF_FORMAT_AIFF;
 
131
                if (buffer [2] == MAKE_MARKER ('8','S','V','X') || buffer [2] == MAKE_MARKER ('1','6','S','V'))
 
132
                        return SF_FORMAT_SVX;
 
133
                return 0;
 
134
                }
 
135
                
 
136
        if ((buffer [0] == MAKE_MARKER ('.','s','n','d') || buffer [0] == MAKE_MARKER ('d','n','s','.')))
 
137
                return SF_FORMAT_AU;
 
138
                
 
139
        if ((buffer [0] == MAKE_MARKER ('f','a','p',' ') || buffer [0] == MAKE_MARKER (' ','p','a','f')))
 
140
                return SF_FORMAT_PAF;
 
141
        
 
142
        if (buffer [0] == MAKE_MARKER ('N','I','S','T'))
 
143
                return SF_FORMAT_NIST;
 
144
                
 
145
        if (is_au_snd_file (ext))
 
146
                return SF_FORMAT_AU | SF_FORMAT_ULAW;
 
147
 
 
148
        /* Default to header-less RAW PCM file type. */
 
149
        return SF_FORMAT_RAW;
 
150
      }
 
151
 
 
152
 
 
153
//---------------------------------------------------------
 
154
//   validateSfinfo
 
155
//---------------------------------------------------------
 
156
 
 
157
bool SndFile::validateSfinfo()
 
158
      { 
 
159
      if (!_samplerate)
 
160
              return false;
 
161
        if (!_samples)
 
162
              return false;
 
163
        if (!_channels)
 
164
              return false;
 
165
        if (!_format & SF_FORMAT_TYPEMASK)
 
166
              return false;
 
167
        if (!_format & SF_FORMAT_SUBMASK)
 
168
              return false;
 
169
        if (!_sections)
 
170
              return false;
 
171
        return true;
 
172
      }
 
173
 
 
174
bool SndFile::validate()
 
175
      { 
 
176
      if (!_blockwidth)
 
177
                return false;   
 
178
        if (!_bytewidth)
 
179
                return false;   
 
180
        if (!_datalength)
 
181
                return false;
 
182
        if (_blockwidth != _channels * _bytewidth)
 
183
                return false;   
 
184
        return true;
 
185
      }
 
186
 
 
187
//---------------------------------------------------------
 
188
//   SndFile
 
189
//---------------------------------------------------------
 
190
 
 
191
SndFile::SndFile(const QString path)
 
192
      {
 
193
      finfo       = new QFileInfo(path);
 
194
      _file       = 0;
 
195
      refs        = 0;
 
196
      cache       = 0;
 
197
      csize       = 0;
 
198
      _format     = 0;
 
199
      fmt         = 0;
 
200
      _samples    = 0;
 
201
      _samplerate = 0;
 
202
      _channels   = 0;
 
203
      _format     = 0;
 
204
      }
 
205
 
 
206
int SndFile::incRef()
 
207
      {
 
208
      ++refs;
 
209
//      printf("SndFile::incRef %d\n", refs);
 
210
      return refs;
 
211
      }
 
212
 
 
213
int SndFile::decRef()
 
214
      {
 
215
      --refs;
 
216
//      printf("SndFile::decRef %d\n", refs);
 
217
      return refs;
 
218
      }
 
219
 
 
220
SndFile::~SndFile()
 
221
      {
 
222
      close();
 
223
      delete finfo;
 
224
      finfo = 0;
 
225
      if (cache) {
 
226
            for (unsigned i = 0; i < channels(); ++i)
 
227
                  delete cache[i];
 
228
            delete cache;
 
229
            cache = 0;
 
230
            }
 
231
      }
 
232
 
 
233
//---------------------------------------------------------
 
234
//   openRead
 
235
//    returns true on error
 
236
//---------------------------------------------------------
 
237
 
 
238
bool SndFile::openRead()
 
239
      {
 
240
        setErrno(0);
 
241
        bool isSeekable = true;
 
242
        QString p = finfo->filePath();
 
243
        _file = fopen (p.latin1(), "r");
 
244
        if (!_file) {   
 
245
            setErrno(SFE_OPEN_FAILED);
 
246
                close();
 
247
                return true;
 
248
                }
 
249
        _mode = SF_MODE_READ;
 
250
      _filelength = 2048;
 
251
        if (isSeekable) {       
 
252
            fseek(_file, 0, SEEK_END);
 
253
                _filelength = ftell(_file) ;
 
254
                fseek (_file, 0, SEEK_SET);
 
255
                }
 
256
        
 
257
        int filetype = guess_file_type(_file, finfo->extension());
 
258
 
 
259
        switch (filetype) {     
 
260
            case  SF_FORMAT_WAV:
 
261
                      setErrno(wav_open_read());
 
262
                        break;
 
263
 
 
264
                default:
 
265
                  printf("unknown format %d 0x%0x\n", filetype, filetype);
 
266
                        setErrno(SFE_UNKNOWN_FORMAT);
 
267
                  break;
 
268
                }
 
269
        /* Both the file format and the file must be seekable to enable sf_seek(). */
 
270
        _seekable = _seekable && isSeekable;
 
271
                
 
272
        if (_errno) {   
 
273
            printf("sf open error %d\n", _errno);
 
274
                close();
 
275
                return true;
 
276
                }
 
277
        if (!validateSfinfo()) {
 
278
                _errno = SFE_BAD_SF_INFO;
 
279
            printf("sf open error %d\n", _errno);
 
280
                close();
 
281
                return true;
 
282
                };
 
283
                
 
284
        if (!validate()) {      
 
285
                _errno = SFE_INTERNAL;
 
286
            printf("sf open error %d\n", _errno);
 
287
                close();
 
288
                return true;
 
289
                }
 
290
      QString cacheName = finfo->dirPath(true) + "/" + finfo->baseName() + ".wca";
 
291
      csize             = (samples() + cacheMag - 1)/cacheMag;
 
292
      cache             = new SampleV*[channels()];
 
293
      for (unsigned ch = 0; ch < channels(); ++ch)
 
294
            cache[ch] = new SampleV[csize];
 
295
      readCache(cacheName);
 
296
        return false;
 
297
      }
 
298
 
 
299
//---------------------------------------------------------
 
300
//   search
 
301
//---------------------------------------------------------
 
302
 
 
303
SndFile* SndFileList::search(const QString& name)
 
304
      {
 
305
      for (iSndFile i = begin(); i != end(); ++i) {
 
306
            if ((*i)->path() == name)
 
307
                  return *i;
 
308
            }
 
309
      return 0;
 
310
      }
 
311
 
 
312
//---------------------------------------------------------
 
313
//   readCache
 
314
//---------------------------------------------------------
 
315
 
 
316
void SndFile::readCache(const QString& path)
 
317
      {
 
318
      FILE* cfile = fopen(path.latin1(), "r");
 
319
      if (cfile) {
 
320
            for (unsigned ch = 0; ch < channels(); ++ch)
 
321
                  fread(cache[ch], csize * sizeof(SampleV), 1, cfile);
 
322
            fclose(cfile);
 
323
            return;
 
324
            }
 
325
 
 
326
      //---------------------------------------------------
 
327
      //  create cache
 
328
      //---------------------------------------------------
 
329
 
 
330
      QString label("create peakfile for ");
 
331
      label += basename();
 
332
      QProgressDialog* progress = new QProgressDialog(label, 0, csize, 0, 0, true);
 
333
      progress->setMinimumDuration(0);
 
334
      progress->show();
 
335
      float data[channels()][cacheMag];
 
336
      float* fp[channels()];
 
337
      for (unsigned k = 0; k < channels(); ++k)
 
338
            fp[k] = &data[k][0];
 
339
      int interval = csize / 10;
 
340
      for (int i = 0; i < csize; i++) {
 
341
            if ((i % interval) == 0) {
 
342
                  progress->setProgress(i);
 
343
                  }
 
344
            seek(i * cacheMag, 0);
 
345
            read(fp, cacheMag);
 
346
            for (unsigned ch = 0; ch < channels(); ++ch) {
 
347
                  float rms = 0.0;
 
348
                  cache[ch][i].peak = 0;
 
349
                  for (int n = 0; n < cacheMag; n++) {
 
350
                        float fd = data[ch][n];
 
351
                        rms += fd * fd;
 
352
                        int idata = int(fd * 255.0);
 
353
                        if (idata < 0)
 
354
                              idata = -idata;
 
355
                        if (cache[ch][i].peak < idata)
 
356
                              cache[ch][i].peak = idata;
 
357
                        }
 
358
                  // amplify rms value +12dB
 
359
                  int rmsValue = int((sqrt(rms/cacheMag) * 255.0));
 
360
                  if (rmsValue > 255)
 
361
                        rmsValue = 255;
 
362
                  cache[ch][i].rms = rmsValue;
 
363
                  }
 
364
            }
 
365
      progress->setProgress(csize);
 
366
      writeCache(path);
 
367
      delete progress;
 
368
      }
 
369
 
 
370
//---------------------------------------------------------
 
371
//   writeCache
 
372
//---------------------------------------------------------
 
373
 
 
374
void SndFile::writeCache(const QString& path)
 
375
      {
 
376
      FILE* cfile = fopen(path.latin1(), "w");
 
377
      if (cfile == 0)
 
378
            return;
 
379
      for (unsigned ch = 0; ch < channels(); ++ch)
 
380
            fwrite(cache[ch], csize * sizeof(SampleV), 1, cfile);
 
381
      fclose(cfile);
 
382
      }
 
383
 
 
384
//---------------------------------------------------------
 
385
//   play
 
386
//---------------------------------------------------------
 
387
 
 
388
#if 0
 
389
int SndFile::play(int fd, int samplepos, int nsamples)
 
390
      {
 
391
      printf("write wave: not implemented: %d %d %d\n", fd, samplepos, nsamples);
 
392
      short* src = _data + headerOffset/2 + samplepos * _channels;
 
393
      if (samplepos + nsamples >= _samples)
 
394
            nsamples = _samples - samplepos;
 
395
      int n = nsamples * _channels * bytes;
 
396
      if (::write(fd, src, n) != n) {
 
397
            perror("write");
 
398
            fprintf(stderr, "fd %d  n %d\n", fd, n);
 
399
            return 0;
 
400
            }
 
401
      return nsamples;
 
402
      }
 
403
#endif
 
404
 
 
405
//---------------------------------------------------------
 
406
//   read
 
407
//---------------------------------------------------------
 
408
 
 
409
void SndFile::read(SampleV* s, int mag, unsigned pos)
 
410
      {
 
411
      for (unsigned ch = 0; ch < channels(); ++ch) {
 
412
            s[ch].peak = 0;
 
413
            s[ch].rms = 0;
 
414
            }
 
415
      if (pos > samples())
 
416
            return;
 
417
 
 
418
      if (mag < cacheMag) {
 
419
            float data[channels()][mag];
 
420
            float* fp[channels()];
 
421
            for (unsigned i = 0; i < channels(); ++i)
 
422
                  fp[i] = &data[i][0];
 
423
            seek(pos, 0);
 
424
            read(fp, mag);
 
425
 
 
426
            for (unsigned ch = 0; ch < channels(); ++ch) {
 
427
                  s[ch].peak = 0;
 
428
                  float rms = 0.0;
 
429
                  for (int i = 0; i < mag; i++) {
 
430
                        float fd = data[ch][i];
 
431
                        rms += fd;
 
432
                        int idata = int(fd * 255.0);
 
433
                        if (idata < 0)
 
434
                              idata = -idata;
 
435
                        if (s[ch].peak < idata)
 
436
                              s[ch].peak = idata;
 
437
                        }
 
438
                  s[ch].rms = 0;    // TODO rms / mag;
 
439
                  }
 
440
            }
 
441
      else {
 
442
            mag /= cacheMag;
 
443
            int rest = csize - (pos/cacheMag);
 
444
            int end  = mag;
 
445
            if (rest < mag)
 
446
                  end = rest;
 
447
 
 
448
            for (unsigned ch = 0; ch < channels(); ++ch) {
 
449
                  int rms = 0;
 
450
                  int off = pos/cacheMag;
 
451
                  for (int offset = off; offset < off+end; offset++) {
 
452
                        rms += cache[ch][offset].rms;
 
453
                        if (s[ch].peak < cache[ch][offset].peak)
 
454
                              s[ch].peak = cache[ch][offset].peak;
 
455
                        }
 
456
                  s[ch].rms = rms / mag;
 
457
                  }
 
458
            }
 
459
      }
 
460
 
 
461
void SndFile::setFormat(int fmt, int ch, int rate, int bits)
 
462
      {
 
463
      _format      = fmt;
 
464
      _channels    = ch;
 
465
      _samplerate  = rate;
 
466
      _pcmbitwidth = bits;
 
467
      }
 
468
 
 
469
//---------------------------------------------------------
 
470
//   openWrite
 
471
//---------------------------------------------------------
 
472
 
 
473
bool SndFile::openWrite()
 
474
      {
 
475
        _errno = 0;
 
476
 
 
477
        QString p = finfo->filePath();
 
478
        if (!(_file = fopen (p.latin1(), "w"))) {
 
479
            _errno = SFE_OPEN_FAILED;
 
480
            printf("SndFile openWrite <%s> failed: %s\n",
 
481
               p.latin1(), strerror(errno));
 
482
                close();
 
483
                return true;
 
484
                }
 
485
        _mode = SF_MODE_WRITE;
 
486
        
 
487
        _filelength = ftell(_file);
 
488
        fseek(_file, 0, SEEK_SET);
 
489
 
 
490
        switch (format() & SF_FORMAT_TYPEMASK) {        
 
491
            case SF_FORMAT_WAV:
 
492
                  if ((_errno = wav_open_write())) {    
 
493
                        close();
 
494
                              return true;
 
495
                        }
 
496
                      break;
 
497
                default:        
 
498
                  _errno = SFE_UNKNOWN_FORMAT;
 
499
                  close();
 
500
                  return true;
 
501
                }
 
502
        return false;
 
503
      }
 
504
 
 
505
//---------------------------------------------------------
 
506
//   seek
 
507
//---------------------------------------------------------
 
508
 
 
509
off_t SndFile::seek(off_t offset, int whence)
 
510
      {
 
511
        off_t realseek, position;
 
512
 
 
513
        if (!_seekable) {       
 
514
            _errno = SFE_NOT_SEEKABLE;
 
515
            return ((off_t) -1);
 
516
                }
 
517
        
 
518
        if (! (_blockwidth && _datalength && _dataoffset)) {    
 
519
            _errno = SFE_BAD_SEEK;
 
520
                return ((off_t) -1);
 
521
                }
 
522
        
 
523
        switch (whence) {       
 
524
            case SEEK_SET:
 
525
                  if (offset < 0 || offset * _blockwidth > _datalength) {       
 
526
                        _errno = SFE_BAD_SEEK;
 
527
                        return ((off_t) -1);
 
528
                        }
 
529
                  realseek = _dataoffset + offset * _blockwidth;
 
530
                  fseek(_file, realseek, SEEK_SET);
 
531
                  position = ftell(_file);
 
532
                  break;
 
533
                                
 
534
                case SEEK_CUR:
 
535
                  realseek = offset * _blockwidth;
 
536
                        position = ftell(_file) - _dataoffset;
 
537
                  if (position + realseek > (int)_datalength || position + realseek < 0) {
 
538
                        _errno = SFE_BAD_SEEK;
 
539
                        return ((off_t) -1);
 
540
                        }
 
541
                  fseek (_file, realseek, SEEK_CUR);
 
542
                  position = ftell (_file);
 
543
                  break;
 
544
                                
 
545
            case SEEK_END:
 
546
                  if (offset > 0) {     
 
547
                        _errno = SFE_BAD_SEEK;
 
548
                        return ((off_t) -1);
 
549
                        }
 
550
                  realseek = (_samples + offset) * _blockwidth + _dataoffset;
 
551
                  fseek (_file, realseek, SEEK_SET);
 
552
                  position = ftell(_file);
 
553
                  break ;
 
554
                                
 
555
                default:
 
556
                  _errno = SFE_BAD_SEEK;
 
557
                  return ((off_t) -1);
 
558
                }
 
559
      current = (position - _dataoffset) / _blockwidth;
 
560
      return current;
 
561
      }
 
562
 
 
563
#if 0
 
564
//---------------------------------------------------------
 
565
//   read_raw
 
566
//---------------------------------------------------------
 
567
 
 
568
size_t SndFile::read_raw(void *ptr, size_t bytes)
 
569
      {
 
570
        if (_mode != SF_MODE_READ) {    
 
571
            _errno = SFE_NOT_READMODE;
 
572
                return ((size_t) -1);
 
573
                }
 
574
        if (current >= _datalength) {   
 
575
            memset (ptr, 0, bytes);
 
576
                return 0;
 
577
                }
 
578
        if (bytes % (_channels * bytewidth)) {  
 
579
            _errno = SFE_BAD_READ_ALIGN;
 
580
                return (size_t) -1;
 
581
                }
 
582
        size_t count = fread(ptr, 1, bytes, _file);
 
583
        if (count < bytes)
 
584
                memset (((char*)ptr) + count, 0, bytes - count);
 
585
        current += count / _blockwidth;
 
586
        return count ;
 
587
      }
 
588
#endif
 
589
 
 
590
//---------------------------------------------------------
 
591
//   read
 
592
//---------------------------------------------------------
 
593
 
 
594
size_t SndFile::read(float** ptr, size_t frames)
 
595
      {
 
596
        if (_mode != SF_MODE_READ)
 
597
                return SFE_NOT_READMODE;
 
598
        
 
599
        if (current >= _samples) {
 
600
            for (unsigned i = 0; i < channels(); ++i)
 
601
                  memset(ptr[i], 0, frames * sizeof (float));
 
602
                return 0;
 
603
                }
 
604
        size_t count = fmt->read(ptr, frames);
 
605
        if (current + count > samples()) {      
 
606
            count        = samples() - current;
 
607
                size_t extra = frames - count ;
 
608
            for (unsigned i = 0; i < channels(); ++i)
 
609
                      memset (ptr[i] + count, 0, extra * sizeof(float));
 
610
                current = samples();
 
611
                }
 
612
        current += count;
 
613
        return count;
 
614
      }
 
615
 
 
616
#if 0
 
617
//---------------------------------------------------------
 
618
//   write_raw
 
619
//---------------------------------------------------------
 
620
 
 
621
size_t SndFile::write_raw(void *ptr, size_t len)
 
622
      {
 
623
        if (_mode != SF_MODE_WRITE) {   
 
624
            _errno = SFE_NOT_WRITEMODE;
 
625
                return (size_t) -1;
 
626
                }
 
627
        if (len % (_channels * bytewidth)) {    
 
628
            _errno = SFE_BAD_WRITE_ALIGN;
 
629
                return (size_t) -1;
 
630
                }
 
631
        size_t count = fwrite(ptr, 1, len, _file);
 
632
        current += count / _blockwidth;
 
633
        return count;
 
634
      }
 
635
#endif
 
636
 
 
637
//---------------------------------------------------------
 
638
//   write
 
639
//---------------------------------------------------------
 
640
 
 
641
size_t SndFile::write(float** ptr, size_t frames)
 
642
      {
 
643
        if (_mode != SF_MODE_WRITE) {   
 
644
            _errno = SFE_NOT_WRITEMODE;
 
645
printf("SndFile: write: error: not write mode\n");
 
646
                return (size_t) -1;
 
647
                }
 
648
// printf("SndFile: write %d frames\n", frames);
 
649
        size_t count = fmt->write(ptr, frames);
 
650
        current += count;
 
651
        return count;
 
652
      }
 
653
 
 
654
//---------------------------------------------------------
 
655
//   close
 
656
//---------------------------------------------------------
 
657
 
 
658
void SndFile::close()
 
659
      {
 
660
      if (_file) {
 
661
            if (fmt)
 
662
                  fmt->close();
 
663
              fclose(_file);
 
664
            _file = 0;
 
665
            }
 
666
      }
 
667
 
 
668
//---------------------------------------------------------
 
669
//   unimpl
 
670
//---------------------------------------------------------
 
671
 
 
672
size_t SndFileFormat::unimpl() const
 
673
      {
 
674
      sfile->setErrno(SFE_UNIMPLEMENTED);
 
675
      return (size_t) -1;
 
676
      }
 
677
 
 
678
/*-----------------------------------------------------------------------------------------------
 
679
 */
 
680
 
 
681
void endswap_short_array (short *ptr, int len)
 
682
      {
 
683
      int k;
 
684
        for (k = 0 ; k < len ; k++)
 
685
                ptr[k] = ((((ptr[k])>>8)&0xFF)|(((ptr[k])&0xFF)<<8));
 
686
      }
 
687
 
 
688
void endswap_int_array (int *ptr, int len)
 
689
      { 
 
690
      int k ;
 
691
        for (k = 0 ; k < len ; k++)
 
692
                ptr[k] = ((((ptr[k])>>24)&0xFF)|(((ptr[k])>>8)&0xFF00)|
 
693
                                        (((ptr[k])&0xFF00)<<8)|(((ptr[k])&0xFF)<<24));
 
694
      }