Skip to content

Commit

Permalink
direct access to CoreAudioToolbox
Browse files Browse the repository at this point in the history
  • Loading branch information
nu774 committed Nov 9, 2011
1 parent b640d20 commit 7bb2914
Show file tree
Hide file tree
Showing 53 changed files with 1,583 additions and 6,810 deletions.
105 changes: 105 additions & 0 deletions AudioCodec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#ifndef AudioCodec_H
#define AudioCodec_H

#include <Components.h>

#ifdef __cplusplus
extern "C" {
#endif

enum {
kAudioCodecPropertyNameCFString = 'lnam',
kAudioCodecPropertyManufacturerCFString = 'lmak',
kAudioCodecPropertyFormatCFString = 'lfor',
//kAudioCodecPropertyHasVariablePacketByteSizes = 'vpk?',
kAudioCodecPropertySupportedInputFormats = 'ifm#',
kAudioCodecPropertySupportedOutputFormats = 'ofm#',
kAudioCodecPropertyAvailableInputSampleRates = 'aisr',
kAudioCodecPropertyAvailableOutputSampleRates = 'aosr',
kAudioCodecPropertyAvailableBitRateRange = 'abrt',
kAudioCodecPropertyMinimumNumberInputPackets = 'mnip',
kAudioCodecPropertyMinimumNumberOutputPackets = 'mnop',
kAudioCodecPropertyAvailableNumberChannels = 'cmnc',
kAudioCodecPropertyDoesSampleRateConversion = 'lmrc',
kAudioCodecPropertyAvailableInputChannelLayoutTags = 'aicl',
kAudioCodecPropertyAvailableOutputChannelLayoutTags = 'aocl',
kAudioCodecPropertyInputFormatsForOutputFormat = 'if4o',
kAudioCodecPropertyOutputFormatsForInputFormat = 'of4i',
kAudioCodecPropertyFormatInfo = 'acfi',
};

enum {
kAudioCodecPropertyInputBufferSize = 'tbuf',
kAudioCodecPropertyPacketFrameSize = 'pakf',
kAudioCodecPropertyMaximumPacketByteSize = 'pakb',
kAudioCodecPropertyCurrentInputFormat = 'ifmt',
kAudioCodecPropertyCurrentOutputFormat = 'ofmt',
kAudioCodecPropertyMagicCookie = 'kuki',
kAudioCodecPropertyUsedInputBufferSize = 'ubuf',
kAudioCodecPropertyIsInitialized = 'init',
kAudioCodecPropertyCurrentTargetBitRate = 'brat',
kAudioCodecPropertyCurrentInputSampleRate = 'cisr',
kAudioCodecPropertyCurrentOutputSampleRate = 'cosr',
kAudioCodecPropertyQualitySetting = 'srcq',
kAudioCodecPropertyApplicableBitRateRange = 'brta',
kAudioCodecPropertyApplicableInputSampleRates = 'isra',
kAudioCodecPropertyApplicableOutputSampleRates = 'osra',
kAudioCodecPropertyPaddedZeros = 'pad0',
kAudioCodecPropertyPrimeMethod = 'prmm',
kAudioCodecPropertyPrimeInfo = 'prim',
kAudioCodecPropertyCurrentInputChannelLayout = 'icl ',
kAudioCodecPropertyCurrentOutputChannelLayout = 'ocl ',
kAudioCodecPropertySettings = 'acs ',
kAudioCodecPropertyFormatList = 'acfl',
kAudioCodecPropertyBitRateControlMode = 'acbf',
kAudioCodecPropertySoundQualityForVBR = 'vbrq',
kAudioCodecPropertyMinimumDelayMode = 'mdel'
};

enum {
kAudioCodecBitRateControlMode_Constant = 0,
kAudioCodecBitRateControlMode_LongTermAverage = 1,
kAudioCodecBitRateControlMode_VariableConstrained = 2,
kAudioCodecBitRateControlMode_Variable = 3,
};

typedef ComponentInstance AudioCodec;
typedef UInt32 AudioCodecPropertyID;

typedef struct AudioCodecPrimeInfo {
UInt32 leadingFrames;
UInt32 trailingFrames;
} AudioCodecPrimeInfo;

ComponentResult AudioCodecGetProperty (
AudioCodec inCodec,
AudioCodecPropertyID inPropertyID,
UInt32 *ioPropertyDataSize,
void *outPropertyData);

ComponentResult AudioCodecGetPropertyInfo (
AudioCodec inCodec,
AudioCodecPropertyID inPropertyID,
UInt32 *outSize,
Boolean *outWritable);

ComponentResult AudioCodecInitialize (
AudioCodec inCodec,
const AudioStreamBasicDescription *inInputFormat,
const AudioStreamBasicDescription *inOutputFormat,
const void *inMagicCookie,
UInt32 inMagicCookieByteSize);

ComponentResult AudioCodecSetProperty (
AudioCodec inCodec,
AudioCodecPropertyID inPropertyID,
UInt32 inPropertyDataSize,
const void *inPropertyData);

ComponentResult AudioCodecUninitialize(AudioCodec inCodec);

#ifdef __cplusplus
}
#endif

