copy the remaining files from trunk

This commit is contained in:
Campbell Barton 2011-09-01 07:51:20 +00:00
parent cc88eebd37
commit 5095a36d2e
5 changed files with 1169 additions and 0 deletions

@ -0,0 +1,181 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* Copyright 2009-2011 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* Audaspace is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Audaspace; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file audaspace/intern/AUD_IHandle.h
* \ingroup audaspaceintern
*/
#ifndef AUD_IHANDLE
#define AUD_IHANDLE
//#include "AUD_Space.h"
//#include "AUD_Reference.h"
typedef void (*stopCallback)(void*);
/**
* This class represents a playback handles for specific devices.
*/
class AUD_IHandle
{
public:
/**
* Destroys the handle.
*/
virtual ~AUD_IHandle() {}
/**
* Pauses a played back sound.
* \return
* - true if the sound has been paused.
* - false if the sound isn't playing back or the handle is invalid.
*/
virtual bool pause()=0;
/**
* Resumes a paused sound.
* \return
* - true if the sound has been resumed.
* - false if the sound isn't paused or the handle is invalid.
*/
virtual bool resume()=0;
/**
* Stops a played back or paused sound. The handle is definitely invalid
* afterwards.
* \return
* - true if the sound has been stopped.
* - false if the handle is invalid.
*/
virtual bool stop()=0;
/**
* Gets the behaviour of the device for a played back sound when the sound
* doesn't return any more samples.
* \return
* - true if the source will be paused when it's end is reached
* - false if the handle won't kept or is invalid.
*/
virtual bool getKeep()=0;
/**
* Sets the behaviour of the device for a played back sound when the sound
* doesn't return any more samples.
* \param keep True when the source should be paused and not deleted.
* \return
* - true if the behaviour has been changed.
* - false if the handle is invalid.
*/
virtual bool setKeep(bool keep)=0;
/**
* Seeks in a played back sound.
* \param position The new position from where to play back, in seconds.
* \return
* - true if the handle is valid.
* - false if the handle is invalid.
* \warning Whether the seek works or not depends on the sound source.
*/
virtual bool seek(float position)=0;
/**
* Retrieves the current playback position of a sound.
* \return The playback position in seconds, or 0.0 if the handle is
* invalid.
*/
virtual float getPosition()=0;
/**
* Returns the status of a played back sound.
* \return
* - AUD_STATUS_INVALID if the sound has stopped or the handle is
*. invalid
* - AUD_STATUS_PLAYING if the sound is currently played back.
* - AUD_STATUS_PAUSED if the sound is currently paused.
* \see AUD_Status
*/
virtual AUD_Status getStatus()=0;
/**
* Retrieves the volume of a playing sound.
* \return The volume.
*/
virtual float getVolume()=0;
/**
* Sets the volume of a playing sound.
* \param volume The volume.
* \return
* - true if the handle is valid.
* - false if the handle is invalid.
*/
virtual bool setVolume(float volume)=0;
/**
* Retrieves the pitch of a playing sound.
* \return The pitch.
*/
virtual float getPitch()=0;
/**
* Sets the pitch of a playing sound.
* \param pitch The pitch.
* \return
* - true if the handle is valid.
* - false if the handle is invalid.
*/
virtual bool setPitch(float pitch)=0;
/**
* Retrieves the loop count of a playing sound.
* A negative value indicates infinity.
* \return The remaining loop count.
*/
virtual int getLoopCount()=0;
/**
* Sets the loop count of a playing sound.
* A negative value indicates infinity.
* \param count The new loop count.
* \return
* - true if the handle is valid.
* - false if the handle is invalid.
*/
virtual bool setLoopCount(int count)=0;
/**
* Sets the callback function that's called when the end of a playing sound
* is reached.
* \param callback The callback function.
* \param data The data that should be passed to the callback function.
* \return
* - true if the handle is valid.
* - false if the handle is invalid.
*/
virtual bool setStopCallback(stopCallback callback = 0, void* data = 0)=0;
};
#endif //AUD_IHandle

