-
Notifications
You must be signed in to change notification settings - Fork 42
/
AudioCodecX.h
129 lines (123 loc) · 4.41 KB
/
AudioCodecX.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#ifndef AudioCodecX_H
#define AudioCodecX_H
#include "CoreAudio/AudioCodec.h"
#include "cautil.h"
class AudioCodecX {
std::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("AudioComponentFindNext(): "
"codec not found");
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)
{
auto dispose = [](AudioCodec x) {
auto y = reinterpret_cast<AudioComponentInstance>(x);
AudioComponentInstanceDispose(y);
};
if (takeOwn)
m_codec.reset(codec, dispose);
else
m_codec.reset(codec, [](AudioCodec) {});
}
operator AudioCodec() { return m_codec.get(); }
// property accessor
std::vector<AudioValueRange> getAvailableInputSampleRates()
{
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.data()));
return vec;
}
std::vector<AudioValueRange> getAvailableOutputSampleRates()
{
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.data()));
return vec;
}
std::vector<UInt32> getAvailableOutputChannelLayoutTags()
{
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.data()));
return vec;
}
bool getIsInitialized()
{
UInt32 value;
UInt32 size = sizeof value;
CHECKCA(AudioCodecGetProperty(m_codec.get(),
kAudioCodecPropertyIsInitialized, &size, &value));
return !!value;
}
std::vector<AudioValueRange> getApplicableBitRateRange()
{
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.data()));
return vec;
}
// helpers
bool isAvailableOutputChannelLayout(UInt32 tag)
{
auto tags = getAvailableOutputChannelLayoutTags();
return std::find(tags.begin(), tags.end(), tag) != tags.end();
}
double getClosestAvailableOutputSampleRate(double value)
{
auto rates = getAvailableOutputSampleRates();
double distance = DBL_MAX;
double pick = value;
for (auto it = rates.begin(); 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;
}
};
#endif