#endif
132 changes: 132 additions & 0 deletions AudioCodecX.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#ifndef AudioCodecX_H
#define AudioCodecX_H

#include "CoreAudioToolbox.h"

class AudioCodecX {
x::shared_ptr<ComponentInstanceRecord> m_codec;
public:
AudioCodecX() {}
AudioCodecX(OSType codec)
{
AudioComponentDescription desc = { 'aenc', codec, 0 };
AudioComponent component = AudioComponentFindNext(0, &desc);
if (!component) {
throw std::runtime_error(format(
"AudioComponentFindNext: component %s not found",
fourcc(codec).svalue));
}
AudioComponentInstance aci;
CHECKCA(AudioComponentInstanceNew(component, &aci));
attach(reinterpret_cast<AudioCodec>(aci), true);
}
AudioCodecX(AudioCodec codec, bool takeOwn)
{
attach(codec, takeOwn);
}
void attach(AudioCodec codec, bool takeOwn)
{
OSStatus (*dispose)(AudioCodec) =
takeOwn ? reinterpret_cast<OSStatus (*)(AudioCodec)>(
AudioComponentInstanceDispose)
: fakeDispose;
m_codec = x::shared_ptr<ComponentInstanceRecord>(codec, dispose);
}
operator AudioCodec() { return m_codec.get(); }

// property accessor
void getAvailableInputSampleRates(std::vector<AudioValueRange> *result)
{
UInt32 size;
Boolean writable;
CHECKCA(AudioCodecGetPropertyInfo(m_codec.get(),
kAudioCodecPropertyAvailableInputSampleRates,
&size, &writable));
std::vector<AudioValueRange> vec(size / sizeof(AudioValueRange));
CHECKCA(AudioCodecGetProperty(m_codec.get(),
kAudioCodecPropertyAvailableInputSampleRates,
&size, &vec[0]));
result->swap(vec);
}
void getAvailableOutputSampleRates(std::vector<AudioValueRange> *result)
{
UInt32 size;
Boolean writable;
CHECKCA(AudioCodecGetPropertyInfo(m_codec.get(),
kAudioCodecPropertyAvailableOutputSampleRates,
&size, &writable));
std::vector<AudioValueRange> vec(size / sizeof(AudioValueRange));
CHECKCA(AudioCodecGetProperty(m_codec.get(),
kAudioCodecPropertyAvailableOutputSampleRates,
&size, &vec[0]));
result->swap(vec);
}
void getAvailableOutputChannelLayoutTags(std::vector<UInt32> *result)
{
UInt32 size;
Boolean writable;
CHECKCA(AudioCodecGetPropertyInfo(m_codec.get(),
kAudioCodecPropertyAvailableOutputChannelLayoutTags,
&size, &writable));
std::vector<UInt32> vec(size/sizeof(UInt32));
CHECKCA(AudioCodecGetProperty(m_codec.get(),
kAudioCodecPropertyAvailableOutputChannelLayoutTags,
&size, &vec[0]));
result->swap(vec);
}
bool getIsInitialized()
{
UInt32 value;
UInt32 size = sizeof value;
CHECKCA(AudioCodecGetProperty(m_codec.get(),
kAudioCodecPropertyIsInitialized, &size, &value));
return !!value;
}
void getApplicableBitRateRange(std::vector<AudioValueRange> *result)
{
UInt32 size;
Boolean writable;
CHECKCA(AudioCodecGetPropertyInfo(m_codec.get(),
kAudioCodecPropertyApplicableBitRateRange,
&size, &writable));
std::vector<AudioValueRange> vec(size / sizeof(AudioValueRange));
CHECKCA(AudioCodecGetProperty(m_codec.get(),
kAudioCodecPropertyApplicableBitRateRange, &size, &vec[0]));
result->swap(vec);
}

// helpers
bool isAvailableOutputChannelLayout(UInt32 tag)
{
std::vector<UInt32> tags;
getAvailableOutputChannelLayoutTags(&tags);
return std::find(tags.begin(), tags.end(), tag) != tags.end();
}

double getClosestAvailableOutputSampleRate(double value)
{
std::vector<AudioValueRange> rates;
getAvailableOutputSampleRates(&rates);
double distance = DBL_MAX;
double pick = value;
std::vector<AudioValueRange>::const_iterator it = rates.begin();
for (; it != rates.end(); ++it) {
if (!it->mMinimum && !it->mMaximum)
continue;
if (it->mMinimum <= value && value <= it->mMaximum)
return value;
double ldiff = std::fabs(value - it->mMinimum),
rdiff = std::fabs(value - it->mMaximum);
double diff = std::min(ldiff, rdiff);
if (distance > diff) {
distance = diff;
pick = ldiff > rdiff ? it->mMaximum : it->mMinimum;
}
}
return pick;
}
private:
static OSStatus fakeDispose(AudioCodec) { return 0; }
};

