Add AudioEngine with new implementation

Change-Id: I5eebe662ecbce9814ed3e763db56df9be737d11f
Reviewed-by: Michael Goddard <michael.goddard@nokia.com>
This commit is contained in:
Ling Hu
2012-01-18 17:17:54 +10:00
committed by Qt by Nokia
parent 262f397e3e
commit 809bbc35c6
39 changed files with 6592 additions and 6 deletions

View File

@@ -0,0 +1,560 @@
/****************************************************************************
**
** 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 "qdeclarative_soundinstance_p.h"
#include "qdeclarative_sound_p.h"
#include "qdeclarative_audioengine_p.h"
#include "qaudioengine_p.h"
#include "qsoundinstance_p.h"
#include "qdebug.h"
#define DEBUG_AUDIOENGINE
QT_USE_NAMESPACE
/*!
\qmlclass SoundInstance QDeclarativeSoundInstance
\since 5.0
\brief The SoundInstance element allows you to play 3d audio content.
\ingroup qml-multimedia
\inherits Item
This element is part of the \bold{QtAudioEngine 1.0} module.
There are two ways to create SoundInstance objects. You can obtain it by calling newInstance
method of Sound element:
\qml
import QtQuick 2.0
import QtAudioEngine 1.0
Rectangle {
id:root
color:"white"
width: 300
height: 500
AudioEngine {
id:audioengine
AudioSample {
name:"explosion01"
source: "explosion-01.wav"
}
Sound {
name:"explosion"
PlayVariation {
sample:"explosion01"
}
}
}
property variant soundEffect: audioengine.sounds["explosion"].newInstance();
MouseArea {
anchors.fill: parent
onPressed: {
root.soundEffect.play();
}
}
}
\endqml
Or alternatively, you can explicitly define SoundInstance element outside of AudioEngine for
easier qml bindings:
\qml
import QtQuick 2.0
import QtAudioEngine 1.0
Rectangle {
id:root
color:"white"
width: 300
height: 500
AudioEngine {
id:audioengine
AudioSample {
name:"explosion01"
source: "explosion-01.wav"
}
Sound {
name:"explosion"
PlayVariation {
sample:"explosion01"
}
}
}
Item {
id: animator
x: 10 + observer.percent * 100
y: 20 + observer.percent * 80
property real percent: 0
SequentialAnimation on percent {
loops: Animation.Infinite
running: true
NumberAnimation {
duration: 8000
from: 0
to: 1
}
}
}
SoundInstance {
id:soundEffect
engine:audioengine
sound:"explosion"
position:Qt.vector3d(animator.x, animator.y, 0);
}
MouseArea {
anchors.fill: parent
onPressed: {
soundEffect.play();
}
}
}
\endqml
*/
QDeclarativeSoundInstance::QDeclarativeSoundInstance(QObject *parent)
: QObject(parent)
, m_position(0, 0, 0)
, m_direction(0, 1, 0)
, m_velocity(0, 0, 0)
, m_gain(1)
, m_pitch(1)
, m_requestState(QDeclarativeSoundInstance::StopppedState)
, m_coneInnerAngle(360)
, m_coneOuterAngle(360)
, m_coneOuterGain(0)
, m_instance(0)
, m_engine(0)
{
#ifdef DEBUG_AUDIOENGINE
qDebug() << "QDeclarativeSoundInstance::ctor()";
#endif
}
/*!
\qmlproperty AudioEngine SoundInstance::engine
This property holds the reference to AudioEngine, must be set only once.
*/
QDeclarativeAudioEngine* QDeclarativeSoundInstance::engine() const
{
return m_engine;
}
void QDeclarativeSoundInstance::setEngine(QDeclarativeAudioEngine *engine)
{
#ifdef DEBUG_AUDIOENGINE
qDebug() << "QDeclarativeSoundInstance::setEngine(" << engine << ")";
#endif
if (!engine)
return;
if (m_engine) {
qWarning("SoundInstance: you can not set different value for engine property");
return;
}
m_engine = engine;
if (!m_engine->isReady()) {
connect(m_engine, SIGNAL(ready()), this, SLOT(engineComplete()));
} else {
engineComplete();
}
}
void QDeclarativeSoundInstance::engineComplete()
{
#ifdef DEBUG_AUDIOENGINE
qDebug() << "QDeclarativeSoundInstance::engineComplete()";
#endif
disconnect(m_engine, SIGNAL(ready()), this, SLOT(engineComplete()));
if (m_sound.isEmpty())
return;
//rebind to actual engine resource
QString sound = m_sound;
m_sound.clear();
setSound(sound);
}
QDeclarativeSoundInstance::~QDeclarativeSoundInstance()
{
}
/*!
\qmlproperty string SoundInstance::sound
This property specifies which Sound this SoundInstance will use. Unlike some properties in
other elements, this property can be changed dynamically.
*/
QString QDeclarativeSoundInstance::sound() const
{
return m_sound;
}
void QDeclarativeSoundInstance::setSound(const QString& sound)
{
#ifdef DEBUG_AUDIOENGINE
qDebug() << "QDeclarativeSoundInstance::setSound(" << sound << ")";
#endif
if (m_sound == sound)
return;
if (!m_engine || !m_engine->isReady()) {
m_sound = sound;
emit soundChanged();
return;
}
#ifdef DEBUG_AUDIOENGINE
qDebug() << "SoundInstance Element switch sound from [" << m_sound << "] to [" << sound << "]";
#endif
stop();
dropInstance();
m_sound = sound;
if (!m_sound.isEmpty()) {
m_instance = m_engine->newSoundInstance(m_sound);
connect(m_instance, SIGNAL(stateChanged(QSoundInstance::State)), this, SLOT(handleStateChanged()));
m_instance->setPosition(m_position);
m_instance->setDirection(m_direction);
m_instance->setVelocity(m_velocity);
m_instance->setGain(m_gain);
m_instance->setPitch(m_pitch);
m_instance->setCone(m_coneInnerAngle, m_coneOuterAngle, m_coneOuterGain);
if (m_requestState == QDeclarativeSoundInstance::PlayingState) {
m_instance->play();
} else if (m_requestState == QDeclarativeSoundInstance::PausedState) {
m_instance->pause();
}
}
emit soundChanged();
}
void QDeclarativeSoundInstance::dropInstance()
{
if (m_instance) {
disconnect(m_instance, SIGNAL(stateChanged(QSoundInstance::State)), this, SLOT(handleStateChanged()));
m_engine->releaseSoundInstance(m_instance);
m_instance = 0;
}
}
/*!
\qmlproperty enumeration SoundInstance::state
This property holds the current playback state. It can be one of:
\list
\o StopppedState
\o PlayingState
\o PausedState
\endlist
*/
QDeclarativeSoundInstance::State QDeclarativeSoundInstance::state() const
{
if (m_instance)
return State(m_instance->state());
return m_requestState;
}
/*!
\qmlmethod SoundInstance::play()
Starts playback.
*/
void QDeclarativeSoundInstance::play()
{
#ifdef DEBUG_AUDIOENGINE
qDebug() << "QDeclarativeSoundInstance::play()";
#endif
if (!m_instance) {
m_requestState = QDeclarativeSoundInstance::PlayingState;
return;
}
m_instance->play();
}
/*!
\qmlmethod SoundInstance::play()
Stops current playback.
*/
void QDeclarativeSoundInstance::stop()
{
#ifdef DEBUG_AUDIOENGINE
qDebug() << "QDeclarativeSoundInstance::stop()";
#endif
m_requestState = QDeclarativeSoundInstance::StopppedState;
if (!m_instance)
return;
m_instance->stop();
}
/*!
\qmlmethod SoundInstance::play()
Pauses current playback.
*/
void QDeclarativeSoundInstance::pause()
{
#ifdef DEBUG_AUDIOENGINE
qDebug() << "QDeclarativeSoundInstance::pause()";
#endif
if (!m_instance) {
m_requestState = QDeclarativeSoundInstance::PausedState;
return;
}
m_instance->pause();
}
void QDeclarativeSoundInstance::updatePosition(qreal deltaTime)
{
if (!m_instance || deltaTime == 0 || m_velocity.lengthSquared() == 0)
return;
setPosition(m_position + m_velocity * deltaTime);
}
/*!
\qmlproperty vector3d SoundInstance::position
This property holds the current 3d position.
*/
QVector3D QDeclarativeSoundInstance::position() const
{
return m_position;
}
void QDeclarativeSoundInstance::setPosition(const QVector3D& position)
{
if (m_position == position)
return;
m_position = position;
emit positionChanged();
if (!m_instance) {
return;
}
m_instance->setPosition(m_position);
}
/*!
\qmlproperty vector3d SoundInstance::direction
This property holds the current 3d direction.
*/
QVector3D QDeclarativeSoundInstance::direction() const
{
return m_direction;
}
void QDeclarativeSoundInstance::setDirection(const QVector3D& direction)
{
if (m_direction == direction)
return;
m_direction = direction;
emit directionChanged();
if (!m_instance) {
return;
}
m_instance->setDirection(m_direction);
}
/*!
\qmlproperty vector3d SoundInstance::velocity
This property holds the current 3d velocity.
*/
QVector3D QDeclarativeSoundInstance::velocity() const
{
return m_velocity;
}
void QDeclarativeSoundInstance::setVelocity(const QVector3D& velocity)
{
if (m_velocity == velocity)
return;
m_velocity = velocity;
emit velocityChanged();
if (!m_instance)
return;
m_instance->setVelocity(m_velocity);
}
/*!
\qmlproperty vector3d SoundInstance::gain
This property holds the gain adjustment which will be used to modulate the audio ouput level
from this SoundInstance.
*/
qreal QDeclarativeSoundInstance::gain() const
{
return m_gain;
}
void QDeclarativeSoundInstance::setGain(qreal gain)
{
if (gain == m_gain)
return;
if (gain < 0) {
qWarning("gain must be a positive value!");
return;
}
m_gain = gain;
emit gainChanged();
if (!m_instance)
return;
m_instance->setGain(m_gain);
}
/*!
\qmlproperty vector3d SoundInstance::gain
This property holds the pitch adjustment which will be used to modulate the audio pitch
from this SoundInstance.
*/
qreal QDeclarativeSoundInstance::pitch() const
{
return m_pitch;
}
void QDeclarativeSoundInstance::setPitch(qreal pitch)
{
if (pitch == m_pitch)
return;
if (pitch < 0) {
qWarning("pitch must be a positive value!");
return;
}
m_pitch = pitch;
emit pitchChanged();
if (!m_instance)
return;
m_instance->setPitch(m_pitch);
}
void QDeclarativeSoundInstance::setConeInnerAngle(qreal innerAngle)
{
if (m_coneInnerAngle == innerAngle)
return;
m_coneInnerAngle = innerAngle;
if (!m_instance)
return;
m_instance->setCone(m_coneInnerAngle, m_coneOuterAngle, m_coneOuterGain);
}
void QDeclarativeSoundInstance::setConeOuterAngle(qreal outerAngle)
{
if (m_coneOuterAngle == outerAngle)
return;
m_coneOuterAngle = outerAngle;
if (!m_instance)
return;
m_instance->setCone(m_coneInnerAngle, m_coneOuterAngle, m_coneOuterGain);
}
void QDeclarativeSoundInstance::setConeOuterGain(qreal outerGain)
{
if (m_coneOuterGain == outerGain)
return;
m_coneOuterGain = outerGain;
if (!m_instance)
return;
m_instance->setCone(m_coneInnerAngle, m_coneOuterAngle, m_coneOuterGain);
}
void QDeclarativeSoundInstance::handleStateChanged()
{
emit stateChanged();
}
/*!
\qmlsignal SoundInstance::onStateChanged(state)
This handler is called when \l state is changed
*/
/*!
\qmlsignal SoundInstance::onPositionChanged()
This handler is called when \l position is changed
*/
/*!
\qmlsignal SoundInstance::onDirectionChanged()
This handler is called when \l direction is changed
*/
/*!
\qmlsignal SoundInstance::onVelocityChanged()
This handler is called when \l velocity is changed
*/
/*!
\qmlsignal SoundInstance::onGainChanged()
This handler is called when \l gain is changed
*/
/*!
\qmlsignal SoundInstance::onPitchChanged()
This handler is called when \l pitch is changed
*/
/*!
\qmlsignal SoundInstance::onSoundChanged()
This handler is called when \l sound is changed
*/