/*============================================================================= CAAudioFileStreamer.cpp $Log: CAAudioFileStreamer.cpp,v $ Revision 1.9 2004/11/18 00:25:34 dwyatt fix GetCurrentFrame so afplay can be told to play portions of a file Revision 1.8 2004/10/25 20:05:07 dwyatt remove printf Revision 1.7 2004/10/15 17:10:34 dwyatt CAAudioFile rewrite to use ExtAudioFile (changeable via compile flag in CAAudioFile.h) Revision 1.6 2004/06/02 20:16:01 bills track changes to CAAudioFile::Wrap Revision 1.5 2004/06/02 20:14:49 bills track changes to CAAudioFile::Wrap Revision 1.4 2004/05/27 19:51:54 dwyatt reinstate SetFile methods which allowed wrapping an existing CAAudioFile Revision 1.3 2004/05/26 00:36:02 dwyatt track change to CABufferQueue; writer/recorder now create their own CAAudioFile's from scratch instead of wrapping the client's [3666988] Revision 1.2 2004/01/31 01:50:38 dwyatt track CAAudioFile changes Revision 1.1 2004/01/14 00:08:09 dwyatt moved from Source/Tests/AudioFileUtility/Utility Revision 1.11 2003/12/04 00:59:02 dwyatt refactoring Revision 1.10 2003/10/15 00:27:30 dwyatt refactor on top of CABufferQueue Revision 1.9 2003/10/09 23:23:13 dwyatt refactor/cleanup to support CAAudioFileRecorder Revision 1.8 2003/09/11 00:47:56 dwyatt maintain a mRunning member so that GetPosition can be accurate when we're stopped Revision 1.7 2003/08/23 04:52:23 dwyatt fix GetCurrentPosition so as not to report EOF until we're really there Revision 1.6 2003/08/04 23:44:41 dwyatt deinterleaved Revision 1.5 2003/07/25 23:29:12 dwyatt use constant strings for operations in CAXException Revision 1.4 2003/07/09 19:12:41 dwyatt multiple I/O buffers, prepare for record Revision 1.3 2003/07/03 18:53:58 dwyatt add missing semicolon Revision 1.2 2003/07/02 21:45:41 dwyatt wasn't toggling between buffers correctly Revision 1.1 2003/06/23 23:07:37 dwyatt initial checkin created Wed Jun 18 2003, Doug Wyatt Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved $NoKeywords: $ =============================================================================*/ #include "CAAudioFileStreamer.h" // ____________________________________________________________________________ void CAAudioFileReader::FileReadBuffer::UpdateAfterRead(SInt64 curFrame, UInt32 nFrames) { //printf("read %ld PCM packets, file packets %qd-%qd\n", nPackets, b->mStartPacket, b->mEndPacket); mEndFrame = nFrames; mEndOfStream = (nFrames == 0); mBufferStartFileFrame = curFrame; } // ____________________________________________________________________________ void CAAudioFileReader::SetFile(const FSRef &inFile) { Stop(); CancelAndDisposeBuffers(); delete mFile; mFile = NULL; mFile = new CAAudioFile; mFile->Open(inFile); const CAStreamBasicDescription &fileFmt = mFile->GetFileDataFormat(); CAStreamBasicDescription iofmt; iofmt.SetCanonical(fileFmt.mChannelsPerFrame, false); // deinterleaved iofmt.mSampleRate = fileFmt.mSampleRate; mFile->SetClientFormat(iofmt, NULL); SetFormat(iofmt); } void CAAudioFileReader::Start() { mErrorCount = 0; mEndOfStream = false; Prime(); mRunning = true; } void CAAudioFileReader::Stop() { mRunning = false; } void CAAudioFileReader::ReadBuffer(FileReadBuffer *b) { b->SetEmpty(); CABufferList *ioMemory = b->GetBufferList(); CABufferList *fileBuffers = GetBufferList(); fileBuffers->SetFrom(ioMemory); UInt32 nFrames = GetBufferSizeFrames(); SInt64 curFrame = mFile->Tell(); mFile->Read(nFrames, &fileBuffers->GetModifiableBufferList()); b->UpdateAfterRead(curFrame, nFrames); } double CAAudioFileReader::GetCurrentPosition() const { return double(GetCurrentFrame()) / double(GetNumberFrames()); #if 0 double nFrames = double(GetNumberFrames()); // +1 to account for leftovers from decoder if (!mRunning) return double(GetCurrentFrame()) / nFrames; if (mEndOfStream) { //printf("EOF\n"); return 1.0; } const FileReadBuffer *b = static_cast(GetCurrentBuffer()); // the buffer from which we're reading UInt32 startFrame, endFrame; b->GetLocation(startFrame, endFrame); //printf("%qd + %ld / %.f\n", b->mBufferStartFileFrame, startFrame, nFrames); return double(b->mBufferStartFileFrame + startFrame) / nFrames; //if (endFrame > 0) { //double frac = (double(startFrame) / double(endFrame)) * double(endPacket - startPacket); //packetIndex += frac; //printf("frames %ld-%ld, packets %qd-%qd, frac %.3f\n", // startFrame, endFrame, startPacket, endPacket, frac); //} //double pos = packetIndex / nPacketsPlus1; //printf("%.3f / %.0f = %.3f\n", packetIndex, nPacketsPlus1, pos); //return pos; //return double(GetCurrentFrame()) / nFrames; #endif } SInt64 CAAudioFileReader::GetCurrentFrame() const { if (!mRunning) return mFile->Tell(); if (mEndOfStream) return GetNumberFrames(); const FileReadBuffer *b = static_cast(GetCurrentBuffer()); // the buffer from which we're reading UInt32 startFrame, endFrame; b->GetLocation(startFrame, endFrame); //printf("%qd + %ld / %.f\n", b->mBufferStartFileFrame, startFrame, nFrames); return b->mBufferStartFileFrame + startFrame; } void CAAudioFileReader::SetCurrentPosition(double loc) { bool wasRunning = IsRunning(); if (wasRunning) Stop(); SInt64 frameNumber = SInt64(loc * GetFile().GetNumberFrames() + 0.5); try { GetFile().Seek(frameNumber); } catch (...) { } if (wasRunning) Start(); } // ____________________________________________________________________________ void CAAudioFileWriter::SetFile(AudioFileID fileID) { Stop(); CancelAndDisposeBuffers(); delete mFile; mFile = NULL; mFile = new CAAudioFile; mFile->Wrap(fileID, true); const CAStreamBasicDescription &fileFmt = mFile->GetFileDataFormat(); CAStreamBasicDescription iofmt; iofmt.SetCanonical(fileFmt.mChannelsPerFrame, false); // deinterleaved iofmt.mSampleRate = fileFmt.mSampleRate; mFile->SetClientFormat(iofmt, NULL); SetFormat(iofmt); } void CAAudioFileWriter::SetFile(const FSRef &parentDir, CFStringRef filename, AudioFileTypeID filetype, const CAStreamBasicDescription &dataFormat, const CAAudioChannelLayout *layout) { Stop(); CancelAndDisposeBuffers(); delete mFile; mFile = NULL; mFile = new CAAudioFile; mFile->CreateNew(parentDir, filename, filetype, dataFormat, layout ? &layout->Layout() : NULL); const CAStreamBasicDescription &fileFmt = mFile->GetFileDataFormat(); CAStreamBasicDescription iofmt; iofmt.SetCanonical(fileFmt.mChannelsPerFrame, false); // deinterleaved iofmt.mSampleRate = fileFmt.mSampleRate; mFile->SetClientFormat(iofmt, NULL); SetFormat(iofmt); } void CAAudioFileWriter::Start() { mErrorCount = 0; mRunning = true; } void CAAudioFileWriter::Stop() { Flush(); mRunning = false; } void CAAudioFileWriter::WriteBuffer(CABufferQueue::Buffer *b) { CABufferList *ioMemory = b->GetBufferList(); CABufferList *fileBuffers = GetBufferList(); UInt32 nFrames = b->FrameCount(); fileBuffers->SetFrom(ioMemory, GetBytesPerFrame() * nFrames); mFile->Write(nFrames, &fileBuffers->GetModifiableBufferList()); b->SetEmpty(); }