@ -0,0 +1,58 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* Copyright 2009-2011 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* Audaspace is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Audaspace; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file audaspace/intern/AUD_JOSResampleFactory.h
* \ingroup audaspaceintern
*/
#ifndef AUD_JOSRESAMPLEFACTORY
#define AUD_JOSRESAMPLEFACTORY
#include "AUD_MixerFactory.h"
/**
* This factory creates a resampling reader that does Julius O. Smith's resampling algorithm.
*/
class AUD_JOSResampleFactory : public AUD_MixerFactory
{
private:
// hide copy constructor and operator=
AUD_JOSResampleFactory(const AUD_JOSResampleFactory&);
AUD_JOSResampleFactory& operator=(const AUD_JOSResampleFactory&);
public:
/**
* Creates a new factory.
* \param factory The input factory.
* \param specs The target specifications.
*/
AUD_JOSResampleFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs);
virtual AUD_Reference<AUD_IReader> createReader();
};
#endif //AUD_JOSRESAMPLEFACTORY

@ -0,0 +1,420 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* Copyright 2009-2011 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* Audaspace is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Audaspace; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file audaspace/intern/AUD_JOSResampleReader.cpp
* \ingroup audaspaceintern
*/
#include "AUD_JOSResampleReader.h"
#include "AUD_JOSResampleReaderCoeff.cpp"
#include <cmath>
#include <cstring>
#include <iostream>
/* MSVC does not have lrint */
#ifdef _MSC_VER
#ifdef _M_X64
#include <emmintrin.h>
static inline int lrint(double d)
{
return _mm_cvtsd_si32(_mm_load_sd(&d));
}
#else
static inline int lrint(double d)
{
int i;
_asm{
fld d
fistp i
};
return i;
}
#endif
#endif
#define CC m_channels + channel
#define AUD_RATE_MAX 256
#define SHIFT_BITS 12
#define double_to_fp(x) (lrint(x * double(1 << SHIFT_BITS)))
#define int_to_fp(x) (x << SHIFT_BITS)
#define fp_to_int(x) (x >> SHIFT_BITS)
#define fp_to_double(x) (x * 1.0/(1 << SHIFT_BITS))
#define fp_rest(x) (x & ((1 << SHIFT_BITS) - 1))
#define fp_rest_to_double(x) fp_to_double(fp_rest(x))
AUD_JOSResampleReader::AUD_JOSResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs) :
AUD_ResampleReader(reader, specs.rate),
m_channels(AUD_CHANNELS_INVALID),
m_n(0),
m_P(0),
m_cache_valid(0),
m_last_factor(0)
{
}
void AUD_JOSResampleReader::reset()
{
m_cache_valid = 0;
m_n = 0;
m_P = 0;
m_last_factor = 0;
}
void AUD_JOSResampleReader::updateBuffer(int size, double factor, int samplesize)
{
unsigned int len;
double num_samples = double(m_len) / double(m_L);
// first calculate what length we need right now
if(factor >= 1)
len = ceil(num_samples);
else
len = (unsigned int)(ceil(num_samples / factor));
// then check if afterwards the length is enough for the maximum rate
if(len + size < num_samples * AUD_RATE_MAX)
len = num_samples * AUD_RATE_MAX - size;
if(m_n > len)
{
sample_t* buf = m_buffer.getBuffer();
len = m_n - len;
memmove(buf, buf + len * m_channels, (m_cache_valid - len) * samplesize);
m_n -= len;
m_cache_valid -= len;
}
m_buffer.assureSize((m_cache_valid + size) * samplesize, true);
}
#define RESAMPLE_METHOD(name, left, right) void AUD_JOSResampleReader::name(double target_factor, int length, sample_t* buffer)\
{\
sample_t* buf = m_buffer.getBuffer();\
\
int P, l, end, channel, i;\
double eta, v, f_increment, factor;\
\
m_sums.assureSize(m_channels * sizeof(double));\
double* sums = reinterpret_cast<double*>(m_sums.getBuffer());\
sample_t* data;\
const float* coeff = m_coeff;\
\
unsigned int P_increment;\
\
for(unsigned int t = 0; t < length; t++)\
{\
factor = (m_last_factor * (length - t - 1) + target_factor * (t + 1)) / length;\
\
memset(sums, 0, sizeof(double) * m_channels);\
\
if(factor >= 1)\
{\
P = double_to_fp(m_P * m_L);\
\
end = floor(m_len / double(m_L) - m_P) - 1;\
if(m_n < end)\
end = m_n;\
\
data = buf + (m_n - end) * m_channels;\
l = fp_to_int(P);\
eta = fp_rest_to_double(P);\
l += m_L * end;\
\
for(i = 0; i <= end; i++)\
{\
v = coeff[l] + eta * (coeff[l+1] - coeff[l]);\
l -= m_L;\
left\
}\
\
P = int_to_fp(m_L) - P;\
\
end = floor((m_len - 1) / double(m_L) + m_P) - 1;\
if(m_cache_valid - m_n - 2 < end)\
end = m_cache_valid - m_n - 2;\
\
data = buf + (m_n + 2 + end) * m_channels - 1;\
l = fp_to_int(P);\
eta = fp_rest_to_double(P);\
l += m_L * end;\
\
for(i = 0; i <= end; i++)\
{\
v = coeff[l] + eta * (coeff[l+1] - coeff[l]);\
l -= m_L;\
right\
}\
\
for(channel = 0; channel < m_channels; channel++)\
{\
*buffer = sums[channel];\
buffer++;\
}\
}\
else\
{\
f_increment = factor * m_L;\
P_increment = double_to_fp(f_increment);\
P = double_to_fp(m_P * f_increment);\
\
end = (int_to_fp(m_len) - P) / P_increment - 1;\
if(m_n < end)\
end = m_n;\
\
P += P_increment * end;\
data = buf + (m_n - end) * m_channels;\
l = fp_to_int(P);\
\
for(i = 0; i <= end; i++)\
{\
eta = fp_rest_to_double(P);\
v = coeff[l] + eta * (coeff[l+1] - coeff[l]);\
P -= P_increment;\
l = fp_to_int(P);\
left\
}\
\
P = -P;\
\
end = (int_to_fp(m_len) - P) / P_increment - 1;\
if(m_cache_valid - m_n - 2 < end)\
end = m_cache_valid - m_n - 2;\
\
P += P_increment * end;\
data = buf + (m_n + 2 + end) * m_channels - 1;\
l = fp_to_int(P);\
\
for(i = 0; i <= end; i++)\
{\
eta = fp_rest_to_double(P);\
v = coeff[l] + eta * (coeff[l+1] - coeff[l]);\
P -= P_increment;\
l = fp_to_int(P);\
right\
}\
\
for(channel = 0; channel < m_channels; channel++)\
{\
*buffer = f_increment / m_L * sums[channel];\
buffer++;\
}\
}\
\
m_P += fmod(1.0 / factor, 1.0);\
m_n += floor(1.0 / factor);\
\
if(m_P >= 1.0)\
{\
m_P -= 1.0;\
m_n++;\
}\
}\
}
RESAMPLE_METHOD(resample, {
channel = 0;
do
{
sums[channel] += *data * v;
channel++;
data++;
}
while(channel < m_channels);
}, {
channel = m_channels;
do
{
channel--;
sums[channel] += *data * v;
data--;
}
while(channel);
})
RESAMPLE_METHOD(resample_mono, {
*sums += *data * v;
data++;
}, {
*sums += *data * v;
data--;
})
RESAMPLE_METHOD(resample_stereo, {
sums[0] += data[0] * v;
sums[1] += data[1] * v;
data+=2;
}, {
data-=2;
sums[0] += data[1] * v;
sums[1] += data[2] * v;
})
void AUD_JOSResampleReader::seek(int position)
{
position = floor(position * double(m_reader->getSpecs().rate) / double(m_rate));
m_reader->seek(position);
reset();
}
int AUD_JOSResampleReader::getLength() const
{
return floor(m_reader->getLength() * double(m_rate) / double(m_reader->getSpecs().rate));
}
int AUD_JOSResampleReader::getPosition() const
{
return floor((m_reader->getPosition() + double(m_P))
* m_rate / m_reader->getSpecs().rate);
}
AUD_Specs AUD_JOSResampleReader::getSpecs() const
{
AUD_Specs specs = m_reader->getSpecs();
specs.rate = m_rate;
return specs;
}
void AUD_JOSResampleReader::read(int& length, bool& eos, sample_t* buffer)
{
if(length == 0)
return;
AUD_Specs specs = m_reader->getSpecs();
int samplesize = AUD_SAMPLE_SIZE(specs);
double target_factor = double(m_rate) / double(specs.rate);
eos = false;
int len;
double num_samples = double(m_len) / double(m_L);
// check for channels changed
if(specs.channels != m_channels)
{
m_channels = specs.channels;
reset();
switch(m_channels)
{
case AUD_CHANNELS_MONO:
m_resample = &AUD_JOSResampleReader::resample_mono;
break;
case AUD_CHANNELS_STEREO:
m_resample = &AUD_JOSResampleReader::resample_stereo;
break;
default:
m_resample = &AUD_JOSResampleReader::resample;
break;
}
}
if(m_last_factor == 0)
m_last_factor = target_factor;
if(target_factor == 1 && m_last_factor == 1 && (m_P == 0))
{
// can read directly!
len = length - (m_cache_valid - m_n);
updateBuffer(len, target_factor, samplesize);
sample_t* buf = m_buffer.getBuffer();
m_reader->read(len, eos, buf + m_cache_valid * m_channels);
m_cache_valid += len;
length = m_cache_valid - m_n;
if(length > 0)
{
memcpy(buffer, buf + m_n * m_channels, length * samplesize);
m_n += length;
}
return;
}
// use minimum for the following calculations
double factor = AUD_MIN(target_factor, m_last_factor);
if(factor >= 1)
len = (m_n - m_cache_valid) + int(ceil(length / factor)) + ceil(num_samples);
else
len = (m_n - m_cache_valid) + int(ceil(length / factor) + ceil(num_samples / factor));
if(len > 0)
{
int should = len;
updateBuffer(len, factor, samplesize);
m_reader->read(len, eos, m_buffer.getBuffer() + m_cache_valid * m_channels);
m_cache_valid += len;
if(len < should)
{
if(len == 0 && eos)
length = 0;
else
{
// use maximum for the following calculations
factor = AUD_MAX(target_factor, m_last_factor);
if(eos)
{
// end of stream, let's check how many more samples we can produce
len = floor((m_cache_valid - m_n) * factor);
if(len < length)
length = len;
}
else
{
// not enough data available yet, so we recalculate how many samples we can calculate
if(factor >= 1)
len = floor((num_samples + m_cache_valid - m_n) * factor);
else
len = floor((num_samples * factor + m_cache_valid - m_n) * factor);
if(len < length)
length = len;
}
}
}
}
(this->*m_resample)(target_factor, length, buffer);
m_last_factor = target_factor;
if(m_n > m_cache_valid)
{
m_n = m_cache_valid;
}
eos = eos && ((m_n == m_cache_valid) || (length == 0));
}

