From bc0e4aa8aec231b43a6033f3f4f12037b02ee64e Mon Sep 17 00:00:00 2001 From: Gareth Stockwell Date: Thu, 10 Dec 2009 17:24:03 +0000 Subject: Implemented reverb effect in Phonon MMF backend Task-number: QTBUG-4659 Reviewed-by: Espen Riskedal --- src/3rdparty/phonon/mmf/effectfactory.cpp | 11 +- src/3rdparty/phonon/mmf/effectparameter.cpp | 8 + src/3rdparty/phonon/mmf/effectparameter.h | 2 + src/3rdparty/phonon/mmf/environmentalreverb.cpp | 202 ++++++++++++++++++++++++ src/3rdparty/phonon/mmf/environmentalreverb.h | 62 ++++++++ src/plugins/phonon/mmf/mmf.pro | 2 + 6 files changed, 285 insertions(+), 2 deletions(-) create mode 100644 src/3rdparty/phonon/mmf/environmentalreverb.cpp create mode 100644 src/3rdparty/phonon/mmf/environmentalreverb.h diff --git a/src/3rdparty/phonon/mmf/effectfactory.cpp b/src/3rdparty/phonon/mmf/effectfactory.cpp index 50d08e7..ef2ddf7 100644 --- a/src/3rdparty/phonon/mmf/effectfactory.cpp +++ b/src/3rdparty/phonon/mmf/effectfactory.cpp @@ -23,6 +23,7 @@ along with this library. If not, see . #include "audioequalizer.h" #include "bassboost.h" +#include "environmentalreverb.h" #include "loudness.h" #include "effectfactory.h" @@ -73,14 +74,19 @@ AbstractAudioEffect *EffectFactory::createAudioEffect(Type type, case TypeAudioEqualizer: effect = new AudioEqualizer(parent, parameters); break; - case TypeDistanceAttenuation: case TypeEnvironmentalReverb: - case TypeListenerOrientation: + effect = new EnvironmentalReverb(parent, parameters); + break; case TypeLoudness: effect = new Loudness(parent, parameters); break; + + // Not implemented + case TypeDistanceAttenuation: + case TypeListenerOrientation: case TypeSourceOrientation: case TypeStereoWidening: + // Fall through default: Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown effect"); } @@ -129,6 +135,7 @@ void EffectFactory::initialize() INITIALIZE_EFFECT(AudioEqualizer) INITIALIZE_EFFECT(BassBoost) + INITIALIZE_EFFECT(EnvironmentalReverb) INITIALIZE_EFFECT(Loudness) m_initialized = true; diff --git a/src/3rdparty/phonon/mmf/effectparameter.cpp b/src/3rdparty/phonon/mmf/effectparameter.cpp index f4287b8..17c1315 100644 --- a/src/3rdparty/phonon/mmf/effectparameter.cpp +++ b/src/3rdparty/phonon/mmf/effectparameter.cpp @@ -59,5 +59,13 @@ qint32 MMF::EffectParameter::toInternalValue(qreal external) const return m_internalRange.first + ((1.0 + external) / 2) * range; } +qreal MMF::EffectParameter::toExternalValue + (qint32 value, qint32 min, qint32 max) +{ + Q_ASSERT_X(max >= min, Q_FUNC_INFO, "Invalid range"); + const qint32 range = max - min; + return range == 0 ? 0.0 : ((2.0 * value - min) / range) - 1.0; +} + QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/effectparameter.h b/src/3rdparty/phonon/mmf/effectparameter.h index 3008159..27cc018 100644 --- a/src/3rdparty/phonon/mmf/effectparameter.h +++ b/src/3rdparty/phonon/mmf/effectparameter.h @@ -57,6 +57,8 @@ public: void setInternalRange(qint32 min, qint32 max); qint32 toInternalValue(qreal external) const; + static qreal toExternalValue(qint32 value, qint32 min, qint32 max); + private: bool m_hasInternalRange; QPair m_internalRange; diff --git a/src/3rdparty/phonon/mmf/environmentalreverb.cpp b/src/3rdparty/phonon/mmf/environmentalreverb.cpp new file mode 100644 index 0000000..2e30ca1 --- /dev/null +++ b/src/3rdparty/phonon/mmf/environmentalreverb.cpp @@ -0,0 +1,202 @@ +/* This file is part of the KDE project. + +Copyright (C) 2009 Nokia Corporation 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 +#include "environmentalreverb.h" + +QT_BEGIN_NAMESPACE + +using namespace Phonon; +using namespace Phonon::MMF; + +/*! \class MMF::EnvironmentalReverb + \internal +*/ + +// Define functions which depend on concrete native effect class name +PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(EnvironmentalReverb) + +enum Parameters +{ + DecayHFRatio, + DecayTime, + Density, + Diffusion, + ReflectionsDelay, + ReflectionsLevel, + ReverbDelay, + ReverbLevel, + RoomHFLevel, + RoomLevel +}; + +EnvironmentalReverb::EnvironmentalReverb(QObject *parent, const QList& parameters) + : AbstractAudioEffect::AbstractAudioEffect(parent, parameters) +{ + +} + +void EnvironmentalReverb::parameterChanged(const EffectParameter ¶m, + const QVariant &value) +{ + const qreal externalLevel = value.toReal(); + const int internalLevel = param.toInternalValue(externalLevel); + + TInt err = 0; + + switch(param.id()) { + case DecayHFRatio: + TRAP(err, concreteEffect()->SetDecayHFRatioL(internalLevel)); + break; + case DecayTime: + TRAP(err, concreteEffect()->SetDecayTimeL(internalLevel)); + break; + case Density: + TRAP(err, concreteEffect()->SetDensityL(internalLevel)); + break; + case Diffusion: + TRAP(err, concreteEffect()->SetDiffusionL(internalLevel)); + break; + case ReflectionsDelay: + TRAP(err, concreteEffect()->SetReflectionsDelayL(internalLevel)); + break; + case ReflectionsLevel: + TRAP(err, concreteEffect()->SetReflectionsLevelL(internalLevel)); + break; + case ReverbDelay: + TRAP(err, concreteEffect()->SetReverbDelayL(internalLevel)); + break; + case ReverbLevel: + TRAP(err, concreteEffect()->SetReverbLevelL(internalLevel)); + break; + case RoomHFLevel: + TRAP(err, concreteEffect()->SetRoomHFLevelL(internalLevel)); + break; + case RoomLevel: + TRAP(err, concreteEffect()->SetRoomLevelL(internalLevel)); + break; + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown parameter"); + } + + // TODO: handle audio effect errors + Q_UNUSED(err); +} + + +//----------------------------------------------------------------------------- +// Static functions +//----------------------------------------------------------------------------- + +const char* EnvironmentalReverb::description() +{ + return "Reverb"; +} + +// Internal helper function +Phonon::MMF::EffectParameter createParameter(int id, const QString &name, + int defaultValue, int minValue, int maxValue, + Phonon::EffectParameter::Hint hint = Phonon::EffectParameter::IntegerHint) +{ + const qreal externalDefaultValue = + Phonon::MMF::EffectParameter::toExternalValue + (defaultValue, minValue, maxValue); + + Phonon::MMF::EffectParameter param(id, name, hint, + /* defaultValue */ QVariant(externalDefaultValue), + /* minimumValue */ QVariant(qreal(-1.0)), + /* maximumValue */ QVariant(qreal(+1.0))); + + param.setInternalRange(minValue, maxValue); + return param; +} + +bool EnvironmentalReverb::getParameters(CMdaAudioOutputStream *stream, + QList& parameters) +{ + bool supported = false; + + QScopedPointer effect; + TRAPD(err, effect.reset(CEnvironmentalReverb::NewL(*stream))); + + if (KErrNone == err) { + supported = true; + + TInt32 min, max; + TUint32 umin, umax; + + // DecayHFRatio + effect->DecayHFRatioRange(umin, umax); + parameters.append(createParameter( + DecayHFRatio, tr("Decay HF ratio (%)"), effect->DecayHFRatio(), + umin, umax)); + + // DecayTime + effect->DecayTimeRange(umin, umax); + parameters.append(createParameter( + DecayTime, tr("Decay time (ms)"), effect->DecayTime(), + umin, umax)); + + // Density + parameters.append(createParameter( + Density, tr("Density (%)"), effect->Density(), 0, 100)); + + // Diffusion + parameters.append(createParameter( + Diffusion, tr("Diffusion (%)"), effect->Diffusion(), 0, 100)); + + // ReflectionsDelay + parameters.append(createParameter( + ReflectionsDelay, tr("Reflections delay (ms)"), + effect->ReflectionsDelay(), 0, effect->ReflectionsDelayMax())); + + // ReflectionsLevel + effect->ReflectionLevelRange(min, max); + parameters.append(createParameter( + ReflectionsLevel, tr("Reflections level (mB)"), + effect->ReflectionsLevel(), + min, max, EffectParameter::LogarithmicHint)); + + // ReverbDelay + parameters.append(createParameter( + ReverbDelay, tr("Reverb delay (ms)"), effect->ReverbDelay(), + 0, effect->ReverbDelayMax())); + + // ReverbLevel + effect->ReverbLevelRange(min, max); + parameters.append(createParameter( + ReverbLevel, tr("Reverb level (mB)"), effect->ReverbLevel(), + min, max, EffectParameter::LogarithmicHint)); + + // RoomHFLevel + effect->RoomHFLevelRange(min, max); + parameters.append(createParameter( + RoomHFLevel, tr("Room HF level"), effect->RoomHFLevel(), + min, max)); + + // RoomLevel + effect->RoomLevelRange(min, max); + parameters.append(createParameter( + RoomLevel, tr("Room level (mB)"), effect->RoomLevel(), + min, max, EffectParameter::LogarithmicHint)); + } + + return supported; +} + +QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/environmentalreverb.h b/src/3rdparty/phonon/mmf/environmentalreverb.h new file mode 100644 index 0000000..5760c0a --- /dev/null +++ b/src/3rdparty/phonon/mmf/environmentalreverb.h @@ -0,0 +1,62 @@ +/* This file is part of the KDE project. + +Copyright (C) 2009 Nokia Corporation 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 . + +*/ + +#ifndef PHONON_MMF_ENVIRONMENTALREVERB_H +#define PHONON_MMF_ENVIRONMENTALREVERB_H + +#include "abstractaudioeffect.h" + +class CEnvironmentalReverb; + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +namespace MMF +{ +/** + * @short A reverb effect. + */ +class EnvironmentalReverb : public AbstractAudioEffect +{ + Q_OBJECT +public: + EnvironmentalReverb(QObject *parent, const QList& parameters); + + // Static interface required by EffectFactory + static const char* description(); + static bool getParameters(CMdaAudioOutputStream *stream, + QList& parameters); + +protected: + // AbstractAudioEffect + virtual void createEffect(AudioPlayer::NativePlayer *player); + virtual void parameterChanged(const EffectParameter ¶m, + const QVariant &value); + +private: + CEnvironmentalReverb *concreteEffect(); + +}; +} +} + +QT_END_NAMESPACE + +#endif + diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro index 37c613c..78e23d9 100644 --- a/src/plugins/phonon/mmf/mmf.pro +++ b/src/plugins/phonon/mmf/mmf.pro @@ -36,6 +36,7 @@ HEADERS += \ $$PHONON_MMF_DIR/dummyplayer.h \ $$PHONON_MMF_DIR/effectfactory.h \ $$PHONON_MMF_DIR/effectparameter.h \ + $$PHONON_MMF_DIR/environmentalreverb.h \ $$PHONON_MMF_DIR/loudness.h \ $$PHONON_MMF_DIR/mediaobject.h \ $$PHONON_MMF_DIR/mmf_medianode.h \ @@ -60,6 +61,7 @@ SOURCES += \ $$PHONON_MMF_DIR/dummyplayer.cpp \ $$PHONON_MMF_DIR/effectfactory.cpp \ $$PHONON_MMF_DIR/effectparameter.cpp \ + $$PHONON_MMF_DIR/environmentalreverb.cpp \ $$PHONON_MMF_DIR/loudness.cpp \ $$PHONON_MMF_DIR/mediaobject.cpp \ $$PHONON_MMF_DIR/mmf_medianode.cpp \ -- cgit v0.12