195 lines
9.9 KiB
C++
195 lines
9.9 KiB
C++
//| Copyright: (C) 2020-2024 Kevin Larke <contact AT larke DOT org>
|
|
//| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
|
|
#ifndef cwAudioFile_h
|
|
#define cwAudioFile_h
|
|
|
|
#ifndef cwAudioFile_MAX_FRAME_READ_CNT
|
|
// Maximum number of samples which will be read in one call to fread().
|
|
// This value is only significant in that an internal buffer is created on the stack
|
|
// whose size must be limited to prevent stack overflows.
|
|
#define cwAudioFile_MAX_FRAME_READ_CNT (8192)
|
|
#endif
|
|
|
|
|
|
namespace cw
|
|
{
|
|
namespace audiofile
|
|
{
|
|
typedef handle<struct audiofile_str> handle_t;
|
|
|
|
// Informational flags used by audioFileInfo
|
|
enum
|
|
{
|
|
kAiffAfFl = 0x01, // this is an AIFF file
|
|
kWavAfFl = 0x02, // this is a WAV file
|
|
kSwapAfFl = 0x04, // file header bytes must be swapped
|
|
kAifcAfFl = 0x08, // this is an AIFC file
|
|
kSwapSamplesAfFl = 0x10, // file sample bytes must be swapped
|
|
};
|
|
|
|
|
|
// Constants
|
|
enum
|
|
{
|
|
kAudioFileLabelCharCnt = 256,
|
|
|
|
kAfBextDescN = 256,
|
|
kAfBextOriginN = 32,
|
|
kAfBextOriginRefN = 32,
|
|
kAfBextOriginDateN = 10,
|
|
kAfBextOriginTimeN = 8
|
|
};
|
|
|
|
// Aiff marker record
|
|
typedef struct
|
|
{
|
|
unsigned id;
|
|
unsigned frameIdx;
|
|
char label[kAudioFileLabelCharCnt];
|
|
} marker_t;
|
|
|
|
// Broadcast WAV header record As used by ProTools audio files. See http://en.wikipedia.org/wiki/Broadcast_Wave_Format
|
|
// When generated from Protools the timeRefLow/timeRefHigh values appear to actually refer
|
|
// to the position on the Protools time-line rather than the wall clock time.
|
|
typedef struct
|
|
{
|
|
char desc[ kAfBextDescN + 1 ];
|
|
char origin[ kAfBextOriginN + 1 ];
|
|
char originRef[ kAfBextOriginRefN + 1 ];
|
|
char originDate[kAfBextOriginDateN + 1 ];
|
|
char originTime[kAfBextOriginTimeN + 1 ];
|
|
unsigned timeRefLow; // sample count since midnight low word
|
|
unsigned timeRefHigh; // sample count since midnight high word
|
|
} bext_t;
|
|
|
|
// Audio file information record used by audioFileNew and audioFileOpen
|
|
typedef struct
|
|
{
|
|
unsigned bits; // bits per sample
|
|
unsigned chCnt; // count of audio file channels
|
|
double srate; // audio file sample rate in samples per second
|
|
unsigned frameCnt; // total number of sample frames in the audio file
|
|
unsigned flags; // informational flags
|
|
unsigned markerCnt; // count of markers in markerArray
|
|
marker_t* markerArray; // array of markers
|
|
bext_t bextRecd; // only used with Broadcast WAV files
|
|
} info_t;
|
|
|
|
|
|
// The file path for fn is internally expanded if it begins with a '~' or '..'.
|
|
rc_t open( handle_t& h, const char* fn, info_t* info );
|
|
|
|
// Set bits to 0 to write the file in IEEE float format.
|
|
// The file path for fn is internally expanded if it begins with a '~' or '..'.
|
|
rc_t create( handle_t& h, const char* fn, double srate, unsigned bits, unsigned chN );
|
|
|
|
rc_t close( handle_t& h );
|
|
|
|
// Return true if the handle is open.
|
|
bool isOpen( handle_t h );
|
|
|
|
// Return true if the current file position is at the end of the file.
|
|
bool isEOF( handle_t h );
|
|
|
|
// Return the current file position as a frame index.
|
|
unsigned tell( handle_t h );
|
|
|
|
// Set the current file position as an offset from the first frame.
|
|
rc_t seek( handle_t h, unsigned frmIdx );
|
|
|
|
// Sample Reading Functions.
|
|
//
|
|
// Fill a user suppled buffer with up to frmCnt samples.
|
|
// If less than frmCnt samples are available at the specified audio file location then the unused
|
|
// buffer space is set to zero. Check *actualFrmCntPtr for the count of samples actually available
|
|
// in the return buffer. Functions which do not include a begFrmIdx argument begin reading from
|
|
// the current file location (see seek()). The buf argument is always a pointer to an
|
|
// array of pointers of length chCnt. Each channel buffer specified in buf[] must contain at least
|
|
// frmCnt samples.
|
|
//
|
|
//
|
|
// h An audio file handle returned from an earlier call to audioFileNew()
|
|
// fn The name of the audio file to read.
|
|
// begFrmIdx The frame index of the first sample to read. Functions that do not use this parameter begin reading at the current file location (See tell()).
|
|
// frmCnt The number of samples allocated in buf.
|
|
// chIdx The index of the first channel to read.
|
|
// chCnt The count of channels to read.
|
|
// buf An array containing chCnt pointers to arrays of frmCnt samples.
|
|
// actualFrmCntPtr The number of frames actually written to the return buffer (ignored if NULL)
|
|
|
|
rc_t readInt( handle_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, int** buf, unsigned* actualFrmCntPtr );
|
|
rc_t readFloat( handle_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr );
|
|
rc_t readDouble( handle_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr );
|
|
|
|
rc_t getInt( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, int** buf, unsigned* actualFrmCntPtr, info_t* afInfoPtr);
|
|
rc_t getFloat( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr, info_t* afInfoPtr);
|
|
rc_t getDouble( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr, info_t* afInfoPtr);
|
|
|
|
// Sum the returned samples into the output buffer.
|
|
rc_t readSumInt( handle_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, int** buf, unsigned* actualFrmCntPtr );
|
|
rc_t readSumFloat( handle_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr );
|
|
rc_t readSumDouble( handle_t h, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr );
|
|
|
|
rc_t getSumInt( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, int** buf, unsigned* actualFrmCntPtr, info_t* afInfoPtr);
|
|
rc_t getSumFloat( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, float** buf, unsigned* actualFrmCntPtr, info_t* afInfoPtr);
|
|
rc_t getSumDouble( const char* fn, unsigned begFrmIdx, unsigned frmCnt, unsigned chIdx, unsigned chCnt, double** buf, unsigned* actualFrmCntPtr, info_t* afInfoPtr);
|
|
|
|
// Allocate a buffer and read the file into it
|
|
rc_t allocFloatBuf( const char* fn, float**& chBufRef, unsigned& chCntRef, unsigned& frmCntRef, info_t& afInfoPtrRef, unsigned begFrmIdx=0, unsigned frmCnt=0, unsigned chIdx=0, unsigned chCnt=0 );
|
|
rc_t freeFloatBuf( float** floatBufRef, unsigned chCnt );
|
|
|
|
// Sample Writing Functions
|
|
rc_t writeInt( handle_t h, unsigned frmCnt, unsigned chCnt, const int* const* 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, const double* const* bufPtrPtr );
|
|
|
|
// Write a buffer of interleaved floating point samples. Note that no sample format conversion is
|
|
// implemented on this function. The samples are directly written to the current file location.
|
|
// This means that the file must have been 'created()' with 'bits' set to 0 to indicate that the
|
|
// file is using a single precision float sample format. This limitation could easily be removed
|
|
// by adding sample conversion to integer types.
|
|
rc_t writeFloatInterleaved( handle_t h, unsigned frmCnt, unsigned chCnt, const float* bufPtr );
|
|
|
|
// File Writing Functions
|
|
// Set 'bit' to 0 to write the file in IEEE float format.
|
|
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.
|
|
// On error *minPtr, *maxPtr, and *meanPtr are set to -acSample_MAX, cmSample_MAX, and 0 respectively
|
|
rc_t minMaxMean( handle_t h, unsigned chIdx, float* minPtr, float* maxPtr, float* meanPtr );
|
|
rc_t minMaxMeanFn( const char* fn, unsigned chIdx, float* minPtr, float* maxPtr, float* meanPtr );
|
|
|
|
// Return the file name associated with a audio file handle.
|
|
const char* name( handle_t h );
|
|
unsigned channelCount( handle_t h );
|
|
double sampleRate( handle_t h );
|
|
|
|
// Return the info_t record associated with a file.
|
|
rc_t getInfo( const char* fn, info_t* infoPtr );
|
|
|
|
// Print the info_t to a file.
|
|
void printInfo( const info_t* infoPtr, log::handle_t logH );
|
|
|
|
rc_t reportInfo( const char* audioFn );
|
|
|
|
// Print the file header information and frmCnt sample values beginning at frame index frmIdx.
|
|
rc_t report( handle_t h, log::handle_t logH, unsigned frmIdx=0, unsigned frmCnt=kInvalidCnt );
|
|
rc_t reportFn( const char* fn, log::handle_t logH, unsigned frmIdx=0, unsigned frmCnt=kInvalidCnt );
|
|
|
|
// Change the sample rate value in the header. Note that this function does not resample the audio
|
|
// signal it simply changes the value of the sample rate in the header.
|
|
rc_t setSrate( const char* audioFn, unsigned srate );
|
|
|
|
// Testing and example routine for functions in .h.
|
|
// Also see cmProcTest.c readWriteTest()
|
|
rc_t test( const object_t* cfg );
|
|
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|