void ACSimpleCodec::ConsumeInputData(UInt32 inConsumedByteSize) { // this is a convenience routine to make maintaining the ring buffer state easy UInt32 theContiguousRange = GetInputBufferContiguousByteSize(); if(inConsumedByteSize > GetUsedInputBufferByteSize()) CODEC_THROW(kAudioCodecUnspecifiedError); if(inConsumedByteSize <= theContiguousRange) { // the region to consume doesn't wrap // figure out how much to consume inConsumedByteSize = (theContiguousRange < inConsumedByteSize) ? theContiguousRange : inConsumedByteSize; // clear the consumed bits memset(mInputBuffer + mInputBufferStart, 0, inConsumedByteSize); // adjust the start mInputBufferStart += inConsumedByteSize; } else { // the region to consume will wrap // clear the bits to the end of the buffer memset(mInputBuffer + mInputBufferStart, 0, theContiguousRange); // now clear the bits left from the start memset(mInputBuffer, 0, inConsumedByteSize - theContiguousRange); // adjust the start mInputBufferStart = inConsumedByteSize - theContiguousRange; } }
void ACSimpleCodec::AppendInputData(const void* inInputData, UInt32& ioInputDataByteSize, UInt32& ioNumberPackets, const AudioStreamPacketDescription* inPacketDescription) { // this buffer handling code doesn't care about such things as the packet descriptions if(!mIsInitialized) CODEC_THROW(kAudioCodecStateError); // this is a ring buffer we're dealing with, so we need to set up a few things UInt32 theUsedByteSize = GetUsedInputBufferByteSize(); UInt32 theAvailableByteSize = GetInputBufferByteSize() - theUsedByteSize; UInt32 theMaxAvailableInputBytes = ioInputDataByteSize; // we can't consume more than we get const Byte* theInputData = static_cast<const Byte*>(inInputData); // >>jamesmcc: added this because ioNumberPackets was not being updated if less was taken than given. // THIS ASSUMES CBR! UInt32 bytesPerPacketOfInput = mInputFormat.mBytesPerPacket; UInt32 theAvailablePacketSize = theAvailableByteSize / bytesPerPacketOfInput; UInt32 minPacketSize = ioNumberPackets < theAvailablePacketSize ? ioNumberPackets : theAvailablePacketSize; UInt32 minByteSize = minPacketSize * bytesPerPacketOfInput; // we can copy only as much data as there is or up to how much space is availiable ioNumberPackets = minPacketSize; ioInputDataByteSize = minByteSize; // ioInputDataByteSize had better be <= to theMaxAvailableInputBytes or we're screwed if (ioInputDataByteSize > theMaxAvailableInputBytes) { CODEC_THROW(kAudioCodecStateError); } // <<jamesmcc // now we have to copy the data taking into account the wrap around and where the start is if(mInputBufferEnd + ioInputDataByteSize < mInputBufferByteSize) { // no wrap around here memcpy(mInputBuffer + mInputBufferEnd, theInputData, ioInputDataByteSize); // adjust the end point mInputBufferEnd += ioInputDataByteSize; } else { // the copy will wrap // copy the first part UInt32 theBeforeWrapByteSize = mInputBufferByteSize - mInputBufferEnd; memcpy(mInputBuffer + mInputBufferEnd, theInputData, theBeforeWrapByteSize); // and the rest UInt32 theAfterWrapByteSize = ioInputDataByteSize - theBeforeWrapByteSize; memcpy(mInputBuffer, theInputData + theBeforeWrapByteSize, theAfterWrapByteSize); // adjust the end point mInputBufferEnd = theAfterWrapByteSize; } }
void ACSimpleCodec::AppendInputBuffer(const void* inInputData, UInt32 inOffset, UInt32& ioInputDataByteSize) { // this buffer handling code doesn't care about such things as the packet descriptions if(!mIsInitialized) CODEC_THROW(kAudioCodecStateError); // this is a ring buffer we're dealing with, so we need to set up a few things UInt32 theUsedByteSize = GetUsedInputBufferByteSize(); UInt32 theAvailableByteSize = GetInputBufferByteSize() - theUsedByteSize; const Byte* theInputData = static_cast<const Byte*>(inInputData) + inOffset; if(ioInputDataByteSize > theAvailableByteSize) { ioInputDataByteSize = theAvailableByteSize; } // now we have to copy the data taking into account the wrap around and where the start is if(mInputBufferEnd + ioInputDataByteSize < mInputBufferByteSize) { // no wrap around here memcpy(mInputBuffer + mInputBufferEnd, theInputData, ioInputDataByteSize); // adjust the end point mInputBufferEnd += ioInputDataByteSize; } else { // the copy will wrap // copy the first part UInt32 theBeforeWrapByteSize = mInputBufferByteSize - mInputBufferEnd; memcpy(mInputBuffer + mInputBufferEnd, theInputData, theBeforeWrapByteSize); // and the rest UInt32 theAfterWrapByteSize = ioInputDataByteSize - theBeforeWrapByteSize; memcpy(mInputBuffer, theInputData + theBeforeWrapByteSize, theAfterWrapByteSize); // adjust the end point mInputBufferEnd = theAfterWrapByteSize; } }
Byte* ACSimpleCodec::GetBytes(UInt32& ioNumberBytes) const { // if a client's algorithm has to have contiguous data and mInputBuffer wraps, then someone has to make a copy. // I can do it more efficiently than the client. if(!mIsInitialized) CODEC_THROW(kAudioCodecStateError); UInt32 theUsedByteSize = GetUsedInputBufferByteSize(); //UInt32 theAvailableByteSize = GetInputBufferByteSize() - theUsedByteSize; if (ioNumberBytes > theUsedByteSize) ioNumberBytes = theUsedByteSize; SInt32 leftOver = mInputBufferStart + ioNumberBytes - mInputBufferByteSize; if(leftOver > 0) { // need to copy beginning of buffer to the end. // We cleverly over allocated our buffer space to make this possible. memmove(mInputBuffer + mInputBufferByteSize, mInputBuffer, leftOver); } return GetInputBufferStart(); }
void ACBaseCodec::GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData) { UInt32 thePacketsToGet; switch(inPropertyID) { case kAudioCodecPropertyNameCFString: { if (ioPropertyDataSize != SizeOf32(CFStringRef)) CODEC_THROW(kAudioCodecBadPropertySizeError); CABundleLocker lock; CFStringRef name = CFCopyLocalizedStringFromTableInBundle(CFSTR("unknown codec"), CFSTR("CodecNames"), GetCodecBundle(), CFSTR("")); *(CFStringRef*)outPropertyData = name; break; } case kAudioCodecPropertyManufacturerCFString: { if (ioPropertyDataSize != SizeOf32(CFStringRef)) CODEC_THROW(kAudioCodecBadPropertySizeError); CABundleLocker lock; CFStringRef name = CFCopyLocalizedStringFromTableInBundle(CFSTR("Apple, Inc."), CFSTR("CodecNames"), GetCodecBundle(), CFSTR("")); *(CFStringRef*)outPropertyData = name; break; } case kAudioCodecPropertyRequiresPacketDescription: if(ioPropertyDataSize == SizeOf32(UInt32)) { *reinterpret_cast<UInt32*>(outPropertyData) = 0; } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyMinimumNumberInputPackets : if(ioPropertyDataSize != SizeOf32(UInt32)) CODEC_THROW(kAudioCodecBadPropertySizeError); *(UInt32*)outPropertyData = 1; break; case kAudioCodecPropertyMinimumNumberOutputPackets : if(ioPropertyDataSize != SizeOf32(UInt32)) CODEC_THROW(kAudioCodecBadPropertySizeError); *(UInt32*)outPropertyData = 1; break; case kAudioCodecPropertyCurrentInputFormat: if(ioPropertyDataSize == SizeOf32(AudioStreamBasicDescription)) { GetCurrentInputFormat(*reinterpret_cast<AudioStreamBasicDescription*>(outPropertyData)); } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertySupportedInputFormats: case kAudioCodecPropertyInputFormatsForOutputFormat: thePacketsToGet = ioPropertyDataSize / SizeOf32(AudioStreamBasicDescription); GetSupportedInputFormats(reinterpret_cast<AudioStreamBasicDescription*>(outPropertyData), thePacketsToGet); ioPropertyDataSize = thePacketsToGet * SizeOf32(AudioStreamBasicDescription); break; case kAudioCodecPropertyCurrentOutputFormat: if(ioPropertyDataSize == SizeOf32(AudioStreamBasicDescription)) { GetCurrentOutputFormat(*reinterpret_cast<AudioStreamBasicDescription*>(outPropertyData)); } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertySupportedOutputFormats: case kAudioCodecPropertyOutputFormatsForInputFormat: thePacketsToGet = ioPropertyDataSize / SizeOf32(AudioStreamBasicDescription); GetSupportedOutputFormats(reinterpret_cast<AudioStreamBasicDescription*>(outPropertyData), thePacketsToGet); ioPropertyDataSize = thePacketsToGet * SizeOf32(AudioStreamBasicDescription); break; case kAudioCodecPropertyMagicCookie: if(ioPropertyDataSize >= GetMagicCookieByteSize()) { GetMagicCookie(outPropertyData, ioPropertyDataSize); } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyInputBufferSize: if(ioPropertyDataSize == SizeOf32(UInt32)) { *reinterpret_cast<UInt32*>(outPropertyData) = GetInputBufferByteSize(); } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyUsedInputBufferSize: if(ioPropertyDataSize == SizeOf32(UInt32)) { *reinterpret_cast<UInt32*>(outPropertyData) = GetUsedInputBufferByteSize(); } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyIsInitialized: if(ioPropertyDataSize == SizeOf32(UInt32)) { *reinterpret_cast<UInt32*>(outPropertyData) = IsInitialized() ? 1 : 0; } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyAvailableNumberChannels: if(ioPropertyDataSize == SizeOf32(UInt32) * 2) { (reinterpret_cast<UInt32*>(outPropertyData))[0] = 1; (reinterpret_cast<UInt32*>(outPropertyData))[1] = 2; } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyPrimeMethod: if(ioPropertyDataSize == SizeOf32(UInt32)) { *reinterpret_cast<UInt32*>(outPropertyData) = (UInt32)kAudioCodecPrimeMethod_None; } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyPrimeInfo: if(ioPropertyDataSize == SizeOf32(AudioCodecPrimeInfo) ) { (reinterpret_cast<AudioCodecPrimeInfo*>(outPropertyData))->leadingFrames = 0; (reinterpret_cast<AudioCodecPrimeInfo*>(outPropertyData))->trailingFrames = 0; } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; case kAudioCodecPropertyDoesSampleRateConversion: if(ioPropertyDataSize == SizeOf32(UInt32)) { *reinterpret_cast<UInt32*>(outPropertyData) = 0; } else { CODEC_THROW(kAudioCodecBadPropertySizeError); } break; default: CODEC_THROW(kAudioCodecUnknownPropertyError); break; }; }