static void AQTestBufferCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer) { AQTestInfo * myInfo = (AQTestInfo *)inUserData; if (myInfo->mDone) return; UInt32 numBytes; UInt32 nPackets = myInfo->mNumPacketsToRead; OSStatus result = AudioFileReadPackets(myInfo->mAudioFile, false, &numBytes, myInfo->mPacketDescs, myInfo->mCurrentPacket, &nPackets, inCompleteAQBuffer->mAudioData); if (result) { DebugMessageN1 ("Error reading from file: %d\n", (int)result); exit(1); } if (nPackets > 0) { inCompleteAQBuffer->mAudioDataByteSize = numBytes; AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, (myInfo->mPacketDescs ? nPackets : 0), myInfo->mPacketDescs); myInfo->mCurrentPacket += nPackets; } else { result = AudioQueueStop(myInfo->mQueue, false); if (result) { DebugMessageN1 ("AudioQueueStop(false) failed: %d", (int)result); exit(1); } // reading nPackets == 0 is our EOF condition myInfo->mDone = true; } }
static void MyAQOutputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer) { MyPlayer *aqp = (MyPlayer*)inUserData; if (aqp->isDone) return; // read audio data from file into supplied buffer UInt32 numBytes; UInt32 nPackets = aqp->numPacketsToRead; CheckError(AudioFileReadPackets(aqp->playbackFile, false, &numBytes, aqp->packetDescs, aqp->packetPosition, &nPackets, inCompleteAQBuffer->mAudioData), "AudioFileReadPackets failed"); // enqueue buffer into the Audio Queue // if nPackets == 0 it means we are EOF (all data has been read from file) if (nPackets > 0) { inCompleteAQBuffer->mAudioDataByteSize = numBytes; AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, (aqp->packetDescs ? nPackets : 0), aqp->packetDescs); aqp->packetPosition += nPackets; } else { CheckError(AudioQueueStop(inAQ, false), "AudioQueueStop failed"); aqp->isDone = true; } }
static void HandleOutputBuffer (void *aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) { AQPlayerState *pAqData = (AQPlayerState *) aqData; if (pAqData->mIsRunning == 0) return; UInt32 numBytesReadFromFile; UInt32 numPackets = pAqData->mNumPacketsToRead; AudioFileReadPackets (pAqData->mAudioFile, false, &numBytesReadFromFile, pAqData->mPacketDescs, pAqData->mCurrentPacket, &numPackets, inBuffer->mAudioData); if (numPackets > 0) { inBuffer->mAudioDataByteSize = numBytesReadFromFile; AudioQueueEnqueueBuffer (pAqData->mQueue, inBuffer, (pAqData->mPacketDescs ? numPackets : 0), pAqData->mPacketDescs); pAqData->mCurrentPacket += numPackets; } else { AudioQueueStop (pAqData->mQueue, false); //printf("Play Stopped!\n"); pAqData->mIsRunning = false; } }
void AudioQueueStreamOut::AQBufferCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer) { AudioQueueStreamOut * pThis = (AudioQueueStreamOut *)inUserData; if (pThis->mInfo.mDone) return; if(pThis->mInfo.m_SeekToPacket != -1) { pThis->mInfo.mCurrentPacket = pThis->mInfo.m_SeekToPacket; pThis->mInfo.m_SeekToPacket = -1; } UInt32 numBytes; UInt32 nPackets = pThis->mInfo.mNumPacketsToRead; if ((AudioFileReadPackets(pThis->mInfo.mAudioFile, false, &numBytes, pThis->mInfo.mPacketDescs, pThis->mInfo.mCurrentPacket, &nPackets, inCompleteAQBuffer->mAudioData) == 0) && (nPackets > 0)) { inCompleteAQBuffer->mAudioDataByteSize = numBytes; AudioQueueParameterEvent event; event.mID = kAudioQueueParam_Volume; event.mValue = pThis->m_Volume; AudioQueueEnqueueBufferWithParameters(inAQ, inCompleteAQBuffer, (pThis->mInfo.mPacketDescs ? nPackets : 0), pThis->mInfo.mPacketDescs,0,0,1, &event,NULL,NULL); pThis->mInfo.mCurrentPacket += nPackets; } else { AudioQueueStop(pThis->mInfo.mQueue, false); // reading nPackets == 0 is our EOF condition pThis->mInfo.mDone = true; } }
void HLAudioFile::ReadAudioFrames(SInt64 inOffset, UInt32& ioNumberFrames, void* outData, bool inCache) { ThrowIf(mAudioFileID == 0, CAException(fnOpnErr), "HLAudioFile::ReadAudioFrames: file isn't prepared"); UInt32 theNumberBytesRead = 0; OSStatus theError = AudioFileReadPackets(mAudioFileID, inCache, &theNumberBytesRead, NULL, inOffset, &ioNumberFrames, outData); ThrowIfError(theError, CAException(theError), "HLAudioFile::ReadAudioFrames: couldn't read the data"); }
static void AQTestBufferCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer) { AQTestInfo * myInfo = (AQTestInfo *)inUserData; if (myInfo->mDone) return; UInt32 numBytes; UInt32 nPackets = myInfo->mNumPacketsToRead; OSStatus result = AudioFileReadPackets(myInfo->mAudioFile, // The audio file from which packets of audio data are to be read. false, // Set to true to cache the data. Otherwise, set to false. &numBytes, // On output, a pointer to the number of bytes actually returned. myInfo->mPacketDescs, // A pointer to an array of packet descriptions that have been allocated. myInfo->mCurrentPacket, // The packet index of the first packet you want to be returned. &nPackets, // On input, a pointer to the number of packets to read. On output, the number of packets actually read. inCompleteAQBuffer->mAudioData); // A pointer to user-allocated memory. if (result) { DebugMessageN1 ("Error reading from file: %d\n", (int)result); exit(1); } // we have some data if (nPackets > 0) { inCompleteAQBuffer->mAudioDataByteSize = numBytes; result = AudioQueueEnqueueBuffer(inAQ, // The audio queue that owns the audio queue buffer. inCompleteAQBuffer, // The audio queue buffer to add to the buffer queue. (myInfo->mPacketDescs ? nPackets : 0), // The number of packets of audio data in the inBuffer parameter. See Docs. myInfo->mPacketDescs); // An array of packet descriptions. Or NULL. See Docs. if (result) { DebugMessageN1 ("Error enqueuing buffer: %d\n", (int)result); exit(1); } myInfo->mCurrentPacket += nPackets; } else { // **** This ensures that we flush the queue when done -- ensures you get all the data out **** if (!myInfo->mFlushed) { result = AudioQueueFlush(myInfo->mQueue); if (result) { DebugMessageN1("AudioQueueFlush failed: %d", (int)result); exit(1); } myInfo->mFlushed = true; } result = AudioQueueStop(myInfo->mQueue, false); if (result) { DebugMessageN1("AudioQueueStop(false) failed: %d", (int)result); exit(1); } // reading nPackets == 0 is our EOF condition myInfo->mDone = true; } }
void LoaderSourceFile::dataInputCallback( Loader* aLoader, uint32_t *ioNumberDataPackets, BufferList *ioData, AudioStreamPacketDescription * packetDescriptions ) { LoaderSourceFile * theLoader = dynamic_cast<LoaderSourceFile *>( aLoader ); SourceFile * theSource = theLoader->mSource; OSStatus err = AudioFileReadPackets( theSource->mFileRef.get(), false, (UInt32 *)&(ioData->mBuffers[0].mDataByteSize), packetDescriptions, theLoader->mPacketOffset, (UInt32 *)ioNumberDataPackets, ioData->mBuffers[0].mData ); if( err ) { //throw ?? } theLoader->mPacketOffset += *ioNumberDataPackets; }
void AudioFile::load() { OSStatus err = noErr; uint32_t bytesReturned = 0; uint32_t packets = mPacketCount; mData = malloc( mByteCount ); memset( mData, 0, mByteCount ); err = AudioFileReadPackets( mNativeFileRef, false, (UInt32 *)&bytesReturned, NULL, 0, (UInt32 *)&packets, mData ); if( err ) { std::cout << "Error loading audio data" << std::endl; } }
void AudioFile::read(Float32 *data, UInt64 *cursor, UInt32 *numFrames) { AudioFramePacketTranslation t; UInt32 size = sizeof(AudioFramePacketTranslation); t.mFrame = *cursor; AudioFileGetProperty(mAudioFileID, kAudioFilePropertyFrameToPacket, &size, &t); *mCursor = t.mPacket; AudioFramePacketTranslation t2; t2.mFrame = *numFrames; AudioFileGetProperty(mAudioFileID, kAudioFilePropertyFrameToPacket, &size, &t2); UInt32 numPacketsToRead = t2.mPacket ? t2.mPacket : 1; AudioBytePacketTranslation t3; t3.mPacket = numPacketsToRead; size = sizeof(AudioBytePacketTranslation); AudioFileGetProperty(mAudioFileID, kAudioFilePropertyPacketToByte, &size, &t3); if (mConverterBuffer) free(mConverterBuffer); mConverterBuffer = (char*)malloc(t3.mByte); mNumPacketsToRead = numPacketsToRead; UInt32 outNumBytes; checkError(AudioFileReadPackets(mAudioFileID, false, &outNumBytes, mPacketDescs, *mCursor, &numPacketsToRead, mConverterBuffer), "AudioFileReadPackets"); mConvertByteSize = outNumBytes; UInt32 numFramesToConvert = t.mFrameOffsetInPacket + *numFrames; bool interleaved = true; interleaved = !(mClientFormat.mFormatFlags & kAudioFormatFlagIsNonInterleaved); AudioBufferList* tmpbuf = AudioSourceNode::createAudioBufferList(2, interleaved, numFramesToConvert, sizeof(Float32)); checkError(AudioConverterFillComplexBuffer(mAudioConverterRef, encoderProc, this, &numFramesToConvert, tmpbuf, NULL), "AudioConverterFillComplexBuffer"); if (interleaved) { Float32* sample = (Float32*)tmpbuf->mBuffers[0].mData; memcpy(data, &sample[t.mFrameOffsetInPacket], numFramesToConvert * sizeof(Float32) * mClientFormat.mChannelsPerFrame); } AudioSourceNode::deleteAudioBufferList(tmpbuf); if (numFramesToConvert == 0) { AudioConverterReset(mAudioConverterRef); } *numFrames = numFramesToConvert; }
static void HandleOutputBuffer ( void *aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer ) { // std::cout << "cb" << std::endl; OSStatus status; AQPlayerState *pAqData = (AQPlayerState *) aqData; // 1 if (pAqData->mIsRunning == 0) return; // 2 UInt32 numBytesReadFromFile; // 3 UInt32 numPackets = pAqData->mNumPacketsToRead; // 4 status = AudioFileReadPackets ( pAqData->mAudioFile, false, &numBytesReadFromFile, pAqData->mPacketDescs, pAqData->mCurrentPacket, &numPackets, inBuffer->mAudioData ); // checkStatus(status); if (numPackets > 0) { // 5 inBuffer->mAudioDataByteSize = numBytesReadFromFile; // 6 status = AudioQueueEnqueueBuffer ( pAqData->mQueue, inBuffer, (pAqData->mPacketDescs ? numPackets : 0), pAqData->mPacketDescs ); // checkStatus(status); pAqData->mCurrentPacket += numPackets; // 7 } else { status = AudioQueueStop ( pAqData->mQueue, false ); // checkStatus(status); pAqData->mIsRunning = false; } }
void AudioFile::getData( void ** aBuffer, uint32_t * size, AudioStreamPacketDescription * outPacketDescriptions, uint32_t startPacket, uint32_t packetCount, bool looping ) { if( startPacket < mPacketCount ) { if( ( startPacket + packetCount ) > mPacketCount ) { packetCount = mPacketCount - startPacket; } } else { packetCount = 0; } UInt32 bytesToCopy = packetCount * mMaxPacketSize; if( packetCount ) { *aBuffer = (void *) calloc( 1, bytesToCopy ); AudioFileReadPackets( mNativeFileRef, false, &bytesToCopy, outPacketDescriptions, (SInt64)startPacket, (UInt32 *)&packetCount, *aBuffer ); *size = bytesToCopy; } else { *size = 0; aBuffer = NULL; } }
UInt32 music_obj<audio_queue_driver>::read_packets(AudioQueueBufferRef buffer) { UInt32 num_bytes, num_packets; num_packets = num_packets_to_read_; AudioFileReadPackets(audio_file_, false, &num_bytes, packet_descriptions_, packet_index_, &num_packets, buffer->mAudioData); if (num_packets > 0) { buffer->mAudioDataByteSize = num_bytes; AudioQueueEnqueueBuffer(queue_, buffer, (packet_descriptions_ ? num_packets : 0), packet_descriptions_); packet_index_ += num_packets; if(stop_packet_index_ != 0 && packet_index_ >= stop_packet_index_) { if(loop_) packet_index_ = start_packet_index_; else return 0; } } return num_packets; }
void AudioFileReaderThread::DoConnect () { if (!mIsEngaged) { mFinishedReadingData = false; mNumTimesAskedSinceFinished = -1; mLockUnsuccessful = false; UInt32 dataChunkSize = 0; mCurrentPacketCountInBuffer = mChunkSizeInPackets; #if LOG_DATA_FLOW fprintf(stdout, "***** DoConnect - AFReadPackets from (pkts/offset) %ld/%qd\n", mCurrentPacketCountInBuffer, mReadPacketPosition); #endif OSStatus result = AudioFileReadPackets ( mAudioFileID, false, &dataChunkSize, mPacketDescriptions, mReadPacketPosition, &mCurrentPacketCountInBuffer, mFileBuffer); THROW_RESULT("AudioFileReadPackets") mCurrentByteCountInBuffer = dataChunkSize; mReadPacketPosition = mCurrentPacketCountInBuffer; mWriteToFirstBuffer = false; mReadFromFirstBuffer = true; sReaderThread.AddReader(); mIsEngaged = true; } else throw static_cast<OSStatus>(-1); //thread has already been started }
void AudioQueueOutput( void *userData, AudioQueueRef queue, AudioQueueBufferRef buffer ) { OSStatus result; State *state = (State *)userData; buffer->mAudioDataByteSize = state->audioBufferSize; buffer->mPacketDescriptionCount = PACKETS_PER_BUFFER; result = AudioFileReadPackets( state->audioFile, false, &buffer->mAudioDataByteSize, buffer->mPacketDescriptions, state->nextPacketIndex, &buffer->mPacketDescriptionCount, buffer->mAudioData ); if (result) { fprintf(stderr, "Error reading packets from file: %d\n", result); } state->nextPacketIndex += buffer->mPacketDescriptionCount; AudioQueueEnqueueBuffer( queue, buffer, 0, NULL ); if (buffer->mPacketDescriptionCount < PACKETS_PER_BUFFER) { AudioQueueStop(queue, false); } }
// Input data proc callback static OSStatus EncoderDataProc(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void *inUserData) { AudioFileIOPtr afio = (AudioFileIOPtr)inUserData; OSStatus error; // figure out how much to read UInt32 maxPackets = afio->srcBufferSize / afio->srcSizePerPacket; if (*ioNumberDataPackets > maxPackets) *ioNumberDataPackets = maxPackets; // read from the file UInt32 outNumBytes; error = AudioFileReadPackets(afio->srcFileID, false, &outNumBytes, afio->packetDescriptions, afio->srcFilePos, ioNumberDataPackets, afio->srcBuffer); if (eofErr == error) error = noErr; if (error) { printf ("Input Proc Read error: %ld (%4.4s)\n", error, (char*)&error); return error; } //printf("Input Proc: Read %lu packets, at position %lld size %lu\n", *ioNumberDataPackets, afio->srcFilePos, outNumBytes); // advance input file packet position afio->srcFilePos += *ioNumberDataPackets; // put the data pointer into the buffer list ioData->mBuffers[0].mData = afio->srcBuffer; ioData->mBuffers[0].mDataByteSize = outNumBytes; ioData->mBuffers[0].mNumberChannels = afio->srcFormat.mChannelsPerFrame; // don't forget the packet descriptions if required if (outDataPacketDescription) { if (afio->packetDescriptions) { *outDataPacketDescription = afio->packetDescriptions; } else { *outDataPacketDescription = NULL; } } return error; }
// _______________________________________________________________________________________ // OSStatus CAAudioFile::ReadInputProc( AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData) { CAAudioFile *This = static_cast<CAAudioFile *>(inUserData); #if 0 SInt64 remainingPacketsInFile = This->mNumberPackets - This->mPacketMark; if (remainingPacketsInFile <= 0) { *ioNumberDataPackets = 0; ioData->mBuffers[0].mDataByteSize = 0; if (outDataPacketDescription) *outDataPacketDescription = This->mPacketDescs; #if VERBOSE_IO printf("CAAudioFile::ReadInputProc: EOF\n"); #endif return noErr; // not eofErr; EOF is signified by 0 packets/0 bytes } #endif // determine how much to read AudioBufferList *readBuffer; UInt32 readPackets; if (inAudioConverter != NULL) { // getting called from converter, need to use our I/O buffer readBuffer = &This->mIOBufferList; readPackets = This->mIOBufferSizePackets; } else { // getting called directly from ReadPackets, use supplied buffer if (This->mFileMaxPacketSize == 0) return kExtAudioFileError_MaxPacketSizeUnknown; readBuffer = ioData; readPackets = std::min(*ioNumberDataPackets, readBuffer->mBuffers[0].mDataByteSize / This->mFileMaxPacketSize); // don't attempt to read more packets than will fit in the buffer } // don't try to read past EOF // if (readPackets > remainingPacketsInFile) // readPackets = remainingPacketsInFile; // don't read more packets than necessary to produce the requested amount of converted data if (readPackets > This->mMaxPacketsToRead) { #if VERBOSE_IO printf("CAAudioFile::ReadInputProc: limiting read to %ld packets (from %ld)\n", This->mMaxPacketsToRead, readPackets); #endif readPackets = This->mMaxPacketsToRead; } // read UInt32 bytesRead; OSStatus err; StartTiming(This, read); StartTiming(This, readinconv); err = AudioFileReadPackets(This->mAudioFile, This->mUseCache, &bytesRead, This->mPacketDescs, This->mPacketMark, &readPackets, readBuffer->mBuffers[0].mData); #if CAAUDIOFILE_PROFILE if (This->mInConverter) ElapsedTime(This, readinconv, This->mTicksInReadInConverter); #endif ElapsedTime(This, read, This->mTicksInIO); if (err) { DebugMessageN1("Error %ld from AudioFileReadPackets!!!\n", err); return err; } #if VERBOSE_IO printf("CAAudioFile::ReadInputProc: read %ld packets (%qd-%qd), %ld bytes, err %ld\n", readPackets, This->mPacketMark, This->mPacketMark + readPackets, bytesRead, err); #if VERBOSE_IO >= 2 if (This->mPacketDescs) { for (UInt32 i = 0; i < readPackets; ++i) { printf(" read packet %qd : offset %qd, length %ld\n", This->mPacketMark + i, This->mPacketDescs[i].mStartOffset, This->mPacketDescs[i].mDataByteSize); } } printf(" read buffer:"); CAShowAudioBufferList(readBuffer, 0, 4); #endif #endif if (readPackets == 0) { *ioNumberDataPackets = 0; ioData->mBuffers[0].mDataByteSize = 0; return noErr; } if (outDataPacketDescription) *outDataPacketDescription = This->mPacketDescs; ioData->mBuffers[0].mDataByteSize = bytesRead; ioData->mBuffers[0].mData = readBuffer->mBuffers[0].mData; This->mPacketMark += readPackets; if (This->mClientDataFormat.mFramesPerPacket != 1) { // for PCM client formats we update in Read // but for non-PCM client format (weird case) we must update here/now if (This->mFileDataFormat.mFramesPerPacket > 0) This->mFrameMark += readPackets * This->mFileDataFormat.mFramesPerPacket; else { for (UInt32 i = 0; i < readPackets; ++i) This->mFrameMark += This->mPacketDescs[i].mVariableFramesInPacket; } } *ioNumberDataPackets = readPackets; return noErr; }
void music_obj<audio_queue_driver>::calculate_seek(float start, float end) { bool want_start = start != 0.0f; bool want_end = end != 0.0f; total_time_ = 0.0f; // variable bitrate requires calculations per packet if (data_format_.mBytesPerPacket == 0 || data_format_.mFramesPerPacket == 0) { UInt32 num_packets = num_packets_to_read_; UInt32 num_bytes; void* dummy_data = malloc(max_packet_size_*num_packets); // read all file while(true) { AudioFileReadPackets(audio_file_, false, &num_bytes, packet_descriptions_, packet_index_, &num_packets, dummy_data); if (num_packets > 0) { for(int i=0; i<num_packets; ++i) { if(packet_descriptions_[i].mVariableFramesInPacket == 0) { total_time_ += data_format_.mFramesPerPacket / data_format_.mSampleRate; } else { total_time_ += packet_descriptions_[i].mVariableFramesInPacket / data_format_.mSampleRate; } if(want_start && total_time_ >= start) { start_packet_index_ = packet_index_; want_start = false; } if(want_end && total_time_ >= end) { stop_packet_index_ = packet_index_; want_end = false; } packet_index_ += 1; } } else { break; // done } } free(dummy_data); } else { UInt32 size = sizeof(UInt64); UInt64 total_packets; OSStatus err = AudioFileGetProperty(audio_file_, kAudioFilePropertyAudioDataPacketCount, &size, &total_packets); if(err != noErr) { throw sys_exception("audio_queue: Can't get total packet count from CBR audio file. " + boost::lexical_cast<std::string>(err)); } float packet_time = data_format_.mFramesPerPacket / data_format_.mSampleRate; if(want_start) { start_packet_index_ = start/packet_time; } if(want_end) { stop_packet_index_ = end/packet_time; } total_time_ = total_packets*packet_time; } LOG("Total length of track: %f", total_time_); }
void FileReaderThread::ReadNextChunk () { OSStatus result; UInt32 dataChunkSize; UInt32 dataChunkSizeInPackets; AudioStreamPacketDescription *packetDescriptions = NULL; FileThreadVariables* theItem = 0; for (;;) { { // this is a scoped based lock CAGuard::Locker fileReadLock (mGuard); if (mThreadShouldDie) return; while (mFileData.empty()) { fileReadLock.Wait(); } // kill thread if (mThreadShouldDie) return; theItem = mFileData[0]; mFileData.erase (mFileData.begin()); } packetDescriptions = theItem->mPacketDescriptions; if (!theItem->mWriteToFirstBuffer) packetDescriptions += theItem->mChunkSizeInPackets; if ((theItem->mPacketCount - theItem->mReadPacketPosition) < theItem->mChunkSizeInPackets) { dataChunkSizeInPackets = theItem->mPacketCount - theItem->mReadPacketPosition; if (!theItem->IsLooping()) { theItem->mFinishedReadingData = true; } } else dataChunkSizeInPackets = theItem->mChunkSizeInPackets; // this is the exit condition for the thread if (dataChunkSizeInPackets == 0 && !theItem->IsLooping()) { theItem->mFinishedReadingData = true; continue; } // construct pointer char* writePtr = const_cast<char*>(theItem->GetFileBuffer() + (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSizeInPackets * theItem->mMaxPacketSize)); #if LOG_DATA_FLOW fprintf(stdout, "***** ReadNextChunk(1) - AFReadPackets (pkts/offset) = %ld/%qd\n", dataChunkSizeInPackets, theItem->mReadPacketPosition); #endif result = AudioFileReadPackets (theItem->GetFileID(), false, &dataChunkSize, packetDescriptions, theItem->mReadPacketPosition, &dataChunkSizeInPackets, writePtr); if (result) { theItem->GetParent().DoNotification(result); continue; } theItem->mCurrentPacketCountInBuffer = dataChunkSizeInPackets; theItem->mCurrentByteCountInBuffer = dataChunkSize; if (dataChunkSizeInPackets != theItem->mChunkSizeInPackets) { writePtr += dataChunkSize; packetDescriptions += dataChunkSizeInPackets; if (theItem->IsLooping()) { packetDescriptions = theItem->mPacketDescriptions + dataChunkSizeInPackets; dataChunkSizeInPackets = theItem->mChunkSizeInPackets - dataChunkSizeInPackets; theItem->mReadPacketPosition = 0; #if LOG_DATA_FLOW fprintf(stdout, "***** ReadNextChunk(2) - AFReadPackets (pkts/offset) = %ld/%qd\n", dataChunkSizeInPackets, theItem->mReadPacketPosition); #endif result = AudioFileReadPackets (theItem->GetFileID(), false, &dataChunkSize, packetDescriptions, theItem->mReadPacketPosition, &dataChunkSizeInPackets, writePtr); if (result) { theItem->GetParent().DoNotification(result); continue; } theItem->mCurrentPacketCountInBuffer += dataChunkSizeInPackets; theItem->mCurrentByteCountInBuffer += dataChunkSize; } else { // can't exit yet.. we still have to pass the partial buffer back memset (writePtr, 0, ((theItem->mChunkSizeInPackets - dataChunkSizeInPackets) * theItem->mMaxPacketSize)); } } theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer; // switch buffers theItem->mReadPacketPosition += dataChunkSizeInPackets; // increment count } }
sfx_obj<audio_queue_driver>::sfx_obj(const boost::shared_ptr<ifdstream>& ifd, bool loop, float pitch, float volume) : ifd_(ifd) , volume_(volume) { OSStatus res = AudioFileOpenWithCallbacks(this, &sfx_obj::af_read_cb, &sfx_obj::af_write_cb, &sfx_obj::af_get_size_cb, &sfx_obj::af_set_size_cb, kAudioFileCAFType, &audio_file_); if(res) { throw sys_exception("audio_queue_driver: couldn't open SFX file in liverpool fs. AudioFileOpen returned " + boost::lexical_cast<std::string>(res)); } UInt32 size = sizeof(data_format_); AudioFileGetProperty(audio_file_, kAudioFilePropertyDataFormat, &size, &data_format_); if (res != 0) { throw sys_exception("audio_queue_driver: couldn't load SFX file from liverpool fs. AudioFileReadBytes returned " + boost::lexical_cast<std::string>(res)); } alGenBuffers(NUM_BUFFERS, buffers_); alGenSources(1, &source_); alSource3f(source_, AL_POSITION, 0.0, 0.0, 0.0); alSource3f(source_, AL_VELOCITY, 0.0, 0.0, 0.0); alSource3f(source_, AL_DIRECTION, 0.0, 0.0, 0.0); alSourcef(source_, AL_PITCH, pitch); alSourcef(source_, AL_GAIN, volume_); alSourcei(source_, AL_LOOPING, loop?AL_TRUE:AL_FALSE); alSourcef(source_, AL_ROLLOFF_FACTOR, 0.0); alSourcei(source_, AL_SOURCE_RELATIVE, AL_TRUE); if (data_format_.mBytesPerPacket == 0 || data_format_.mFramesPerPacket == 0) { LOG("Variable bitrate SFX"); size = sizeof(max_packet_size_); AudioFileGetProperty(audio_file_, kAudioFilePropertyPacketSizeUpperBound, &size, &max_packet_size_); if (max_packet_size_ > BUFFER_SIZE_BYTES) { max_packet_size_ = BUFFER_SIZE_BYTES; } num_packets_to_read_ = BUFFER_SIZE_BYTES / max_packet_size_; } else { LOG("Constant bitrate SFX"); num_packets_to_read_ = BUFFER_SIZE_BYTES / data_format_.mBytesPerPacket; } UInt32 offset = 0; std::vector<unsigned char> dat; for( int i=0; i<NUM_BUFFERS; ++i) { UInt32 packets = num_packets_to_read_; dat.resize(BUFFER_SIZE_BYTES); res = AudioFileReadPackets (audio_file_, false, &size, NULL, offset, &packets, &dat.at(0)); if(res != noErr) { throw sys_exception("AudioFileReadPackets returned error: " + boost::lexical_cast<std::string>(res)); } if (size == 0) { LOG("All buffered into %d buffers total.", i+1); break; // done } dat.resize(size); LOG("Read %d bytes", size); LOG("Buffering data.. size is %d", dat.size()); alBufferData(buffers_[i], AL_FORMAT_STEREO16, &dat.at(0), dat.size(), 44100); alSourcei(source_, AL_BUFFER, buffers_[i]); offset += packets; } AudioFileClose(audio_file_); }
OSStatus MyAudioConverterCallback(AudioConverterRef inAudioConverter, UInt32 *ioDataPacketCount, AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void *inUserData) { MyAudioConverterSettings *audioConverterSettings = (MyAudioConverterSettings *)inUserData; // initialize in case of failure ioData->mBuffers[0].mData = NULL; ioData->mBuffers[0].mDataByteSize = 0; // if there are not enough packets to satisfy request, then read what's left if (audioConverterSettings->inputFilePacketIndex + *ioDataPacketCount > audioConverterSettings->inputFilePacketCount) *ioDataPacketCount = audioConverterSettings->inputFilePacketCount - audioConverterSettings->inputFilePacketIndex; if(*ioDataPacketCount == 0) return noErr; if (audioConverterSettings->sourceBuffer != NULL) { free(audioConverterSettings->sourceBuffer); audioConverterSettings->sourceBuffer = NULL; } audioConverterSettings->sourceBuffer = (void *)calloc(1, *ioDataPacketCount * audioConverterSettings->inputFilePacketMaxSize); UInt32 outByteCount = 0; OSStatus result = AudioFileReadPackets(audioConverterSettings->inputFile, true, &outByteCount, audioConverterSettings->inputFilePacketDescriptions, audioConverterSettings->inputFilePacketIndex, ioDataPacketCount, audioConverterSettings->sourceBuffer); // it's not an error if we just read the remainder of the file #ifdef MAC_OS_X_VERSION_10_7 if (result == kAudioFileEndOfFileError && *ioDataPacketCount) result = noErr; #else if (result == eofErr && *ioDataPacketCount) result = noErr; #endif else if (result != noErr) return result; audioConverterSettings->inputFilePacketIndex += *ioDataPacketCount; // KEVIN: in "// initialize in case of failure", we assumed there was only 1 // buffer (since we set it up ourselves in Convert()). so why be careful to // iterate over potentially multiple buffers here? /* UInt32 bufferIndex; for (bufferIndex = 0; bufferIndex < ioData->mNumberBuffers; bufferIndex++) { ioData->mBuffers[bufferIndex].mData = audioConverterSettings->sourceBuffer; ioData->mBuffers[bufferIndex].mDataByteSize = outByteCount; } */ // chris' hacky asssume-one-buffer equivalent ioData->mBuffers[0].mData = audioConverterSettings->sourceBuffer; ioData->mBuffers[0].mDataByteSize = outByteCount; if (outDataPacketDescription) *outDataPacketDescription = audioConverterSettings->inputFilePacketDescriptions; return result; }
static void QueueCallback( void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inCompleteAQBuffer) { // dispose of the buffer if no longer in use OSStatus result = noErr; BackgroundTrackMgr *THIS = (BackgroundTrackMgr*)inUserData; if (DisposeBuffer(inAQ, THIS->mBuffersToDispose, inCompleteAQBuffer)) return; UInt32 nPackets = 0; // loop the current buffer if the following: // 1. file was loaded into the buffer previously // 2. only one file in the queue // 3. we have not been told to stop at playlist completion if ((CurFileInfo->mFileDataInQueue) && (THIS->mBGFileInfo.size() == 1) && (!THIS->mStopAtEnd)) nPackets = THIS->GetNumPacketsToRead(CurFileInfo); else { UInt32 numBytes; while (nPackets == 0) { // if loadAtOnce, get all packets in the file, otherwise ~.5 seconds of data nPackets = THIS->GetNumPacketsToRead(CurFileInfo); result = AudioFileReadPackets(CurFileInfo->mAFID, false, &numBytes, THIS->mPacketDescs, THIS->mCurrentPacket, &nPackets, inCompleteAQBuffer->mAudioData); AssertNoError("Error reading file data", end); inCompleteAQBuffer->mAudioDataByteSize = numBytes; if (nPackets == 0) // no packets were read, this file has ended. { if (CurFileInfo->mLoadAtOnce) CurFileInfo->mFileDataInQueue = true; THIS->mCurrentPacket = 0; UInt32 theNextFileIndex = (THIS->mCurrentFileIndex < THIS->mBGFileInfo.size()-1) ? THIS->mCurrentFileIndex+1 : 0; // we have gone through the playlist. if mStopAtEnd, stop the queue here if (theNextFileIndex == 0 && THIS->mStopAtEnd) { result = AudioQueueStop(inAQ, false); AssertNoError("Error stopping queue", end); return; } SInt8 theQueueState = GetQueueStateForNextBuffer(CurFileInfo, THIS->mBGFileInfo[theNextFileIndex]); if (theNextFileIndex != THIS->mCurrentFileIndex) { // if were are not looping the same file. Close the old one and open the new result = AudioFileClose(CurFileInfo->mAFID); AssertNoError("Error closing file", end); THIS->mCurrentFileIndex = theNextFileIndex; result = LoadFileDataInfo(CurFileInfo->mFilePath, CurFileInfo->mAFID, CurFileInfo->mFileFormat, CurFileInfo->mFileDataSize); AssertNoError("Error opening file", end); } switch (theQueueState) { // if we need to resize the buffer, set the buffer's audio data size to the new file's size // we will also need to get the new file cookie case kQueueState_ResizeBuffer: inCompleteAQBuffer->mAudioDataByteSize = CurFileInfo->mFileDataSize; // if the data format is the same but we just need a new cookie, attach a new cookie case kQueueState_NeedNewCookie: result = AttachNewCookie(inAQ, CurFileInfo); AssertNoError("Error attaching new file cookie data to queue", end); break; // we can keep the same queue, but not the same buffer(s) case kQueueState_NeedNewBuffers: THIS->mBuffersToDispose.push_back(inCompleteAQBuffer); THIS->SetupBuffers(CurFileInfo); break; // if the data formats are not the same, we need to dispose the current queue and create a new one case kQueueState_NeedNewQueue: THIS->mMakeNewQueueWhenStopped = true; result = AudioQueueStop(inAQ, false); AssertNoError("Error stopping queue", end); return; default: break; } } } } result = AudioQueueEnqueueBuffer(inAQ, inCompleteAQBuffer, (THIS->mPacketDescs ? nPackets : 0), THIS->mPacketDescs); AssertNoError("Error enqueuing new buffer", end); if (CurFileInfo->mLoadAtOnce) CurFileInfo->mFileDataInQueue = true; THIS->mCurrentPacket += nPackets; end: return; }
OSStatus DiskInUGenInternal::clearOutputsAndReadData(bool& shouldDelete) throw() { const int outputBlockSize = uGenOutput.getBlockSize(); const double sampeRateRatio = 1.0;//fileSampleRate * UGen::getReciprocalSampleRate(); const int inputBlockSize = outputBlockSize * sampeRateRatio; if(inputBlockSize > allocatedBlockSize) { allocatedBlockSize = inputBlockSize; audioData = realloc(audioData, bytesPerFrame * allocatedBlockSize); if(!audioData) { printf("DiskIn: error: could not allocated memory for the new buffer size\n\n"); AudioFileClose(audioFile_); audioFile_ = 0; } } for(int channel = 0; channel < numChannels_; channel++) { float *outputSamples = proxies[channel]->getSampleData(); memset(outputSamples, 0, outputBlockSize * sizeof(float)); } if(!audioFile_) { numPackets = 0; return -1; } else { numPackets = inputBlockSize; UInt32 numBytesRead = -1; OSStatus result = AudioFileReadPackets(audioFile_, false, &numBytesRead, NULL, currentPacket, &numPackets, audioData); if(result == noErr) { currentPacket += numPackets; if(numPackets < inputBlockSize) { if(loopFlag_) { // we hit the end of the file and looping is on, we need to pull // a few samples from the start of the file const int remainingPackets = inputBlockSize - numPackets; unsigned char *remainingAudioData = (unsigned char*)audioData; remainingAudioData += remainingPackets * bytesPerFrame; numPackets = remainingPackets; result = AudioFileReadPackets(audioFile_, false, &numBytesRead, NULL, 0, &numPackets, audioData); if(result == noErr) { currentPacket = remainingPackets; } } else { if(shouldDeleteValue) setIsDone(); shouldDelete = shouldDelete ? true : shouldDeleteValue; } } } return result; } }