@ -0,0 +1,344 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* Copyright 2009-2011 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* Audaspace is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Audaspace; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file audaspace/intern/AUD_SequencerEntry.cpp
* \ingroup audaspaceintern
*/
#include "AUD_SequencerEntry.h"
#include "AUD_SequencerReader.h"
#include <cmath>
#include <limits>
AUD_SequencerEntry::AUD_SequencerEntry(AUD_Reference<AUD_IFactory> sound, float begin, float end, float skip, int id) :
m_status(0),
m_pos_status(1),
m_sound_status(0),
m_id(id),
m_sound(sound),
m_begin(begin),
m_end(end),
m_skip(skip),
m_muted(false),
m_relative(true),
m_volume_max(1.0f),
m_volume_min(0),
m_distance_max(std::numeric_limits<float>::max()),
m_distance_reference(1.0f),
m_attenuation(1.0f),
m_cone_angle_outer(360),
m_cone_angle_inner(360),
m_cone_volume_outer(0),
m_location(3),
m_orientation(4)
{
AUD_Quaternion q;
m_orientation.write(q.get());
float f = 1;
m_volume.write(&f);
m_pitch.write(&f);
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_mutex, &attr);
pthread_mutexattr_destroy(&attr);
}
AUD_SequencerEntry::~AUD_SequencerEntry()
{
pthread_mutex_destroy(&m_mutex);
}
void AUD_SequencerEntry::lock()
{
pthread_mutex_lock(&m_mutex);
}
void AUD_SequencerEntry::unlock()
{
pthread_mutex_unlock(&m_mutex);
}
void AUD_SequencerEntry::setSound(AUD_Reference<AUD_IFactory> sound)
{
lock();
if(m_sound.get() != sound.get())
{
m_sound = sound;
m_sound_status++;
}
unlock();
}
void AUD_SequencerEntry::move(float begin, float end, float skip)
{
lock();
if(m_begin != begin || m_skip != skip || m_end != end)
{
m_begin = begin;
m_skip = skip;
m_end = end;
m_pos_status++;
}
unlock();
}
void AUD_SequencerEntry::mute(bool mute)
{
lock();
m_muted = mute;
unlock();
}
int AUD_SequencerEntry::getID() const
{
return m_id;
}
AUD_AnimateableProperty* AUD_SequencerEntry::getAnimProperty(AUD_AnimateablePropertyType type)
{
switch(type)
{
case AUD_AP_VOLUME:
return &m_volume;
case AUD_AP_PITCH:
return &m_pitch;
case AUD_AP_PANNING:
return &m_panning;
case AUD_AP_LOCATION:
return &m_location;
case AUD_AP_ORIENTATION:
return &m_orientation;
default:
return NULL;
}
}
void AUD_SequencerEntry::updateAll(float volume_max, float volume_min, float distance_max,
float distance_reference, float attenuation, float cone_angle_outer,
float cone_angle_inner, float cone_volume_outer)
{
lock();
if(volume_max != m_volume_max)
{
m_volume_max = volume_max;
m_status++;
}
if(volume_min != m_volume_min)
{
m_volume_min = volume_min;
m_status++;
}
if(distance_max != m_distance_max)
{
m_distance_max = distance_max;
m_status++;
}
if(distance_reference != m_distance_reference)
{
m_distance_reference = distance_reference;
m_status++;
}
if(attenuation != m_attenuation)
{
m_attenuation = attenuation;
m_status++;
}
if(cone_angle_outer != m_cone_angle_outer)
{
m_cone_angle_outer = cone_angle_outer;
m_status++;
}
if(cone_angle_inner != m_cone_angle_inner)
{
m_cone_angle_inner = cone_angle_inner;
m_status++;
}
if(cone_volume_outer != m_cone_volume_outer)
{
m_cone_volume_outer = cone_volume_outer;
m_status++;
}
unlock();
}
bool AUD_SequencerEntry::isRelative()
{
return m_relative;
}
void AUD_SequencerEntry::setRelative(bool relative)
{
lock();
if(m_relative != relative)
{
m_relative = relative;
m_status++;
}
unlock();
}
float AUD_SequencerEntry::getVolumeMaximum()
{
return m_volume_max;
}
void AUD_SequencerEntry::setVolumeMaximum(float volume)
{
lock();
m_volume_max = volume;
m_status++;
unlock();
}
float AUD_SequencerEntry::getVolumeMinimum()
{
return m_volume_min;
}
void AUD_SequencerEntry::setVolumeMinimum(float volume)
{
lock();
m_volume_min = volume;
m_status++;
unlock();
}
float AUD_SequencerEntry::getDistanceMaximum()
{
return m_distance_max;
}
void AUD_SequencerEntry::setDistanceMaximum(float distance)
{
lock();
m_distance_max = distance;
m_status++;
unlock();
}
float AUD_SequencerEntry::getDistanceReference()
{
return m_distance_reference;
}
void AUD_SequencerEntry::setDistanceReference(float distance)
{
lock();
m_distance_reference = distance;
m_status++;
unlock();
}
float AUD_SequencerEntry::getAttenuation()
{
return m_attenuation;
}
void AUD_SequencerEntry::setAttenuation(float factor)
{
lock();
m_attenuation = factor;
m_status++;
unlock();
}
float AUD_SequencerEntry::getConeAngleOuter()
{
return m_cone_angle_outer;
}
void AUD_SequencerEntry::setConeAngleOuter(float angle)
{
lock();
m_cone_angle_outer = angle;
m_status++;
unlock();
}
float AUD_SequencerEntry::getConeAngleInner()
{
return m_cone_angle_inner;
}
void AUD_SequencerEntry::setConeAngleInner(float angle)
{
lock();
m_cone_angle_inner = angle;
m_status++;
unlock();
}
float AUD_SequencerEntry::getConeVolumeOuter()
{
return m_cone_volume_outer;
}
void AUD_SequencerEntry::setConeVolumeOuter(float volume)
{
lock();
m_cone_volume_outer = volume;
m_status++;
unlock();
}

