cwAudioFile.h/cpp : Add floating point file format.

This commit is contained in:
kevin 2021-05-08 08:15:06 -04:00
parent a511b00493
commit eed27b2e49
2 changed files with 431 additions and 68 deletions

View File

@ -42,13 +42,28 @@ namespace cw
kWavChkId = 'EVAW', kWavChkId = 'EVAW',
}; };
enum { kWriteAudioGutsFl=0x01 }; enum
{
kWriteAudioGutsFl = 0x01,
kWriteFloatFl = 0x02
};
enum
{
kIntegerFmtId = 1,
kFloatFmtId = 3,
kBitsPerByte = 8,
kMax24Bits = 0x007fffff,
kMax16Bits = 0x00007fff,
kMax32Bits = 0x7fffffff
};
typedef struct audiofile_str typedef struct audiofile_str
{ {
FILE* fp; FILE* fp;
info_t info; // audio file details info_t info; // audio file details
unsigned curFrmIdx; // current frame offset unsigned curFrmIdx; // current frame offset
unsigned fileByteCnt; // file byte cnt unsigned fileByteCnt; // file byte cnt
unsigned smpByteOffs; // byte offset of the first sample unsigned smpByteOffs; // byte offset of the first sample
marker_t* markArray; marker_t* markArray;
@ -373,11 +388,12 @@ namespace cw
p->info.chCnt = chCnt; p->info.chCnt = chCnt;
p->info.bits = bits; p->info.bits = bits;
p->info.srate = srate; p->info.srate = srate;
p->flags = fmtId == kFloatFmtId ? kWriteFloatFl : 0;
// if the 'data' chunk was read before the 'fmt' chunk then info.frameCnt // if the 'data' chunk was read before the 'fmt' chunk then info.frameCnt
// holds the number of bytes in the data chunk // holds the number of bytes in the data chunk
if( p->info.frameCnt != 0 ) if( p->info.frameCnt != 0 )
p->info.frameCnt = p->info.frameCnt / (p->info.chCnt * p->info.bits/8); p->info.frameCnt = p->info.frameCnt / (p->info.chCnt * (p->info.bits/kBitsPerByte));
return rc; return rc;
} }
@ -386,7 +402,7 @@ namespace cw
{ {
// if the 'fmt' chunk was read before the 'data' chunk then info.chCnt is non-zero // if the 'fmt' chunk was read before the 'data' chunk then info.chCnt is non-zero
if( p->info.chCnt != 0 ) if( p->info.chCnt != 0 )
p->info.frameCnt = chkByteCnt / (p->info.chCnt * p->info.bits/8); p->info.frameCnt = chkByteCnt / (p->info.chCnt * (p->info.bits/kBitsPerByte));
else else
p->info.frameCnt = chkByteCnt; p->info.frameCnt = chkByteCnt;
@ -544,7 +560,7 @@ namespace cw
doubleToX80( p->info.srate, srateX80 ); doubleToX80( p->info.srate, srateX80 );
unsigned hdrByteCnt = 54; unsigned hdrByteCnt = 54;
unsigned ssndByteCnt = 8 + (p->info.chCnt * p->info.frameCnt * (p->info.bits/8)); unsigned ssndByteCnt = 8 + (p->info.chCnt * p->info.frameCnt * (p->info.bits/kBitsPerByte));
unsigned formByteCnt = hdrByteCnt + ssndByteCnt - 8; unsigned formByteCnt = hdrByteCnt + ssndByteCnt - 8;
unsigned commByteCnt = 18; unsigned commByteCnt = 18;
unsigned ssndSmpOffs = 0; unsigned ssndSmpOffs = 0;
@ -583,8 +599,8 @@ namespace cw
unsigned frmCnt = p->info.frameCnt; unsigned frmCnt = p->info.frameCnt;
short bits = p->info.bits; short bits = p->info.bits;
unsigned srate = p->info.srate; unsigned srate = p->info.srate;
short fmtId = 1; short fmtId = p->flags & kWriteFloatFl ? kFloatFmtId : kIntegerFmtId;
unsigned bytesPerSmp = bits/8; unsigned bytesPerSmp = bits/kBitsPerByte;
unsigned hdrByteCnt = 36; unsigned hdrByteCnt = 36;
unsigned fmtByteCnt = 16; unsigned fmtByteCnt = 16;
unsigned blockAlignCnt = chCnt * bytesPerSmp; unsigned blockAlignCnt = chCnt * bytesPerSmp;
@ -674,13 +690,16 @@ namespace cw
rc_t rc = kOkRC; rc_t rc = kOkRC;
af_t* p = _handleToPtr(h); af_t* p = _handleToPtr(h);
//if( p->flags & kWriteFloatFl )
// return cwLogError(kOpFailRC,"Conversion from floating point samples to integer output is not implemented.");
if( chIdx+chCnt > p->info.chCnt ) if( chIdx+chCnt > p->info.chCnt )
return cwLogError(kInvalidArgRC,"Invalid channel index on read. %i > %i",chIdx+chCnt,chCnt); return cwLogError(kInvalidArgRC,"Invalid channel index on read. %i > %i",chIdx+chCnt,chCnt);
if( actualFrmCntPtr != NULL ) if( actualFrmCntPtr != NULL )
*actualFrmCntPtr = 0; *actualFrmCntPtr = 0;
unsigned bps = p->info.bits / 8; // bytes per sample unsigned bps = p->info.bits / kBitsPerByte; // bytes per sample
unsigned bpf = bps * p->info.chCnt; // bytes per file frame unsigned bpf = bps * p->info.chCnt; // bytes per file frame
unsigned bufFrmCnt = std::min(totalFrmCnt,(unsigned)cwAudioFile_MAX_FRAME_READ_CNT); unsigned bufFrmCnt = std::min(totalFrmCnt,(unsigned)cwAudioFile_MAX_FRAME_READ_CNT);
unsigned bytesPerBuf = bufFrmCnt * bpf; unsigned bytesPerBuf = bufFrmCnt * bpf;
@ -842,7 +861,6 @@ namespace cw
if( actualFrmCntPtr != NULL ) if( actualFrmCntPtr != NULL )
*actualFrmCntPtr = 0; *actualFrmCntPtr = 0;
unsigned totalReadCnt = 0; unsigned totalReadCnt = 0;
unsigned bufFrmCnt = std::min( totalFrmCnt, (unsigned)cwAudioFile_MAX_FRAME_READ_CNT ); unsigned bufFrmCnt = std::min( totalFrmCnt, (unsigned)cwAudioFile_MAX_FRAME_READ_CNT );
unsigned bufSmpCnt = bufFrmCnt * chCnt; unsigned bufSmpCnt = bufFrmCnt * chCnt;
@ -864,7 +882,7 @@ namespace cw
default: default:
return cwLogError(kInvalidArgRC,"Audio file invalid sample word size:%i bits.",p->info.bits); return cwLogError(kInvalidArgRC,"Audio file invalid sample word size:%i bits.",p->info.bits);
} }
double dblMaxSmpVal = fltMaxSmpVal; double dblMaxSmpVal = fltMaxSmpVal;
// initialize the audio ptr buffers // initialize the audio ptr buffers
@ -877,7 +895,6 @@ namespace cw
if( fbuf != NULL ) if( fbuf != NULL )
fPtrBuf[i] = fbuf[i]; fPtrBuf[i] = fbuf[i];
} }
// //
@ -886,61 +903,116 @@ namespace cw
unsigned actualReadFrmCnt = 0; unsigned actualReadFrmCnt = 0;
frmCnt = std::min( p->info.frameCnt - p->curFrmIdx, std::min( totalFrmCnt-totalReadCnt, bufFrmCnt ) ); frmCnt = std::min( p->info.frameCnt - p->curFrmIdx, std::min( totalFrmCnt-totalReadCnt, bufFrmCnt ) );
// fill the integer audio buffer from the file // Fill the integer audio buffer from the file.
// Note that the input format may be float but this is ok since there size is the same and _readInt() does not processes the values.
if((rc = _readInt( h, frmCnt, chIdx, chCnt, ptrBuf, &actualReadFrmCnt, false )) != kOkRC ) if((rc = _readInt( h, frmCnt, chIdx, chCnt, ptrBuf, &actualReadFrmCnt, false )) != kOkRC )
return rc; return rc;
if( actualFrmCntPtr != NULL ) if( actualFrmCntPtr != NULL )
*actualFrmCntPtr += actualReadFrmCnt; *actualFrmCntPtr += actualReadFrmCnt;
// convert the integer buffer to floating point // Convert the integer buffer to floating point
for(i=0; i<chCnt; ++i) for(i=0; i<chCnt; ++i)
{ {
int* sp = ptrBuf[i]; // if the input is already in float format
if( p->flags & kWriteFloatFl )
if( fbuf != NULL )
{ {
float* sp = (float*)ptrBuf[i];
float* dp = fPtrBuf[i];
float* ep = dp + frmCnt; // if output is in float (not double) format
if( fbuf != NULL )
if( sumFl )
{ {
for(; dp<ep; ++dp,++sp) float* dp = fPtrBuf[i];
*dp += ((float)*sp) / fltMaxSmpVal; float* ep = dp + frmCnt;
if( sumFl )
{
for(; dp<ep; ++dp,++sp)
*dp += *sp;
}
else
{
for(; dp<ep; ++dp,++sp)
*dp = *sp;
}
assert( dp <= fbuf[i] + totalFrmCnt );
fPtrBuf[i] = dp;
} }
else else // uf output is in double (not float) format
{ {
for(; dp<ep; ++dp,++sp)
*dp = ((float)*sp) / fltMaxSmpVal; double* dp = dPtrBuf[i];
double* ep = dp + frmCnt;
if( sumFl )
{
for(; dp<ep; ++dp,++sp)
*dp += ((double)*sp);
}
else
{
for(; dp<ep; ++dp,++sp)
*dp = ((double)*sp);
}
assert( dp <= dbuf[i] + totalFrmCnt );
dPtrBuf[i] = dp;
} }
assert( dp <= fbuf[i] + totalFrmCnt );
fPtrBuf[i] = dp;
} }
else else // if input is an integer format (not float format)
{ {
double* dp = dPtrBuf[i]; int* sp = ptrBuf[i];
double* ep = dp + frmCnt;
// if output is float (not double)
if( sumFl ) if( fbuf != NULL )
{ {
for(; dp<ep; ++dp,++sp)
*dp += ((double)*sp) / dblMaxSmpVal;
}
else
{
for(; dp<ep; ++dp,++sp)
*dp = ((double)*sp) / dblMaxSmpVal;
}
assert( dp <= dbuf[i] + totalFrmCnt ); float* dp = fPtrBuf[i];
dPtrBuf[i] = dp; float* ep = dp + frmCnt;
if( sumFl )
{
for(; dp<ep; ++dp,++sp)
*dp += ((float)*sp) / fltMaxSmpVal;
}
else
{
for(; dp<ep; ++dp,++sp)
*dp = ((float)*sp) / fltMaxSmpVal;
}
assert( dp <= fbuf[i] + totalFrmCnt );
fPtrBuf[i] = dp;
}
else // output is double (not float)
{
double* dp = dPtrBuf[i];
double* ep = dp + frmCnt;
if( sumFl )
{
for(; dp<ep; ++dp,++sp)
*dp += ((double)*sp) / dblMaxSmpVal;
}
else
{
for(; dp<ep; ++dp,++sp)
*dp = ((double)*sp) / dblMaxSmpVal;
}
assert( dp <= dbuf[i] + totalFrmCnt );
dPtrBuf[i] = dp;
}
} }
} }
} }
@ -1011,6 +1083,225 @@ namespace cw
return rc; return rc;
} }
rc_t _write_samples_to_file( af_t* p, unsigned bytesPerSmp, unsigned bufSmpCnt, void* buf )
{
rc_t rc = kOkRC;
if( fwrite( buf, bufSmpCnt*bytesPerSmp, 1, p->fp ) != 1)
rc = cwLogError(kWriteFailRC,"Audio file write failed on '%s'.",cwStringNullGuard(p->fn));
return rc;
}
//
// Write 8 bit samples
//
// sample writer: int->uint8_t
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const int* sbuf, int8_t* dbuf )
{
for(unsigned i=0; i<bufSmpCnt; ++i)
dbuf[i] = (((long)sbuf[i]*255) / ((long)INT_MAX - INT_MIN)) + 127;
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
// sample writer: float->uint8_t
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const float* sbuf, int8_t* dbuf )
{
for(unsigned i=0; i<bufSmpCnt; ++i)
dbuf[i] = (uint8_t)(sbuf[i] * 128) + 127;
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
// sample writer: double->uint8_t
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const double* sbuf, int8_t* dbuf )
{
for(unsigned i=0; i<bufSmpCnt; ++i)
dbuf[i] = (uint8_t)(sbuf[i] * 128) + 127;
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
//
// Write 16 bit samples
//
// sample writer: int->short
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const int* sbuf, short* dbuf )
{
for(unsigned i=0; i<bufSmpCnt; ++i)
dbuf[i] = ((long)sbuf[i]*2*SHRT_MAX) / ((long)INT_MAX - INT_MIN);
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
// sample writer: float->short
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const float* sbuf, short* dbuf )
{
for(unsigned i=0; i<bufSmpCnt; ++i)
dbuf[i] = (short)(sbuf[i] * SHRT_MAX);
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
// sample writer: double->short
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const double* sbuf, short* dbuf )
{
for(unsigned i=0; i<bufSmpCnt; ++i)
dbuf[i] = (short)(sbuf[i] * SHRT_MAX);
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
//
// Write 24 bit samples
//
inline void int_to_24( int v, uint8_t* d )
{
uint8_t* s = (uint8_t*)(&v);
d[0] = s[0];
d[1] = s[1];
d[2] = s[2];
}
// sample writer: int->int24
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const int* sbuf, uint32_t* dbuf )
{
uint8_t* dbp = (uint8_t*)dbuf;
for(unsigned i=0; i<bufSmpCnt; dbp+=3, ++i)
int_to_24(sbuf[i],dbp);
return _write_samples_to_file(p,3,bufSmpCnt,dbuf);
}
// sample writer: float->int24
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const float* sbuf, uint32_t* dbuf )
{
uint8_t* dbp = (uint8_t*)dbuf;
for(unsigned i=0; i<bufSmpCnt; dbp+=3, ++i)
{
int ismp = sbuf[i]*kMax24Bits;
int_to_24(ismp,dbp);
}
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
// sample writer: double->int24
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const double* sbuf, uint32_t* dbuf )
{
uint8_t* dbp = (uint8_t*)dbuf;
for(unsigned i=0; i<bufSmpCnt; dbp+=3, ++i)
{
int ismp = sbuf[i]*kMax24Bits;
int_to_24(ismp,dbp);
}
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
//
// Write 32 bit samples
//
// sample writer: int->int
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const int* sbuf, int* dbuf )
{
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
// float->int
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const float* sbuf, int* dbuf )
{
for(unsigned i=0; i<bufSmpCnt; ++i)
dbuf[i] = (int)(sbuf[i] * INT_MAX);
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
// double->int
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const double* sbuf, int* dbuf )
{
for(unsigned i=0; i<bufSmpCnt; ++i)
dbuf[i] = (int)(sbuf[i] * INT_MAX);
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
//
// Write float samples
//
// int->float
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const int* sbuf, float* dbuf )
{
for(unsigned i=0; i<bufSmpCnt; ++i)
dbuf[i] = sbuf[i]/INT_MAX;
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
// float->float
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const float* sbuf, float* dbuf )
{
memcpy(dbuf,sbuf,bufSmpCnt*sizeof(float));
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
// double->float
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const double* sbuf, float* dbuf )
{
for(unsigned i=0; i<bufSmpCnt; ++i)
dbuf[i] = (float)(sbuf[i]);
return _write_samples_to_file(p,sizeof(dbuf[0]),bufSmpCnt,dbuf);
}
template< typename S, typename D >
rc_t _write_samples( af_t* p, unsigned bufSmpCnt, const S* sbuf, D* dbuf)
{
return cwLogError(kInvalidDataTypeRC,"The source and desintation sample types are not supported by the audio file writer.");
}
template< typename S, typename D >
rc_t _write_audio( af_t* p, unsigned srcBufFrmCnt, unsigned chCnt, const S* const * srcPtrPtr )
{
rc_t rc = kOkRC;
// Determine the size of the temporary buffer used for deinterleaving, type conversion and file writing
unsigned bufFrmCnt = std::min(srcBufFrmCnt,4096u);
unsigned bufSmpCnt = bufFrmCnt*chCnt;
// allocate the temp. buffers
S sbuf[ bufSmpCnt ];
D dbuf[ bufSmpCnt ];
// for each frame in the source
for(unsigned sfi=0; sfi<srcBufFrmCnt; )
{
// copy as many samples as are available into the temp. buffer
unsigned copyFrmN = std::min( bufFrmCnt, srcBufFrmCnt - sfi );
// deinterleave the source channel signal arrays into the temp buffer
for(unsigned fi=0,si=0; fi<copyFrmN; ++fi)
for(unsigned sci=0; sci<chCnt; ++sci,++si)
sbuf[si] = srcPtrPtr[sci][sfi+fi];
// convert the sample data types and write the result to the output file
if((rc = _write_samples(p,copyFrmN*chCnt,sbuf,dbuf)) != kOkRC )
break;
p->info.frameCnt += copyFrmN;
sfi += copyFrmN;
}
return rc;
}
/*
rc_t _writeRealSamples( handle_t h, unsigned frmCnt, unsigned chCnt, const void* srcPtrPtr, unsigned realSmpByteCnt ) rc_t _writeRealSamples( handle_t h, unsigned frmCnt, unsigned chCnt, const void* srcPtrPtr, unsigned realSmpByteCnt )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
@ -1093,6 +1384,7 @@ namespace cw
return rc; return rc;
} }
*/
void _test( const char* audioFn ) void _test( const char* audioFn )
{ {
@ -1181,12 +1473,13 @@ cw::rc_t cw::audiofile::create( handle_t& h, const char* fn, double srate, unsig
} }
else else
{ {
p->fn = mem::duplStr( fn ); p->fn = mem::duplStr( fn );
p->info.srate = srate; p->info.srate = srate;
p->info.bits = bits; p->info.bits = bits==0 ? sizeof(float)*kBitsPerByte : bits;
p->info.chCnt = chCnt; p->info.chCnt = chCnt;
p->info.frameCnt = 0; p->info.frameCnt = 0;
p->flags = kWriteAudioGutsFl; p->flags = kWriteAudioGutsFl + (bits==0 ? kWriteFloatFl : 0);
// set the swap flags // set the swap flags
bool swapFl = cwIsFlag(p->info.flags,kWavAfFl) ? _cmWavSwapFl : _cmAifSwapFl; bool swapFl = cwIsFlag(p->info.flags,kWavAfFl) ? _cmWavSwapFl : _cmAifSwapFl;
@ -1250,7 +1543,7 @@ cw::rc_t cw::audiofile::seek( handle_t h, unsigned frmIdx )
rc_t rc = kOkRC; rc_t rc = kOkRC;
af_t* p = _handleToPtr(h); af_t* p = _handleToPtr(h);
if((rc = _seek(p,p->smpByteOffs + (frmIdx * p->info.chCnt * (p->info.bits/8)), SEEK_SET)) != kOkRC ) if((rc = _seek(p,p->smpByteOffs + (frmIdx * p->info.chCnt * (p->info.bits/kBitsPerByte)), SEEK_SET)) != kOkRC )
return rc; return rc;
p->curFrmIdx = frmIdx; p->curFrmIdx = frmIdx;
@ -1355,11 +1648,11 @@ cw::rc_t cw::audiofile::freeFloatBuf( float** floatBuf, unsigned chCnt )
} }
cw::rc_t cw::audiofile::writeInt( handle_t h, unsigned frmCnt, unsigned chCnt, int** srcPtrPtr ) cw::rc_t cw::audiofile::writeInt( handle_t h, unsigned frmCnt, unsigned chCnt, const int* const* srcPtrPtr )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
af_t* p = _handleToPtr(h); af_t* p = _handleToPtr(h);
unsigned bytesPerSmp = p->info.bits / 8; unsigned bytesPerSmp = p->info.bits / kBitsPerByte;
unsigned bufFrmCnt = 1024; unsigned bufFrmCnt = 1024;
unsigned bufByteCnt = bufFrmCnt * bytesPerSmp; unsigned bufByteCnt = bufFrmCnt * bytesPerSmp;
unsigned ci; unsigned ci;
@ -1484,11 +1777,78 @@ cw::rc_t cw::audiofile::writeInt( handle_t h, unsigned frmCnt, unsigned ch
} }
cw::rc_t cw::audiofile::writeFloat( handle_t h, unsigned frmCnt, unsigned chCnt, float** bufPtrPtr ) cw::rc_t cw::audiofile::writeFloat( handle_t h, unsigned frmCnt, unsigned chCnt, const float* const* srcPtrPtr )
{ return _writeRealSamples(h,frmCnt,chCnt,bufPtrPtr,sizeof(float)); } {
rc_t rc = kOkRC;
af_t* p = _handleToPtr(h);
if( p->flags & kWriteFloatFl )
rc = _write_audio<float,float>( p, frmCnt, chCnt, srcPtrPtr );
else
{
switch(p->info.bits)
{
case 8:
rc = _write_audio<float,uint8_t>( p, frmCnt, chCnt, srcPtrPtr );
break;
case 16:
rc = _write_audio<float,short>( p, frmCnt, chCnt, srcPtrPtr );
break;
case 24:
break;
case 32:
rc = _write_audio<float,int>( p, frmCnt, chCnt, srcPtrPtr );
break;
cw::rc_t cw::audiofile::writeDouble( handle_t h, unsigned frmCnt, unsigned chCnt, double** bufPtrPtr ) default:
{ return _writeRealSamples(h,frmCnt,chCnt,bufPtrPtr,sizeof(double)); } cwLogError(kInvalidArgRC,"Invalid bit depth:%i",p->info.bits);
}
}
return rc;
//return _writeRealSamples(h,frmCnt,chCnt,bufPtrPtr,sizeof(float));
}
cw::rc_t cw::audiofile::writeDouble( handle_t h, unsigned frmCnt, unsigned chCnt, const double* const* srcPtrPtr )
{
rc_t rc = kOkRC;
af_t* p = _handleToPtr(h);
if( p->flags & kWriteFloatFl )
rc = _write_audio<double,float>( p, frmCnt, chCnt, srcPtrPtr );
else
{
switch(p->info.bits)
{
case 8:
rc = _write_audio<double,uint8_t>( p, frmCnt, chCnt, srcPtrPtr );
break;
case 16:
rc = _write_audio<double,short>( p, frmCnt, chCnt, srcPtrPtr );
break;
case 24:
break;
case 32:
rc = _write_audio<double,int>( p, frmCnt, chCnt, srcPtrPtr );
break;
default:
cwLogError(kInvalidArgRC,"Invalid bit depth:%i",p->info.bits);
}
}
return rc;
//return _writeRealSamples(h,frmCnt,chCnt,bufPtrPtr,sizeof(double));
}
@ -1547,11 +1907,11 @@ cw::rc_t cw::audiofile::minMaxMean( handle_t h, unsigned chIdx, float* minPtr
} }
cw::rc_t cw::audiofile::writeFileInt( const char* fn, double srate, unsigned bits, unsigned frmCnt, unsigned chCnt, int** bufPtrPtr ) cw::rc_t cw::audiofile::writeFileInt( const char* fn, double srate, unsigned bits, unsigned frmCnt, unsigned chCnt, const int* const* bufPtrPtr )
{ {
rc_t rc; rc_t rc;
handle_t h; handle_t h;
if(( rc = create(h,fn,srate,bits,chCnt)) != kOkRC ) if(( rc = create(h,fn,srate,bits,chCnt)) != kOkRC )
{ {
rc = writeInt( h, frmCnt, chCnt, bufPtrPtr ); rc = writeInt( h, frmCnt, chCnt, bufPtrPtr );
@ -1562,7 +1922,7 @@ cw::rc_t cw::audiofile::writeFileInt( const char* fn, double srate, unsign
return rc; return rc;
} }
cw::rc_t cw::audiofile::writeFileFloat( const char* fn, double srate, unsigned bits, unsigned frmCnt, unsigned chCnt, float** bufPtrPtr ) cw::rc_t cw::audiofile::writeFileFloat( const char* fn, double srate, unsigned bits, unsigned frmCnt, unsigned chCnt, const float* const* bufPtrPtr )
{ {
rc_t rc; rc_t rc;
handle_t h; handle_t h;
@ -1577,7 +1937,7 @@ cw::rc_t cw::audiofile::writeFileFloat( const char* fn, double srate, unsign
return rc; return rc;
} }
cw::rc_t cw::audiofile::writeFileDouble( const char* fn, double srate, unsigned bits, unsigned frmCnt, unsigned chCnt, double** bufPtrPtr ) cw::rc_t cw::audiofile::writeFileDouble( const char* fn, double srate, unsigned bits, unsigned frmCnt, unsigned chCnt, const double* const* bufPtrPtr )
{ {
rc_t rc; rc_t rc;
handle_t h; handle_t h;

View File

@ -22,7 +22,7 @@ namespace cw
kWavAfFl = 0x02, // this is a WAV file kWavAfFl = 0x02, // this is a WAV file
kSwapAfFl = 0x04, // file header bytes must be swapped kSwapAfFl = 0x04, // file header bytes must be swapped
kAifcAfFl = 0x08, // this is an AIFC file kAifcAfFl = 0x08, // this is an AIFC file
kSwapSamplesAfFl = 0x10 // file sample bytes must be swapped kSwapSamplesAfFl = 0x10, // file sample bytes must be swapped
}; };
@ -75,7 +75,8 @@ namespace cw
rc_t open( handle_t& h, const char* fn, info_t* info ); rc_t open( handle_t& h, const char* fn, info_t* info );
// Set bits to 0 to write the file in IEEE float format.
rc_t create( handle_t& h, const char* fn, double srate, unsigned bits, unsigned chN ); rc_t create( handle_t& h, const char* fn, double srate, unsigned bits, unsigned chN );
rc_t close( handle_t& h ); rc_t close( handle_t& h );
@ -134,13 +135,15 @@ namespace cw
rc_t freeFloatBuf( float** floatBufRef, unsigned chCnt ); rc_t freeFloatBuf( float** floatBufRef, unsigned chCnt );
// Sample Writing Functions // Sample Writing Functions
rc_t writeInt( handle_t h, unsigned frmCnt, unsigned chCnt, int** bufPtrPtr ); rc_t writeInt( handle_t h, unsigned frmCnt, unsigned chCnt, const int* const* bufPtrPtr );
rc_t writeFloat( handle_t h, unsigned frmCnt, unsigned chCnt, float** bufPtrPtr ); rc_t writeFloat( handle_t h, unsigned frmCnt, unsigned chCnt, const float* const* bufPtrPtr );
rc_t writeDouble( handle_t h, unsigned frmCnt, unsigned chCnt, double** bufPtrPtr ); rc_t writeDouble( handle_t h, unsigned frmCnt, unsigned chCnt, const double* const* bufPtrPtr );
rc_t writeFileInt( const char* fn, double srate, unsigned bit, unsigned frmCnt, unsigned chCnt, int** bufPtrPtr); // File Writing Functions
rc_t writeFileFloat( const char* fn, double srate, unsigned bit, unsigned frmCnt, unsigned chCnt, float** bufPtrPtr); // Set 'bit' to 0 to write the file in IEEE float format.
rc_t writeFileDouble( const char* fn, double srate, unsigned bit, unsigned frmCnt, unsigned chCnt, double** bufPtrPtr); rc_t writeFileInt( const char* fn, double srate, unsigned bit, unsigned frmCnt, unsigned chCnt, const int* const * bufPtrPtr);
rc_t writeFileFloat( const char* fn, double srate, unsigned bit, unsigned frmCnt, unsigned chCnt, const float* const* bufPtrPtr);
rc_t writeFileDouble( const char* fn, double srate, unsigned bit, unsigned frmCnt, unsigned chCnt, const double* const* bufPtrPtr);
// Scan an entire audio file and return the minimum, maximum and mean sample value. // Scan an entire audio file and return the minimum, maximum and mean sample value.