0
|
1 |
/* This file is part of the KDE project.
|
|
2 |
|
|
3 |
Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
4 |
|
|
5 |
This library is free software: you can redistribute it and/or modify
|
|
6 |
it under the terms of the GNU Lesser General Public License as published by
|
|
7 |
the Free Software Foundation, either version 2.1 or 3 of the License.
|
|
8 |
|
|
9 |
This library is distributed in the hope that it will be useful,
|
|
10 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12 |
GNU Lesser General Public License for more details.
|
|
13 |
|
|
14 |
You should have received a copy of the GNU Lesser General Public License
|
|
15 |
along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
16 |
*/
|
|
17 |
|
|
18 |
#include "audioeffects.h"
|
|
19 |
|
|
20 |
QT_BEGIN_NAMESPACE
|
|
21 |
|
|
22 |
namespace Phonon
|
|
23 |
{
|
|
24 |
namespace QT7
|
|
25 |
{
|
|
26 |
|
|
27 |
AudioEffectAudioNode::AudioEffectAudioNode(int effectType)
|
|
28 |
: AudioNode(1, 1), m_effectType(effectType)
|
|
29 |
{
|
|
30 |
}
|
|
31 |
|
|
32 |
ComponentDescription AudioEffectAudioNode::getAudioNodeDescription() const
|
|
33 |
{
|
|
34 |
ComponentDescription d;
|
|
35 |
d.componentType = kAudioUnitType_Effect;
|
|
36 |
d.componentSubType = m_effectType;
|
|
37 |
d.componentManufacturer = kAudioUnitManufacturer_Apple;
|
|
38 |
d.componentFlags = 0;
|
|
39 |
d.componentFlagsMask = 0;
|
|
40 |
return d;
|
|
41 |
}
|
|
42 |
|
|
43 |
void AudioEffectAudioNode::initializeAudioUnit()
|
|
44 |
{
|
|
45 |
if (!m_audioUnit)
|
|
46 |
return;
|
|
47 |
foreach(int id, m_alteredParameters.keys()){
|
|
48 |
Float32 value = m_alteredParameters.value(id);
|
|
49 |
ComponentResult res = AudioUnitSetParameter(m_audioUnit, id, kAudioUnitScope_Global, 0, value, 0);
|
|
50 |
BACKEND_ASSERT2(res == noErr, "Could not initialize audio effect.", NORMAL_ERROR)
|
|
51 |
}
|
|
52 |
}
|
|
53 |
|
|
54 |
QVariant AudioEffectAudioNode::parameterValue(const Phonon::EffectParameter ¶meter) const
|
|
55 |
{
|
|
56 |
if (m_audioUnit){
|
|
57 |
Float32 value = 0;
|
|
58 |
AudioUnitGetParameter(m_audioUnit, parameter.id(), kAudioUnitScope_Global, 0, &value);
|
|
59 |
return QVariant(value);
|
|
60 |
} else if (m_alteredParameters.contains(parameter.id())){
|
|
61 |
return QVariant(m_alteredParameters.value(parameter.id()));
|
|
62 |
} else {
|
|
63 |
// Use default value:
|
|
64 |
AudioUnit tmpAudioUnit;
|
|
65 |
ComponentDescription description = getAudioNodeDescription();
|
|
66 |
Component component = FindNextComponent(0, &description);
|
|
67 |
BACKEND_ASSERT3(component, "Could not get parameters of audio effect.", NORMAL_ERROR, QVariant())
|
|
68 |
OSErr err = OpenAComponent(component, &tmpAudioUnit);
|
|
69 |
BACKEND_ASSERT3(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR, QVariant())
|
|
70 |
AudioUnitParameterInfo info;
|
|
71 |
UInt32 size = sizeof(info);
|
|
72 |
ComponentResult res = AudioUnitGetProperty(tmpAudioUnit,
|
|
73 |
kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameter.id(), &info, &size);
|
|
74 |
BACKEND_ASSERT3(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR, QVariant())
|
|
75 |
return QVariant(info.defaultValue);
|
|
76 |
}
|
|
77 |
}
|
|
78 |
|
|
79 |
void AudioEffectAudioNode::setParameterValue(const Phonon::EffectParameter ¶meter, const QVariant &newValue)
|
|
80 |
{
|
|
81 |
Float32 value = 0;
|
|
82 |
if (newValue.isValid()){
|
|
83 |
value = newValue.toDouble();
|
|
84 |
m_alteredParameters.insert(parameter.id(), value);
|
|
85 |
} else {
|
|
86 |
// Use default value:
|
|
87 |
m_alteredParameters.remove(parameter.id());
|
|
88 |
if (m_audioUnit){
|
|
89 |
AudioUnit tmpAudioUnit;
|
|
90 |
ComponentDescription description = getAudioNodeDescription();
|
|
91 |
Component component = FindNextComponent(0, &description);
|
|
92 |
BACKEND_ASSERT2(component, "Could not get parameters of audio effect.", NORMAL_ERROR)
|
|
93 |
OSErr err = OpenAComponent(component, &tmpAudioUnit);
|
|
94 |
BACKEND_ASSERT2(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR)
|
|
95 |
AudioUnitParameterInfo info;
|
|
96 |
UInt32 size = sizeof(info);
|
|
97 |
ComponentResult res = AudioUnitGetProperty(tmpAudioUnit,
|
|
98 |
kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameter.id(), &info, &size);
|
|
99 |
BACKEND_ASSERT2(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR)
|
|
100 |
value = info.defaultValue;
|
|
101 |
}
|
|
102 |
}
|
|
103 |
|
|
104 |
if (m_audioUnit){
|
|
105 |
ComponentResult res = AudioUnitSetParameter(m_audioUnit, parameter.id(), kAudioUnitScope_Global, 0, value, 0);
|
|
106 |
BACKEND_ASSERT2(res == noErr, "Could not set effect parameter value.", NORMAL_ERROR)
|
|
107 |
}
|
|
108 |
}
|
|
109 |
|
|
110 |
///////////////////////////////////////////////////////////////////////
|
|
111 |
|
|
112 |
AudioEffect::AudioEffect(int effectType, QObject *parent)
|
|
113 |
: MediaNode(AudioSink | AudioSource, 0, parent)
|
|
114 |
{
|
|
115 |
m_audioNode = new AudioEffectAudioNode(effectType);
|
|
116 |
setAudioNode(m_audioNode);
|
|
117 |
}
|
|
118 |
|
|
119 |
QList<Phonon::EffectParameter> AudioEffect::parameters() const
|
|
120 |
{
|
|
121 |
QList<Phonon::EffectParameter> effectList;
|
|
122 |
// Create a temporary audio unit:
|
|
123 |
AudioUnit audioUnit;
|
|
124 |
ComponentDescription description = m_audioNode->getAudioNodeDescription();
|
|
125 |
Component component = FindNextComponent(0, &description);
|
|
126 |
BACKEND_ASSERT3(component, "Could not get parameters of audio effect.", NORMAL_ERROR, effectList)
|
|
127 |
OSErr err = OpenAComponent(component, &audioUnit);
|
|
128 |
BACKEND_ASSERT3(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR, effectList)
|
|
129 |
|
|
130 |
UInt32 size = 0;
|
|
131 |
// Get parameter count:
|
|
132 |
ComponentResult res = AudioUnitGetProperty(audioUnit,
|
|
133 |
kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, 0, &size);
|
|
134 |
BACKEND_ASSERT3(res == noErr, "Could not get parameter count from audio effect.", NORMAL_ERROR, effectList)
|
|
135 |
int paramCount = size / sizeof(AudioUnitParameterID);
|
|
136 |
|
|
137 |
// Get parameters:
|
|
138 |
AudioUnitParameterID parameters[paramCount];
|
|
139 |
res = AudioUnitGetProperty(audioUnit,
|
|
140 |
kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, ¶meters, &size);
|
|
141 |
BACKEND_ASSERT3(res == noErr, "Could not get parameter list from audio effect.", NORMAL_ERROR, effectList)
|
|
142 |
|
|
143 |
for (int i=0; i<paramCount; ++i)
|
|
144 |
effectList << createParameter(audioUnit, parameters[i]);
|
|
145 |
|
|
146 |
CloseComponent(audioUnit);
|
|
147 |
return effectList;
|
|
148 |
}
|
|
149 |
|
|
150 |
QString AudioEffect::name()
|
|
151 |
{
|
|
152 |
ComponentDescription description = m_audioNode->getAudioNodeDescription();
|
|
153 |
Component component = FindNextComponent(0, &description);
|
|
154 |
BACKEND_ASSERT3(component, "Could not get audio effect name.", NORMAL_ERROR, QLatin1String("<unknown effect>"))
|
|
155 |
|
|
156 |
ComponentDescription cDesc;
|
|
157 |
Handle nameH = NewHandle(0);
|
|
158 |
GetComponentInfo(component, &cDesc, nameH, 0, 0);
|
|
159 |
HLock(nameH);
|
|
160 |
char *namePtr = *nameH;
|
|
161 |
int len = *namePtr++;
|
|
162 |
namePtr[len] = 0;
|
|
163 |
QString qsName = QString::fromUtf8(namePtr);
|
|
164 |
DisposeHandle(nameH);
|
|
165 |
return qsName;
|
|
166 |
}
|
|
167 |
|
|
168 |
QString AudioEffect::description()
|
|
169 |
{
|
|
170 |
ComponentDescription description = m_audioNode->getAudioNodeDescription();
|
|
171 |
Component component = FindNextComponent(0, &description);
|
|
172 |
BACKEND_ASSERT3(component, "Could not get audio effect description.", NORMAL_ERROR, QLatin1String("<unknown effect>"))
|
|
173 |
|
|
174 |
ComponentDescription cDesc;
|
|
175 |
Handle descH = NewHandle(0);
|
|
176 |
GetComponentInfo(component, &cDesc, 0, descH, 0);
|
|
177 |
HLock(descH);
|
|
178 |
char *descPtr = *descH;
|
|
179 |
int len = *descPtr++;
|
|
180 |
descPtr[len] = 0;
|
|
181 |
QString qsDesc = QString::fromUtf8(descPtr);
|
|
182 |
DisposeHandle(descH);
|
|
183 |
return qsDesc;
|
|
184 |
}
|
|
185 |
|
|
186 |
QList<int> AudioEffect::effectList()
|
|
187 |
{
|
|
188 |
QList<int> effects;
|
|
189 |
|
|
190 |
ComponentDescription d;
|
|
191 |
d.componentType = kAudioUnitType_Effect;
|
|
192 |
d.componentSubType = 0;
|
|
193 |
d.componentManufacturer = 0;
|
|
194 |
d.componentFlags = 0;
|
|
195 |
d.componentFlagsMask = 0;
|
|
196 |
Component component = FindNextComponent(0, &d);
|
|
197 |
|
|
198 |
while (component) {
|
|
199 |
ComponentDescription cDesc;
|
|
200 |
GetComponentInfo(component, &cDesc, 0, 0, 0);
|
|
201 |
effects << cDesc.componentSubType;
|
|
202 |
component = FindNextComponent(component, &d);
|
|
203 |
}
|
|
204 |
return effects;
|
|
205 |
}
|
|
206 |
|
|
207 |
Phonon::EffectParameter AudioEffect::createParameter(const AudioUnit &audioUnit, const AudioUnitParameterID &id) const
|
|
208 |
{
|
|
209 |
AudioUnitParameterInfo info;
|
|
210 |
UInt32 size = sizeof(info);
|
|
211 |
ComponentResult res = AudioUnitGetProperty(audioUnit,
|
|
212 |
kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, id, &info, &size);
|
|
213 |
BACKEND_ASSERT3(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR, Phonon::EffectParameter())
|
|
214 |
|
|
215 |
QString name = info.flags & kAudioUnitParameterFlag_HasCFNameString
|
|
216 |
? PhononCFString::toQString(info.cfNameString) : QLatin1String("<unknown parameter>");
|
|
217 |
|
|
218 |
Phonon::EffectParameter::Hint hint;
|
|
219 |
switch(info.unit){
|
|
220 |
case (kAudioUnitParameterUnit_Indexed):
|
|
221 |
case (kAudioUnitParameterUnit_Seconds):
|
|
222 |
case (kAudioUnitParameterUnit_SampleFrames):
|
|
223 |
case (kAudioUnitParameterUnit_Milliseconds):
|
|
224 |
hint = Phonon::EffectParameter::IntegerHint;
|
|
225 |
break;
|
|
226 |
case (kAudioUnitParameterUnit_Boolean):
|
|
227 |
hint = Phonon::EffectParameter::ToggledHint;
|
|
228 |
break;
|
|
229 |
default:
|
|
230 |
hint = Phonon::EffectParameter::LogarithmicHint;
|
|
231 |
break;
|
|
232 |
}
|
|
233 |
|
|
234 |
QVariant def(info.defaultValue);
|
|
235 |
QVariant min(info.minValue);
|
|
236 |
QVariant max(info.maxValue);
|
|
237 |
return Phonon::EffectParameter(id, name, hint, def, min, max, QVariantList(), name);
|
|
238 |
}
|
|
239 |
|
|
240 |
QVariant AudioEffect::parameterValue(const Phonon::EffectParameter &value) const
|
|
241 |
{
|
|
242 |
return m_audioNode->parameterValue(value);
|
|
243 |
}
|
|
244 |
|
|
245 |
void AudioEffect::setParameterValue(const Phonon::EffectParameter ¶meter, const QVariant &newValue)
|
|
246 |
{
|
|
247 |
m_audioNode->setParameterValue(parameter, newValue);
|
|
248 |
}
|
|
249 |
|
|
250 |
}} //namespace Phonon::QT7
|
|
251 |
|
|
252 |
QT_END_NAMESPACE
|
|
253 |
|
|
254 |
#include "moc_audioeffects.cpp"
|