18 #define CONVERT_16_BIT(unsV, sinV, bigE) \
20 unsV = ((unsV << 8) | (unsV >> 8)); \
21 sinV = unsV & 0x7fff; \
25 #define CONVERT_24_BIT(res, ptr, bigE) \
27 res = (((int) ptr[2]) << 16) \
28 | (((uint32) (uint8) ptr[1]) << 8) \
29 | ((uint32) (uint8) ptr[0]); \
31 res = (((int) ptr[0]) << 16) \
32 | (((uint32) (uint8) ptr[1]) << 8) \
33 | ((uint32) (uint8) ptr[2])
46 mURL = CFURLCreateWithFileSystemPath (NULL,
47 (CFStringCreateWithCString (NULL, tpath.c_str(), kCFStringEncodingMacRoman)),
48 kCFURLPOSIXPathStyle,
false);
68 CFStringGetCString (CFURLGetString(path), theName,
CSL_NAME_LEN, kCFStringEncodingMacRoman);
69 mPath = string(theName);
108 OSStatus err = noErr;
110 UInt32 propertySize, fileSize;
113 mURL = CFURLCreateFromFileSystemRepresentation(NULL,
114 (
const UInt8*) mPath.c_str(), mPath.size(),
false);
116 AudioFileOpenURL(mURL, 0x01, kAudioFileCAFType, &mSoundID);
118 err = AudioFileGetPropertyInfo(mSoundID,
119 kAudioFilePropertyAudioDataPacketCount,
123 printf(
"\nCASoundFile::openForRead: AudioFileGetPropertyInfo Error = %x\nFile: \"%s\"\n\n",
124 (
int) err, mPath.c_str());
127 err = AudioFileGetProperty(mSoundID, kAudioFilePropertyAudioDataPacketCount, &propertySize, &fileSize);
129 printf(
"\nCASoundFile::openForRead: AudioFileGetProperty Error = %x\nFile: \"%s\"\n\n",
130 (
int) err, mPath.c_str());
133 AudioStreamBasicDescription fileFormat;
134 propertySize =
sizeof(AudioStreamBasicDescription);
135 err = AudioFileGetProperty(mSoundID, kAudioFilePropertyDataFormat, &propertySize, &fileFormat);
137 printf(
"\nCASoundFile::openForRead: AudioFileGetProperty2 Error = %x\nFile: \"%s\"\n\n",
138 (
int) err, mPath.c_str());
143 mFrameRate = (unsigned) fileFormat.mSampleRate;
144 mNumChannels = (
unsigned) fileFormat.mChannelsPerFrame;
145 mNumFrames = (unsigned) fileSize;
146 mBigEndian = fileFormat.mFormatFlags & kAudioFormatFlagIsBigEndian;
147 mBytesPerSample = (unsigned) fileFormat.mBitsPerChannel / 8;
148 if (mBytesPerSample == 0) {
149 logMsg(
kLogError,
"Sound file \"%s\" has mBitsPerChannel = 0\n", mPath.c_str());
153 this->initFromSndfile();
162 this->readBufferFromFile(mNumFrames);
163 mCurrentFrame = mStart;
168 unsigned rate,
unsigned bitDepth)
throw (
CException) {
169 logMsg(
"Error: CASoundFile::openForWrite unsupported");
180 OSStatus err = noErr;
184 UInt32 numBytes, fileSize;
191 memset(sampleBufferPtr, 0, numFrames *
sizeof(
sample));
195 fileSize = numFrames;
197 unsigned char * soundBuffer = (
unsigned char *) malloc(numBytes);
209 err = AudioFileReadPackets(
mSoundID,
false, &numBytes, NULL, currentFrame, &fileSize, soundBuffer);
211 printf(
"\nCASoundFile::openForRead: AudioFileReadPackets Error = %x\nFile: \"%s\"\n\n",
212 (
int) err,
mPath.c_str());
215 if (fileSize != numFrames) {
216 printf(
"\nCASoundFile::openForRead: read too few samples, %d instead of %d\n",
217 (
int) fileSize, numFrames);
220 unsigned short * tBfr = (
unsigned short *) soundBuffer;
221 unsigned char * cBfr = soundBuffer;
226 if (myChannels == 1) {
228 if (mBytesPerSample == 2) {
229 sample scale = 1.0f / 32867.0f;
230 for (
unsigned j = 0; j < fileSize; j++) {
233 *sampPtr++ = (
sample) sVal * scale;
235 }
else if (mBytesPerSample == 3) {
237 for (
unsigned j = 0; j < fileSize; j++) {
239 *sampPtr++ = (
sample) iVal * scale;
243 }
else if (myChannels == 2) {
245 sample * sampPtr = sampBuf;
246 if (mBytesPerSample == 2) {
247 sample scale = 1.0f / 32867.0f;
248 for (
unsigned j = 0; j < (fileSize * myChannels); j++) {
251 *sampPtr++ = (
sample) sVal * scale;
253 }
else if (mBytesPerSample == 3) {
255 for (
unsigned j = 0; j < (fileSize * myChannels); j++) {
257 *sampPtr++ = (
sample) iVal * scale;
266 currentFrame += numFrames;
269 if (currentFrame > (
unsigned) mStop) {
270 unsigned numFramesRemaining = currentFrame -
mStop;
271 unsigned numFramesRead = numFrames - numFramesRemaining;
274 while (numFramesRead < numFrames) {
278 currentFrame += numFramesRead;
281 unsigned bytesToClear = numFramesRemaining *
sizeof(
sample);
284 memset(sampleBufferPtr, 0, bytesToClear);
294 if (this->isCached())
295 return mCurrentFrame;
298 mCurrentFrame = position;
301 mCurrentFrame = mCurrentFrame - position;
304 mCurrentFrame = duration() - position;
307 mCurrentFrame = SEEK_CUR;
308 logMsg(
"Error: Invalid position seek flag. Used kPositionCurrent.");
311 return mCurrentFrame;
317 logMsg(
"Error: CASoundFile::writeBuffer unsupported");
324 const char * nam =
path().c_str();
325 if (strlen(nam) > 50)
326 logMsg(
"SndFile \"%s\"\n\t\t%d Hz, %d ch, %5.3f sec %s",
330 logMsg(
"SndFile \"%s\" - %d Hz, %d ch, %5.3f sec %s",
sample * SampleBuffer
1-channel buffer data type, vector of (sample)
void logMsg(const char *format,...)
These are the public logging messages.
SeekPosition
Enumeration for seek flags.
#define kSoundFileFormatAIFF
unsigned mNumFrames
sample frames
AudioFileID mSoundID
the CS audio file ID
static unsigned mFrameRate
default sample rate (tested up to 96000)
AdditiveInstrument.h – Sum-of-sines synthesis instrument class.
void writeBuffer(Buffer &inputBuffer)
write a buffer of data into the file
Interleaver handles copying interleaved sample buffers (like sound files and inter-process sockets) t...
static unsigned maxSndFileFrames()
the max num frames that can be cached
void openForRead(bool load=true)
void initFromSndfile()
read SF header
#define kSoundFileRead
Sound file constants.
unsigned mFrameRate
trigger ignored here
virtual void setToEnd()
set to end position
virtual SampleBuffer buffer(unsigned bufNum)
convenience accessors for sample buffers
CASoundFile(CFURLRef path, bool load=true)
CFURLRef mURL
the full URL of the file
void deinterleave(Buffer &output, SampleBuffer samples, unsigned numFrames, unsigned numChannels)
De-interleave = copy from interleaved SampleBuffer to CSL Buffer object.
bool mIsValid
is my file valid?
bool mBigEndian
flag for endian-ness of sound file (varies byformat)
#define CSL_NAME_LEN
default string length
unsigned mBytesPerSample
the # of bytes per sample
unsigned mCurrentFrame
where I currently am in the buffer
float sample
(could be changed to int, or double)
unsigned mNumChannels
my "expected" number of output channels
virtual void freeBuffer()
free the file cache
void readBufferFromFile(unsigned numFrames)
read a buffer from the file (possibly all of it)
bool mIsLooping
am i looping start-stop?
#define CONVERT_16_BIT(unsV, sinV, bigE)
int mStop
starting/ending frames (or -1 if not used)
SoundFileFormat format()
get format
unsigned seekTo(int position, SeekPosition whence)
seek to some position relative to "whence"
Buffer mWavetable
the stored wave form
void close()
close file seek to some position
Buffer – the multi-channel sample buffer class (passed around between generators and IO guys)...
void dump()
log snd file props < open file and get stats; read it if "load"
void checkBuffer(unsigned numFrames)
allocate buffer lazily
Here's the abstract sound file reader/writer class, a sample player UGen. The concrete subclasses rep...
unsigned channels() const
accessors
float durationInSecs()
number of frames in the sound file
#define CONVERT_24_BIT(res, ptr, bigE)
void openForWrite(SoundFileFormat format=kSoundFileFormatAIFF, unsigned channels=1, unsigned rate=44100, unsigned bitDepth=16)
Open a file for write. Default values are some common format.
Base class of CSL exceptions (written upper-case). Has a string message.