Codecs/IMA4/ACAppleIMA4Codec.cpp
/* |
File: ACAppleIMA4Codec.cpp |
Abstract: ACAppleIMA4Codec.cpp file for AudioCodecSDK. |
Version: 1.0 |
Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple |
Inc. ("Apple") in consideration of your agreement to the following |
terms, and your use, installation, modification or redistribution of |
this Apple software constitutes acceptance of these terms. If you do |
not agree with these terms, please do not use, install, modify or |
redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and |
subject to these terms, Apple grants you a personal, non-exclusive |
license, under Apple's copyrights in this original Apple software (the |
"Apple Software"), to use, reproduce, modify and redistribute the Apple |
Software, with or without modifications, in source and/or binary forms; |
provided that if you redistribute the Apple Software in its entirety and |
without modifications, you must retain this notice and the following |
text and disclaimers in all such redistributions of the Apple Software. |
Neither the name, trademarks, service marks or logos of Apple Inc. may |
be used to endorse or promote products derived from the Apple Software |
without specific prior written permission from Apple. Except as |
expressly stated in this notice, no other rights or licenses, express or |
implied, are granted by Apple herein, including but not limited to any |
patent rights that may be infringed by your derivative works or by other |
works in which the Apple Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE |
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION |
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS |
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND |
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL |
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, |
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED |
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), |
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
Copyright (C) 2013 Apple Inc. All Rights Reserved. |
*/ |
//============================================================================= |
// Includes |
//============================================================================= |
#include "ACAppleIMA4Codec.h" |
#include "CABundleLocker.h" |
//============================================================================= |
// ACAppleIMA4Codec |
//============================================================================= |
ACAppleIMA4Codec::ACAppleIMA4Codec(UInt32 inInputBufferByteSize, AudioComponentInstance inInstance) |
: |
ACSimpleCodec(inInputBufferByteSize, inInstance), |
mChannelStateList() |
{ |
} |
ACAppleIMA4Codec::~ACAppleIMA4Codec() |
{ |
} |
void ACAppleIMA4Codec::Initialize(const AudioStreamBasicDescription* inInputFormat, const AudioStreamBasicDescription* inOutputFormat, const void* inMagicCookie, UInt32 inMagicCookieByteSize) |
{ |
// use the given arguments, if necessary |
if(inInputFormat != NULL) |
{ |
SetCurrentInputFormat(*inInputFormat); |
} |
if(inOutputFormat != NULL) |
{ |
SetCurrentOutputFormat(*inOutputFormat); |
} |
FixFormats(); |
// make sure the sample rate and number of channels match between the input format and the output format |
if( (mInputFormat.mSampleRate != mOutputFormat.mSampleRate) || |
(mInputFormat.mChannelsPerFrame != mOutputFormat.mChannelsPerFrame)) |
{ |
CODEC_THROW(kAudioCodecUnsupportedFormatError); |
} |
// initalize the channel state list |
InitializeChannelStateList(); |
ACSimpleCodec::Initialize(inInputFormat, inOutputFormat, inMagicCookie, inMagicCookieByteSize); |
} |
void ACAppleIMA4Codec::Uninitialize() |
{ |
// clean up the internal state |
ResetChannelStateList(); |
// let our base class clean up it's internal state |
ACSimpleCodec::Uninitialize(); |
} |
void ACAppleIMA4Codec::Reset() |
{ |
// clean up the internal state |
ResetChannelStateList(); |
// let our base class clean up it's internal state |
ACSimpleCodec::Reset(); |
} |
void ACAppleIMA4Codec::InitializeChannelStateList() |
{ |
mChannelStateList.clear(); |
for(UInt32 theIndex = 0; theIndex < mInputFormat.mChannelsPerFrame; ++theIndex) |
{ |
mChannelStateList.push_back(ChannelState()); |
} |
} |
void ACAppleIMA4Codec::ResetChannelStateList() |
{ |
ChannelStateList::iterator theIterator = mChannelStateList.begin(); |
while(theIterator != mChannelStateList.end()) |
{ |
theIterator->Reset(); |
std::advance(theIterator, 1); |
} |
} |
void ACAppleIMA4Codec::GetPropertyInfo(AudioCodecPropertyID inPropertyID, UInt32& outPropertyDataSize, Boolean& outWritable) |
{ |
switch(inPropertyID) |
{ |
case kAudioCodecPropertyMaximumPacketByteSize: |
outPropertyDataSize = SizeOf32(UInt32); |
outWritable = false; |
break; |
case kAudioCodecPropertyRequiresPacketDescription: |
outPropertyDataSize = SizeOf32(UInt32); |
outWritable = false; |
break; |
case kAudioCodecPropertyHasVariablePacketByteSizes: |
outPropertyDataSize = SizeOf32(UInt32); |
outWritable = false; |
break; |
case kAudioCodecPropertyPacketFrameSize: |
outPropertyDataSize = SizeOf32(UInt32); |
outWritable = false; |
break; |
case kAudioCodecPropertyCurrentInputSampleRate: |
outPropertyDataSize = SizeOf32(Float64); |
outWritable = false; |
break; |
case kAudioCodecPropertyCurrentOutputSampleRate: |
outPropertyDataSize = SizeOf32(Float64); |
outWritable = false; |
break; |
case kAudioCodecPropertyCurrentInputChannelLayout: |
case kAudioCodecPropertyCurrentOutputChannelLayout: |
outPropertyDataSize = SizeOf32(AudioChannelLayout); |
outWritable = false; |
break; |
case kAudioCodecPropertyAvailableInputChannelLayoutTags: |
case kAudioCodecPropertyAvailableOutputChannelLayoutTags: |
outPropertyDataSize = kMaxIMA4Channels * SizeOf32(AudioChannelLayoutTag); |
outWritable = false; |
break; |
case kAudioCodecPropertyFormatInfo: |
outPropertyDataSize = SizeOf32(AudioFormatInfo); |
outWritable = false; |
break; |
default: |
ACSimpleCodec::GetPropertyInfo(inPropertyID, outPropertyDataSize, outWritable); |
break; |
}; |
} |
void ACAppleIMA4Codec::GetProperty(AudioCodecPropertyID inPropertyID, UInt32& ioPropertyDataSize, void* outPropertyData) |
{ |
switch(inPropertyID) |
{ |
#if !BUILD_ADEC_LIB |
case kAudioCodecPropertyFormatCFString: |
{ |
if (ioPropertyDataSize != SizeOf32(CFStringRef)) |
{ |
CODEC_THROW(kAudioCodecBadPropertySizeError); |
} |
CABundleLocker lock; |
CFStringRef name = CFCopyLocalizedStringFromTableInBundle(CFSTR("Acme IMA4"), CFSTR("CodecNames"), GetCodecBundle(), CFSTR("")); |
*(CFStringRef*)outPropertyData = name; |
break; |
} |
#endif |
case kAudioCodecPropertyMaximumPacketByteSize: |
if(ioPropertyDataSize == SizeOf32(UInt32)) |
{ |
*reinterpret_cast<UInt32*>(outPropertyData) = kIMA4PacketBytes * mInputFormat.mChannelsPerFrame; |
} |
else |
{ |
CODEC_THROW(kAudioCodecBadPropertySizeError); |
} |
break; |
case kAudioCodecPropertyRequiresPacketDescription: |
if(ioPropertyDataSize == SizeOf32(UInt32)) |
{ |
*reinterpret_cast<UInt32*>(outPropertyData) = 0; |
} |
else |
{ |
CODEC_THROW(kAudioCodecBadPropertySizeError); |
} |
break; |
case kAudioCodecPropertyHasVariablePacketByteSizes: |
if(ioPropertyDataSize == SizeOf32(UInt32)) |
{ |
*reinterpret_cast<UInt32*>(outPropertyData) = 0; // We are constant bitrate |
} |
else |
{ |
CODEC_THROW(kAudioCodecBadPropertySizeError); |
} |
break; |
case kAudioCodecPropertyPacketFrameSize: |
if(ioPropertyDataSize == SizeOf32(UInt32)) |
{ |
*reinterpret_cast<UInt32*>(outPropertyData) = kIMAFramesPerPacket; |
} |
else |
{ |
CODEC_THROW(kAudioCodecBadPropertySizeError); |
} |
break; |
case kAudioCodecPropertyCurrentInputSampleRate: |
if(ioPropertyDataSize == SizeOf32(Float64)) |
{ |
*reinterpret_cast<Float64*>(outPropertyData) = (Float64)(mInputFormat.mSampleRate); |
} |
else |
{ |
CODEC_THROW(kAudioCodecBadPropertySizeError); |
} |
break; |
case kAudioCodecPropertyCurrentOutputSampleRate: |
if(ioPropertyDataSize == SizeOf32(Float64)) |
{ |
*reinterpret_cast<Float64*>(outPropertyData) = (Float64)(mOutputFormat.mSampleRate); |
} |
else |
{ |
CODEC_THROW(kAudioCodecBadPropertySizeError); |
} |
break; |
case kAudioCodecPropertyCurrentInputChannelLayout: |
case kAudioCodecPropertyCurrentOutputChannelLayout: |
AudioChannelLayout temp1AudioChannelLayout; |
memset(&temp1AudioChannelLayout, 0, SizeOf32(AudioChannelLayout)); |
if(ioPropertyDataSize == SizeOf32(AudioChannelLayout)) |
{ |
if (mInputFormat.mChannelsPerFrame == 1) |
{ |
temp1AudioChannelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono; |
} |
else |
{ |
temp1AudioChannelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; |
} |
memcpy(outPropertyData, &temp1AudioChannelLayout, ioPropertyDataSize); |
} |
else |
{ |
CODEC_THROW(kAudioCodecBadPropertySizeError); |
} |
break; |
case kAudioCodecPropertyAvailableInputChannelLayoutTags: |
case kAudioCodecPropertyAvailableOutputChannelLayoutTags: |
if(ioPropertyDataSize == kMaxIMA4Channels * SizeOf32(AudioChannelLayoutTag)) |
{ |
if(mIsInitialized) |
{ |
AudioChannelLayoutTag temp2AudioChannelLayoutTag[1]; |
if (mInputFormat.mChannelsPerFrame == 1) |
{ |
temp2AudioChannelLayoutTag[0] = kAudioChannelLayoutTag_Mono; |
} |
else |
{ |
temp2AudioChannelLayoutTag[0] = kAudioChannelLayoutTag_Stereo; |
} |
ioPropertyDataSize = SizeOf32(AudioChannelLayoutTag); |
memcpy(reinterpret_cast<AudioChannelLayoutTag*>(outPropertyData), temp2AudioChannelLayoutTag, ioPropertyDataSize); |
} |
else |
{ |
AudioChannelLayoutTag temp2AudioChannelLayoutTag[2]; |
temp2AudioChannelLayoutTag[0] = kAudioChannelLayoutTag_Mono; |
temp2AudioChannelLayoutTag[1] = kAudioChannelLayoutTag_Stereo; |
memcpy(reinterpret_cast<AudioChannelLayoutTag*>(outPropertyData), temp2AudioChannelLayoutTag, ioPropertyDataSize); |
} |
} |
else |
{ |
CODEC_THROW(kAudioCodecBadPropertySizeError); |
} |
break; |
case kAudioCodecPropertyFormatInfo: |
if(ioPropertyDataSize == SizeOf32(AudioFormatInfo)) |
{ |
AudioFormatInfo& formatInfo = *(AudioFormatInfo*)outPropertyData; |
// We don't have a cookie, we have to check the ASBD |
// according to the input formats |
UInt32 i; |
for(i = 0; i < GetNumberSupportedInputFormats(); ++i) |
{ |
if(mInputFormatList[i].IsEqual(formatInfo.mASBD)) |
{ |
// Fill out missing entries |
CAStreamBasicDescription::FillOutFormat(formatInfo.mASBD, mInputFormatList[i]); |
break; |
} |
} |
if(i == GetNumberSupportedInputFormats()) |
{ |
// No suitable settings found |
CODEC_THROW(kAudioCodecUnsupportedFormatError); |
} |
} |
else |
{ |
CODEC_THROW(kAudioCodecBadPropertySizeError); |
} |
break; |
default: |
ACSimpleCodec::GetProperty(inPropertyID, ioPropertyDataSize, outPropertyData); |
} |
} |
void ACAppleIMA4Codec::SetProperty(AudioCodecPropertyID inPropertyID, UInt32 inPropertyDataSize, const void* inPropertyData) |
{ |
switch(inPropertyID) |
{ |
case kAudioCodecPropertyFormatInfo: |
case kAudioCodecPropertyHasVariablePacketByteSizes: |
case kAudioCodecPropertyCurrentInputChannelLayout: |
case kAudioCodecPropertyCurrentOutputChannelLayout: |
case kAudioCodecPropertyPacketFrameSize: |
case kAudioCodecPropertyAvailableInputChannelLayoutTags: |
case kAudioCodecPropertyAvailableOutputChannelLayoutTags: |
case kAudioCodecDoesSampleRateConversion: |
case kAudioCodecPropertyMaximumPacketByteSize: |
case kAudioCodecPropertyCurrentInputSampleRate: |
case kAudioCodecPropertyCurrentOutputSampleRate: |
CODEC_THROW(kAudioCodecIllegalOperationError); |
break; |
default: |
ACSimpleCodec::SetProperty(inPropertyID, inPropertyDataSize, inPropertyData); |
break; |
} |
} |
const UInt16 ACAppleIMA4Codec::kPredictorMask = 0xFF80; |
const UInt16 ACAppleIMA4Codec::kStepTableIndexMask = 0x007F; |
const SInt32 ACAppleIMA4Codec::kPredictorTolerance = 0x0000007F; |
const SInt16 ACAppleIMA4Codec::sIndexTable[16] = { -1,-1,-1,-1, 2, 4, 6, 8, -1,-1,-1,-1, 2, 4, 6, 8 }; |
const SInt16 ACAppleIMA4Codec::sStepTable[89] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, |
19, 21, 23, 25, 28, 31, 34, 37, 41, 45, |
50, 55, 60, 66, 73, 80, 88, 97, 107, 118, |
130, 143, 157, 173, 190, 209, 230, 253, 279, 307, |
337, 371, 408, 449, 494, 544, 598, 658, 724, 796, |
876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, |
2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, |
5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, |
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 }; |
Copyright © 2013 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2013-01-02