#endif
62 changes: 62 additions & 0 deletions AudioComponent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#ifndef AudioComponent_H
#define AudioComponent_H

#include <CoreFoundation.h>
#include <CoreAudioTypes.h>

#ifdef __cplusplus
extern "C" {
#endif

struct OpaqueAudioComponent;
typedef struct OpaqueAudioComponent *AudioComponent;

struct OpaqueAudioComponentInstance;
typedef struct OpaqueAudioComponentInstance *AudioComponentInstance;

typedef struct AudioComponentDescription {
OSType componentType;
OSType componentSubType;
OSType componentManufacturer;
UInt32 componentFlags;
UInt32 componentFlagsMask;
} AudioComponentDescription;

AudioComponent AudioComponentFindNext(
AudioComponent inAComponent,
AudioComponentDescription *inDesc
);

OSStatus AudioComponentGetDescription(
AudioComponent inComponent,
AudioComponentDescription *outDesc
);

OSStatus AudioComponentGetVersion(
AudioComponent inComponent,
UInt32 *outVersion
);

OSStatus AudioComponentInstanceDispose(
AudioComponentInstance inInstance
);

OSStatus AudioComponentInstanceNew(
AudioComponent inComponent,
AudioComponentInstance *outInstance
);

typedef void *CFPlugInFactoryFunction; // XXX

AudioComponent AudioComponentRegister(
const AudioComponentDescription *inDesc,
CFStringRef inName,
UInt32 inVersion,
CFPlugInFactoryFunction inFactory
);

#ifdef __cplusplus
}
#endif

#endif
Loading

0 comments on commit 7bb2914

Please sign in to comment.