diff options
Diffstat (limited to 'src/imports/audioengine/qsoundinstance_p.cpp')
-rw-r--r-- | src/imports/audioengine/qsoundinstance_p.cpp | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/src/imports/audioengine/qsoundinstance_p.cpp b/src/imports/audioengine/qsoundinstance_p.cpp new file mode 100644 index 000000000..9c5fc7ad9 --- /dev/null +++ b/src/imports/audioengine/qsoundinstance_p.cpp @@ -0,0 +1,387 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsoundinstance_p.h" +#include "qsoundsource_p.h" +#include "qsoundbuffer_p.h" +#include "qdeclarative_sound_p.h" +#include "qdeclarative_audiocategory_p.h" +#include "qdeclarative_audiosample_p.h" +#include "qdeclarative_attenuationmodel_p.h" +#include "qdeclarative_playvariation_p.h" +#include "qdeclarative_audioengine_p.h" +#include "qdeclarative_audiolistener_p.h" + +#include "qdebug.h" + +#define DEBUG_AUDIOENGINE + +QT_USE_NAMESPACE + +QSoundInstance::QSoundInstance(QObject *parent) + : QObject(parent) + , m_soundSource(0) + , m_bindBuffer(0) + , m_sound(0) + , m_variationIndex(-1) + , m_isReady(false) + , m_gain(1) + , m_attenuationGain(1) + , m_varGain(1) + , m_pitch(1) + , m_varPitch(1) + , m_state(QSoundInstance::StopppedState) + , m_coneOuterGain(0) + , m_engine(0) +{ +#ifdef DEBUG_AUDIOENGINE + qDebug() << "creating new QSoundInstance"; +#endif + m_engine = qobject_cast<QDeclarativeAudioEngine*>(parent); +} + +void QSoundInstance::bindSoundDescription(QDeclarativeSound *sound) +{ +#ifdef DEBUG_AUDIOENGINE + qDebug() << "QSoundInstance::bindSoundDescription" << sound; +#endif + if (m_sound == sound) + return; + + if (m_sound && m_sound->categoryObject()) { + disconnect(m_sound->categoryObject(), SIGNAL(volumeChanged(qreal)), this, SLOT(categoryVolumeChanged())); + disconnect(m_sound->categoryObject(), SIGNAL(paused()), this, SLOT(pause())); + disconnect(m_sound->categoryObject(), SIGNAL(stopped()), this, SLOT(stop())); + disconnect(m_sound->categoryObject(), SIGNAL(resumed()), this, SLOT(resume())); + } + m_attenuationGain = 1; + m_gain = 1; + + m_sound = sound; + + if (sound) { + if (!m_soundSource) { + m_soundSource = m_engine->engine()->createSoundSource(); + connect(m_soundSource, SIGNAL(stateChanged(QSoundSource::State)), + this, SLOT(handleSourceStateChanged(QSoundSource::State))); + } + } else { + if (m_soundSource) { + detach(); + m_engine->engine()->releaseSoundSource(m_soundSource); + m_soundSource = 0; + } + } + + if (m_sound) { + if (m_sound->categoryObject()) { + connect(m_sound->categoryObject(), SIGNAL(volumeChanged(qreal)), this, SLOT(categoryVolumeChanged())); + connect(m_sound->categoryObject(), SIGNAL(paused()), this, SLOT(pause())); + connect(m_sound->categoryObject(), SIGNAL(stopped()), this, SLOT(stop())); + connect(m_sound->categoryObject(), SIGNAL(resumed()), this, SLOT(resume())); + } + prepareNewVariation(); + } else { + m_variationIndex = -1; + } +} + +QSoundInstance::~QSoundInstance() +{ +#ifdef DEBUG_AUDIOENGINE + qDebug() << "QSoundInstance::dtor()"; +#endif + if (m_soundSource) { + detach(); + m_engine->engine()->releaseSoundSource(m_soundSource); + } +} + +void QSoundInstance::prepareNewVariation() +{ +#ifdef DEBUG_AUDIOENGINE + qDebug() << "QSoundInstance::prepareNewVariation()"; +#endif + int newVariationIndex = m_sound->genVariationIndex(m_variationIndex); + if (newVariationIndex == m_variationIndex) + return; + QDeclarativePlayVariation *playVar = m_sound->getVariation(newVariationIndex); +#ifdef DEBUG_AUDIOENGINE + qDebug() << "QSoundInstance: generate new play variation [old:" << m_variationIndex << ", new:" << newVariationIndex << "-" << playVar->sample() << "]"; +#endif + m_variationIndex = newVariationIndex; + playVar->applyParameters(this); + detach(); + + m_bindBuffer = playVar->sampleObject()->soundBuffer(); + if (m_bindBuffer->isReady()) { + Q_ASSERT(m_soundSource); + m_soundSource->bindBuffer(m_bindBuffer); + m_isReady = true; + } else { + m_bindBuffer->load(); + connect(m_bindBuffer, SIGNAL(ready()), this, SLOT(bufferReady())); + } +} + +void QSoundInstance::bufferReady() +{ +#ifdef DEBUG_AUDIOENGINE + qDebug() << "QSoundInstance::bufferReady()"; +#endif + if (!m_soundSource) + return; + m_soundSource->bindBuffer(m_bindBuffer); + disconnect(m_bindBuffer, SIGNAL(ready()), this, SLOT(bufferReady())); + m_isReady = true; + + if (m_state == QSoundInstance::PlayingState) { + sourcePlay(); + } else if (m_state == QSoundInstance::PausedState) { + sourcePause(); + } +} + +void QSoundInstance::categoryVolumeChanged() +{ + updateGain(); +} + +void QSoundInstance::handleSourceStateChanged(QSoundSource::State newState) +{ + State ns = State(newState); + if (ns == m_state) + return; + if (ns == QSoundInstance::StopppedState) { + prepareNewVariation(); + } + setState(ns); +} + +void QSoundInstance::setState(State state) +{ + if (state == m_state) + return; + m_state = state; + emit stateChanged(m_state); +} + +qreal QSoundInstance::categoryVolume() const +{ + if (!m_sound) + return 1; + if (!m_sound->categoryObject()) + return 1; + return m_sound->categoryObject()->volume(); +} + +void QSoundInstance::sourceStop() +{ + Q_ASSERT(m_soundSource); + m_soundSource->stop(); + setState(QSoundInstance::StopppedState); +} + +void QSoundInstance::detach() +{ + sourceStop(); + m_isReady = false; + if (m_soundSource) + m_soundSource->unbindBuffer(); + if (m_bindBuffer) { + disconnect(m_bindBuffer, SIGNAL(ready()), this, SLOT(bufferReady())); + m_engine->engine()->releaseSoundBuffer(m_bindBuffer); + m_bindBuffer = 0; + } +} + +void QSoundInstance::play() +{ +#ifdef DEBUG_AUDIOENGINE + qDebug() << "QSoundInstancePrivate::play()"; +#endif + if (!m_soundSource || m_state == QSoundInstance::PlayingState) + return; + if (!m_isReady) { + setState(QSoundInstance::PlayingState); + return; + } + sourcePlay(); + setState(QSoundInstance::PlayingState); +} + +void QSoundInstance::sourcePlay() +{ + update3DVolume(m_engine->listener()->position()); + Q_ASSERT(m_soundSource); + m_soundSource->play(); +} + +void QSoundInstance::resume() +{ +#ifdef DEBUG_AUDIOENGINE + qDebug() << "QSoundInstancePrivate::resume()"; +#endif + if (m_state != QSoundInstance::PausedState) + return; + play(); +} + +void QSoundInstance::pause() +{ + if (!m_soundSource || m_state == QSoundInstance::PausedState) + return; + if (!m_isReady) { + setState(QSoundInstance::PausedState); + return; + } + sourcePause(); + setState(QSoundInstance::PausedState); +} + +void QSoundInstance::sourcePause() +{ + Q_ASSERT(m_soundSource); + m_soundSource->pause(); +} + +void QSoundInstance::stop() +{ + if (!m_isReady || !m_soundSource || m_state == QSoundInstance::StopppedState) { + setState(QSoundInstance::StopppedState); + return; + } + sourceStop(); + prepareNewVariation(); +} + +QSoundInstance::State QSoundInstance::state() const +{ + return m_state; +} + +void QSoundInstance::setPosition(const QVector3D& position) +{ + if (!m_soundSource) + return; + m_soundSource->setPosition(position); +} + +void QSoundInstance::setDirection(const QVector3D& direction) +{ + if (!m_soundSource) + return; + m_soundSource->setDirection(direction); +} + +void QSoundInstance::setVelocity(const QVector3D& velocity) +{ + if (!m_soundSource) + return; + m_soundSource->setVelocity(velocity); +} + +void QSoundInstance::setGain(qreal gain) +{ + if (!m_soundSource) + return; + m_gain = gain; + updateGain(); +} + +void QSoundInstance::setPitch(qreal pitch) +{ + if (!m_soundSource) + return; + m_pitch = pitch; + updatePitch(); +} + +void QSoundInstance::setCone(qreal innerAngle, qreal outerAngle, qreal outerGain) +{ + if (!m_soundSource) + return; + m_soundSource->setCone(innerAngle, outerAngle, outerGain); +} + +bool QSoundInstance::attenuationEnabled() const +{ + if (!m_sound || !m_sound->attenuationModelObject()) + return false; + return true; +} + +void QSoundInstance::update3DVolume(const QVector3D& listenerPosition) +{ + if (!m_sound || !m_soundSource) + return; + QDeclarativeAttenuationModel *attenModel = m_sound->attenuationModelObject(); + if (!attenModel) + return; + m_attenuationGain = attenModel->calculateGain(listenerPosition, m_soundSource->position()); + updateGain(); +} + +void QSoundInstance::updateVariationParameters(qreal varPitch, qreal varGain, bool looping) +{ + if (!m_soundSource) + return; + m_soundSource->setLooping(looping); +#ifdef DEBUG_AUDIOENGINE + qDebug() << "QSoundInstance::updateVariationParameters" << varPitch << varGain << looping; +#endif + m_varPitch = varPitch; + m_varGain = varGain; + updatePitch(); + updateGain(); +} + +void QSoundInstance::updatePitch() +{ + m_soundSource->setPitch(m_pitch * m_varPitch); +} + +void QSoundInstance::updateGain() +{ + m_soundSource->setGain(m_gain * m_varGain * m_attenuationGain * categoryVolume()); +} + +QT_END_NAMESPACE |