| 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"
|
|---|