/* This file is part of the KDE project. Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). This library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 or 3 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "audioeffects.h" QT_BEGIN_NAMESPACE namespace Phonon { namespace QT7 { AudioEffectAudioNode::AudioEffectAudioNode(int effectType) : AudioNode(1, 1), m_effectType(effectType) { } ComponentDescription AudioEffectAudioNode::getAudioNodeDescription() const { ComponentDescription d; d.componentType = kAudioUnitType_Effect; d.componentSubType = m_effectType; d.componentManufacturer = kAudioUnitManufacturer_Apple; d.componentFlags = 0; d.componentFlagsMask = 0; return d; } void AudioEffectAudioNode::initializeAudioUnit() { if (!m_audioUnit) return; foreach(int id, m_alteredParameters.keys()){ Float32 value = m_alteredParameters.value(id); ComponentResult res = AudioUnitSetParameter(m_audioUnit, id, kAudioUnitScope_Global, 0, value, 0); BACKEND_ASSERT2(res == noErr, "Could not initialize audio effect.", NORMAL_ERROR) } } QVariant AudioEffectAudioNode::parameterValue(const Phonon::EffectParameter ¶meter) const { if (m_audioUnit){ Float32 value = 0; AudioUnitGetParameter(m_audioUnit, parameter.id(), kAudioUnitScope_Global, 0, &value); return QVariant(value); } else if (m_alteredParameters.contains(parameter.id())){ return QVariant(m_alteredParameters.value(parameter.id())); } else { // Use default value: AudioUnit tmpAudioUnit; ComponentDescription description = getAudioNodeDescription(); Component component = FindNextComponent(0, &description); BACKEND_ASSERT3(component, "Could not get parameters of audio effect.", NORMAL_ERROR, QVariant()) OSErr err = OpenAComponent(component, &tmpAudioUnit); BACKEND_ASSERT3(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR, QVariant()) AudioUnitParameterInfo info; UInt32 size = sizeof(info); ComponentResult res = AudioUnitGetProperty(tmpAudioUnit, kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameter.id(), &info, &size); BACKEND_ASSERT3(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR, QVariant()) return QVariant(info.defaultValue); } } void AudioEffectAudioNode::setParameterValue(const Phonon::EffectParameter ¶meter, const QVariant &newValue) { Float32 value = 0; if (newValue.isValid()){ value = newValue.toDouble(); m_alteredParameters.insert(parameter.id(), value); } else { // Use default value: m_alteredParameters.remove(parameter.id()); if (m_audioUnit){ AudioUnit tmpAudioUnit; ComponentDescription description = getAudioNodeDescription(); Component component = FindNextComponent(0, &description); BACKEND_ASSERT2(component, "Could not get parameters of audio effect.", NORMAL_ERROR) OSErr err = OpenAComponent(component, &tmpAudioUnit); BACKEND_ASSERT2(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR) AudioUnitParameterInfo info; UInt32 size = sizeof(info); ComponentResult res = AudioUnitGetProperty(tmpAudioUnit, kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, parameter.id(), &info, &size); BACKEND_ASSERT2(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR) value = info.defaultValue; } } if (m_audioUnit){ ComponentResult res = AudioUnitSetParameter(m_audioUnit, parameter.id(), kAudioUnitScope_Global, 0, value, 0); BACKEND_ASSERT2(res == noErr, "Could not set effect parameter value.", NORMAL_ERROR) } } /////////////////////////////////////////////////////////////////////// AudioEffect::AudioEffect(int effectType, QObject *parent) : MediaNode(AudioSink | AudioSource, 0, parent) { m_audioNode = new AudioEffectAudioNode(effectType); setAudioNode(m_audioNode); } QList AudioEffect::parameters() const { QList effectList; // Create a temporary audio unit: AudioUnit audioUnit; ComponentDescription description = m_audioNode->getAudioNodeDescription(); Component component = FindNextComponent(0, &description); BACKEND_ASSERT3(component, "Could not get parameters of audio effect.", NORMAL_ERROR, effectList) OSErr err = OpenAComponent(component, &audioUnit); BACKEND_ASSERT3(err == noErr, "Could not get parameters of audio effect.", NORMAL_ERROR, effectList) UInt32 size = 0; // Get parameter count: ComponentResult res = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, 0, &size); BACKEND_ASSERT3(res == noErr, "Could not get parameter count from audio effect.", NORMAL_ERROR, effectList) int paramCount = size / sizeof(AudioUnitParameterID); // Get parameters: AudioUnitParameterID parameters[paramCount]; res = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, 0, ¶meters, &size); BACKEND_ASSERT3(res == noErr, "Could not get parameter list from audio effect.", NORMAL_ERROR, effectList) for (int i=0; igetAudioNodeDescription(); Component component = FindNextComponent(0, &description); BACKEND_ASSERT3(component, "Could not get audio effect name.", NORMAL_ERROR, QLatin1String("")) ComponentDescription cDesc; Handle nameH = NewHandle(0); GetComponentInfo(component, &cDesc, nameH, 0, 0); HLock(nameH); char *namePtr = *nameH; int len = *namePtr++; namePtr[len] = 0; QString qsName = QString::fromUtf8(namePtr); DisposeHandle(nameH); return qsName; } QString AudioEffect::description() { ComponentDescription description = m_audioNode->getAudioNodeDescription(); Component component = FindNextComponent(0, &description); BACKEND_ASSERT3(component, "Could not get audio effect description.", NORMAL_ERROR, QLatin1String("")) ComponentDescription cDesc; Handle descH = NewHandle(0); GetComponentInfo(component, &cDesc, 0, descH, 0); HLock(descH); char *descPtr = *descH; int len = *descPtr++; descPtr[len] = 0; QString qsDesc = QString::fromUtf8(descPtr); DisposeHandle(descH); return qsDesc; } QList AudioEffect::effectList() { QList effects; ComponentDescription d; d.componentType = kAudioUnitType_Effect; d.componentSubType = 0; d.componentManufacturer = 0; d.componentFlags = 0; d.componentFlagsMask = 0; Component component = FindNextComponent(0, &d); while (component) { ComponentDescription cDesc; GetComponentInfo(component, &cDesc, 0, 0, 0); effects << cDesc.componentSubType; component = FindNextComponent(component, &d); } return effects; } Phonon::EffectParameter AudioEffect::createParameter(const AudioUnit &audioUnit, const AudioUnitParameterID &id) const { AudioUnitParameterInfo info; UInt32 size = sizeof(info); ComponentResult res = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_ParameterInfo, kAudioUnitScope_Global, id, &info, &size); BACKEND_ASSERT3(res == noErr, "Could not get parameter info from audio effect.", NORMAL_ERROR, Phonon::EffectParameter()) QString name = info.flags & kAudioUnitParameterFlag_HasCFNameString ? PhononCFString::toQString(info.cfNameString) : QLatin1String(""); Phonon::EffectParameter::Hint hint; switch(info.unit){ case (kAudioUnitParameterUnit_Indexed): case (kAudioUnitParameterUnit_Seconds): case (kAudioUnitParameterUnit_SampleFrames): case (kAudioUnitParameterUnit_Milliseconds): hint = Phonon::EffectParameter::IntegerHint; break; case (kAudioUnitParameterUnit_Boolean): hint = Phonon::EffectParameter::ToggledHint; break; default: hint = Phonon::EffectParameter::LogarithmicHint; break; } QVariant def(info.defaultValue); QVariant min(info.minValue); QVariant max(info.maxValue); return Phonon::EffectParameter(id, name, hint, def, min, max, QVariantList(), name); } QVariant AudioEffect::parameterValue(const Phonon::EffectParameter &value) const { return m_audioNode->parameterValue(value); } void AudioEffect::setParameterValue(const Phonon::EffectParameter ¶meter, const QVariant &newValue) { m_audioNode->setParameterValue(parameter, newValue); } }} //namespace Phonon::QT7 QT_END_NAMESPACE #include "moc_audioeffects.cpp"