Add AudioEngine with new implementation
Change-Id: I5eebe662ecbce9814ed3e763db56df9be737d11f Reviewed-by: Michael Goddard <michael.goddard@nokia.com>
This commit is contained in:
560
src/imports/audioengine/qdeclarative_soundinstance_p.cpp
Normal file
560
src/imports/audioengine/qdeclarative_soundinstance_p.cpp
Normal 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
|
||||
*/
|
||||
Reference in New Issue
Block a user