1
//=========================================================
4
// $Id: sndfile.cpp,v 1.2 2002/02/13 11:42:56 muse Exp $
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
//=========================================================
22
#include <qprogressdialog.h>
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))
33
# error "Cannot determine endian-ness of processor."
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." },
63
{ SFE_SHORT_READ , "Short read error." },
64
{ SFE_SHORT_WRITE , "Short write error." },
65
{ SFE_INTERNAL , "Unspecified internal error." },
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." },
72
{ SFE_WAV_FMT_TOO_BIG , "Error in WAV file. 'fmt ' chunk too large." },
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." },
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."},
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."},
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."},
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."},
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."},
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."},
105
{ SFE_NIST_BAD_HEADER , "Error in NIST file, bad header."},
106
{ SFE_NIST_BAD_ENCODING , "Error in NIST file, unsupported compression format."},
108
{ SFE_MAX_ERROR , "Maximum error number." }
113
static int is_au_snd_file (const QString ext)
115
return ext == "au" || ext == "snd";
118
static int guess_file_type (FILE *file, const QString ext)
120
unsigned int buffer[3];
122
fread(buffer, sizeof(buffer), 1, file);
123
fseek(file, 0, SEEK_SET);
125
if (buffer [0] == MAKE_MARKER ('R','I','F','F') && buffer [2] == MAKE_MARKER ('W','A','V','E'))
126
return SF_FORMAT_WAV ;
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;
136
if ((buffer [0] == MAKE_MARKER ('.','s','n','d') || buffer [0] == MAKE_MARKER ('d','n','s','.')))
139
if ((buffer [0] == MAKE_MARKER ('f','a','p',' ') || buffer [0] == MAKE_MARKER (' ','p','a','f')))
140
return SF_FORMAT_PAF;
142
if (buffer [0] == MAKE_MARKER ('N','I','S','T'))
143
return SF_FORMAT_NIST;
145
if (is_au_snd_file (ext))
146
return SF_FORMAT_AU | SF_FORMAT_ULAW;
148
/* Default to header-less RAW PCM file type. */
149
return SF_FORMAT_RAW;
153
//---------------------------------------------------------
155
//---------------------------------------------------------
157
bool SndFile::validateSfinfo()
165
if (!_format & SF_FORMAT_TYPEMASK)
167
if (!_format & SF_FORMAT_SUBMASK)
174
bool SndFile::validate()
182
if (_blockwidth != _channels * _bytewidth)
187
//---------------------------------------------------------
189
//---------------------------------------------------------
191
SndFile::SndFile(const QString path)
193
finfo = new QFileInfo(path);
206
int SndFile::incRef()
209
// printf("SndFile::incRef %d\n", refs);
213
int SndFile::decRef()
216
// printf("SndFile::decRef %d\n", refs);
226
for (unsigned i = 0; i < channels(); ++i)
233
//---------------------------------------------------------
235
// returns true on error
236
//---------------------------------------------------------
238
bool SndFile::openRead()
241
bool isSeekable = true;
242
QString p = finfo->filePath();
243
_file = fopen (p.latin1(), "r");
245
setErrno(SFE_OPEN_FAILED);
249
_mode = SF_MODE_READ;
252
fseek(_file, 0, SEEK_END);
253
_filelength = ftell(_file) ;
254
fseek (_file, 0, SEEK_SET);
257
int filetype = guess_file_type(_file, finfo->extension());
261
setErrno(wav_open_read());
265
printf("unknown format %d 0x%0x\n", filetype, filetype);
266
setErrno(SFE_UNKNOWN_FORMAT);
269
/* Both the file format and the file must be seekable to enable sf_seek(). */
270
_seekable = _seekable && isSeekable;
273
printf("sf open error %d\n", _errno);
277
if (!validateSfinfo()) {
278
_errno = SFE_BAD_SF_INFO;
279
printf("sf open error %d\n", _errno);
285
_errno = SFE_INTERNAL;
286
printf("sf open error %d\n", _errno);
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);
299
//---------------------------------------------------------
301
//---------------------------------------------------------
303
SndFile* SndFileList::search(const QString& name)
305
for (iSndFile i = begin(); i != end(); ++i) {
306
if ((*i)->path() == name)
312
//---------------------------------------------------------
314
//---------------------------------------------------------
316
void SndFile::readCache(const QString& path)
318
FILE* cfile = fopen(path.latin1(), "r");
320
for (unsigned ch = 0; ch < channels(); ++ch)
321
fread(cache[ch], csize * sizeof(SampleV), 1, cfile);
326
//---------------------------------------------------
328
//---------------------------------------------------
330
QString label("create peakfile for ");
332
QProgressDialog* progress = new QProgressDialog(label, 0, csize, 0, 0, true);
333
progress->setMinimumDuration(0);
335
float data[channels()][cacheMag];
336
float* fp[channels()];
337
for (unsigned k = 0; k < channels(); ++k)
339
int interval = csize / 10;
340
for (int i = 0; i < csize; i++) {
341
if ((i % interval) == 0) {
342
progress->setProgress(i);
344
seek(i * cacheMag, 0);
346
for (unsigned ch = 0; ch < channels(); ++ch) {
348
cache[ch][i].peak = 0;
349
for (int n = 0; n < cacheMag; n++) {
350
float fd = data[ch][n];
352
int idata = int(fd * 255.0);
355
if (cache[ch][i].peak < idata)
356
cache[ch][i].peak = idata;
358
// amplify rms value +12dB
359
int rmsValue = int((sqrt(rms/cacheMag) * 255.0));
362
cache[ch][i].rms = rmsValue;
365
progress->setProgress(csize);
370
//---------------------------------------------------------
372
//---------------------------------------------------------
374
void SndFile::writeCache(const QString& path)
376
FILE* cfile = fopen(path.latin1(), "w");
379
for (unsigned ch = 0; ch < channels(); ++ch)
380
fwrite(cache[ch], csize * sizeof(SampleV), 1, cfile);
384
//---------------------------------------------------------
386
//---------------------------------------------------------
389
int SndFile::play(int fd, int samplepos, int nsamples)
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) {
398
fprintf(stderr, "fd %d n %d\n", fd, n);
405
//---------------------------------------------------------
407
//---------------------------------------------------------
409
void SndFile::read(SampleV* s, int mag, unsigned pos)
411
for (unsigned ch = 0; ch < channels(); ++ch) {
418
if (mag < cacheMag) {
419
float data[channels()][mag];
420
float* fp[channels()];
421
for (unsigned i = 0; i < channels(); ++i)
426
for (unsigned ch = 0; ch < channels(); ++ch) {
429
for (int i = 0; i < mag; i++) {
430
float fd = data[ch][i];
432
int idata = int(fd * 255.0);
435
if (s[ch].peak < idata)
438
s[ch].rms = 0; // TODO rms / mag;
443
int rest = csize - (pos/cacheMag);
448
for (unsigned ch = 0; ch < channels(); ++ch) {
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;
456
s[ch].rms = rms / mag;
461
void SndFile::setFormat(int fmt, int ch, int rate, int bits)
469
//---------------------------------------------------------
471
//---------------------------------------------------------
473
bool SndFile::openWrite()
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));
485
_mode = SF_MODE_WRITE;
487
_filelength = ftell(_file);
488
fseek(_file, 0, SEEK_SET);
490
switch (format() & SF_FORMAT_TYPEMASK) {
492
if ((_errno = wav_open_write())) {
498
_errno = SFE_UNKNOWN_FORMAT;
505
//---------------------------------------------------------
507
//---------------------------------------------------------
509
off_t SndFile::seek(off_t offset, int whence)
511
off_t realseek, position;
514
_errno = SFE_NOT_SEEKABLE;
518
if (! (_blockwidth && _datalength && _dataoffset)) {
519
_errno = SFE_BAD_SEEK;
525
if (offset < 0 || offset * _blockwidth > _datalength) {
526
_errno = SFE_BAD_SEEK;
529
realseek = _dataoffset + offset * _blockwidth;
530
fseek(_file, realseek, SEEK_SET);
531
position = ftell(_file);
535
realseek = offset * _blockwidth;
536
position = ftell(_file) - _dataoffset;
537
if (position + realseek > (int)_datalength || position + realseek < 0) {
538
_errno = SFE_BAD_SEEK;
541
fseek (_file, realseek, SEEK_CUR);
542
position = ftell (_file);
547
_errno = SFE_BAD_SEEK;
550
realseek = (_samples + offset) * _blockwidth + _dataoffset;
551
fseek (_file, realseek, SEEK_SET);
552
position = ftell(_file);
556
_errno = SFE_BAD_SEEK;
559
current = (position - _dataoffset) / _blockwidth;
564
//---------------------------------------------------------
566
//---------------------------------------------------------
568
size_t SndFile::read_raw(void *ptr, size_t bytes)
570
if (_mode != SF_MODE_READ) {
571
_errno = SFE_NOT_READMODE;
572
return ((size_t) -1);
574
if (current >= _datalength) {
575
memset (ptr, 0, bytes);
578
if (bytes % (_channels * bytewidth)) {
579
_errno = SFE_BAD_READ_ALIGN;
582
size_t count = fread(ptr, 1, bytes, _file);
584
memset (((char*)ptr) + count, 0, bytes - count);
585
current += count / _blockwidth;
590
//---------------------------------------------------------
592
//---------------------------------------------------------
594
size_t SndFile::read(float** ptr, size_t frames)
596
if (_mode != SF_MODE_READ)
597
return SFE_NOT_READMODE;
599
if (current >= _samples) {
600
for (unsigned i = 0; i < channels(); ++i)
601
memset(ptr[i], 0, frames * sizeof (float));
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));
617
//---------------------------------------------------------
619
//---------------------------------------------------------
621
size_t SndFile::write_raw(void *ptr, size_t len)
623
if (_mode != SF_MODE_WRITE) {
624
_errno = SFE_NOT_WRITEMODE;
627
if (len % (_channels * bytewidth)) {
628
_errno = SFE_BAD_WRITE_ALIGN;
631
size_t count = fwrite(ptr, 1, len, _file);
632
current += count / _blockwidth;
637
//---------------------------------------------------------
639
//---------------------------------------------------------
641
size_t SndFile::write(float** ptr, size_t frames)
643
if (_mode != SF_MODE_WRITE) {
644
_errno = SFE_NOT_WRITEMODE;
645
printf("SndFile: write: error: not write mode\n");
648
// printf("SndFile: write %d frames\n", frames);
649
size_t count = fmt->write(ptr, frames);
654
//---------------------------------------------------------
656
//---------------------------------------------------------
658
void SndFile::close()
668
//---------------------------------------------------------
670
//---------------------------------------------------------
672
size_t SndFileFormat::unimpl() const
674
sfile->setErrno(SFE_UNIMPLEMENTED);
678
/*-----------------------------------------------------------------------------------------------
681
void endswap_short_array (short *ptr, int len)
684
for (k = 0 ; k < len ; k++)
685
ptr[k] = ((((ptr[k])>>8)&0xFF)|(((ptr[k])&0xFF)<<8));
688
void endswap_int_array (int *ptr, int len)
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));