@ -0,0 +1,166 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* Copyright 2009-2011 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* Audaspace is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* AudaSpace 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Audaspace; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file audaspace/intern/AUD_SequencerHandle.cpp
* \ingroup audaspaceintern
*/
#include "AUD_SequencerHandle.h"
#include "AUD_ReadDevice.h"
AUD_SequencerHandle::AUD_SequencerHandle(AUD_Reference<AUD_SequencerEntry> entry, AUD_ReadDevice& device) :
m_entry(entry),
m_status(0),
m_pos_status(0),
m_sound_status(0),
m_device(device)
{
if(!entry->m_sound.isNull())
{
m_handle = device.play(entry->m_sound, true);
m_3dhandle = AUD_Reference<AUD_I3DHandle>(m_handle);
}
}
AUD_SequencerHandle::~AUD_SequencerHandle()
{
stop();
}
int AUD_SequencerHandle::compare(AUD_Reference<AUD_SequencerEntry> entry) const
{
if(m_entry->getID() < entry->getID())
return -1;
else if(m_entry->getID() == entry->getID())
return 0;
return 1;
}
void AUD_SequencerHandle::stop()
{
if(!m_handle.isNull())
m_handle->stop();
}
void AUD_SequencerHandle::update(float position, float frame)
{
if(!m_handle.isNull())
{
m_entry->lock();
if(position >= m_entry->m_end && m_entry->m_end >= 0)
m_handle->pause();
else if(position >= m_entry->m_begin)
m_handle->resume();
if(m_sound_status != m_entry->m_sound_status)
{
if(!m_handle.isNull())
m_handle->stop();
if(!m_entry->m_sound.isNull())
{
m_handle = m_device.play(m_entry->m_sound, true);
m_3dhandle = AUD_Reference<AUD_I3DHandle>(m_handle);
}
m_sound_status = m_entry->m_sound_status;
m_pos_status--;
m_status--;
}
if(m_pos_status != m_entry->m_pos_status)
{
seek(position);
m_pos_status = m_entry->m_pos_status;
}
if(m_status != m_entry->m_status)
{
m_3dhandle->setRelative(m_entry->m_relative);
m_3dhandle->setVolumeMaximum(m_entry->m_volume_max);
m_3dhandle->setVolumeMinimum(m_entry->m_volume_min);
m_3dhandle->setDistanceMaximum(m_entry->m_distance_max);
m_3dhandle->setDistanceReference(m_entry->m_distance_reference);
m_3dhandle->setAttenuation(m_entry->m_attenuation);
m_3dhandle->setConeAngleOuter(m_entry->m_cone_angle_outer);
m_3dhandle->setConeAngleInner(m_entry->m_cone_angle_inner);
m_3dhandle->setConeVolumeOuter(m_entry->m_cone_volume_outer);
m_status = m_entry->m_status;
}
float value;
m_entry->m_volume.read(frame, &value);
m_handle->setVolume(value);
m_entry->m_pitch.read(frame, &value);
m_handle->setPitch(value);
m_entry->m_panning.read(frame, &value);
AUD_SoftwareDevice::setPanning(m_handle.get(), value);
AUD_Vector3 v, v2;
AUD_Quaternion q;
m_entry->m_orientation.read(frame, q.get());
m_3dhandle->setSourceOrientation(q);
m_entry->m_location.read(frame, v.get());
m_3dhandle->setSourceLocation(v);
m_entry->m_location.read(frame + 1, v2.get());
v2 -= v;
m_3dhandle->setSourceVelocity(v2);
if(m_entry->m_muted)
m_handle->setVolume(0);
m_entry->unlock();
}
}
void AUD_SequencerHandle::seek(float position)
{
if(!m_handle.isNull())
{
m_entry->lock();
if(position >= m_entry->m_end && m_entry->m_end >= 0)
{
m_handle->pause();
m_entry->unlock();
return;
}
float seekpos = position - m_entry->m_begin;
if(seekpos < 0)
seekpos = 0;
seekpos += m_entry->m_skip;
m_handle->seek(seekpos);
if(position < m_entry->m_begin)
m_handle->pause();
else
m_handle->resume();
m_entry->unlock();
}
}