diff --git a/intern/audaspace/intern/AUD_IHandle.h b/intern/audaspace/intern/AUD_IHandle.h new file mode 100644 index 00000000000..5b8695131e4 --- /dev/null +++ b/intern/audaspace/intern/AUD_IHandle.h @@ -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 diff --git a/intern/audaspace/intern/AUD_JOSResampleFactory.h b/intern/audaspace/intern/AUD_JOSResampleFactory.h new file mode 100644 index 00000000000..90a5df5baf0 --- /dev/null +++ b/intern/audaspace/intern/AUD_JOSResampleFactory.h @@ -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 factory, AUD_DeviceSpecs specs); + + virtual AUD_Reference createReader(); +}; + +#endif //AUD_JOSRESAMPLEFACTORY diff --git a/intern/audaspace/intern/AUD_JOSResampleReader.cpp b/intern/audaspace/intern/AUD_JOSResampleReader.cpp new file mode 100644 index 00000000000..8da3d55acae --- /dev/null +++ b/intern/audaspace/intern/AUD_JOSResampleReader.cpp @@ -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 +#include +#include + +/* MSVC does not have lrint */ +#ifdef _MSC_VER +#ifdef _M_X64 +#include +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 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(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)); +} diff --git a/intern/audaspace/intern/AUD_SequencerEntry.cpp b/intern/audaspace/intern/AUD_SequencerEntry.cpp new file mode 100644 index 00000000000..c5112f9f3de --- /dev/null +++ b/intern/audaspace/intern/AUD_SequencerEntry.cpp @@ -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 +#include + +AUD_SequencerEntry::AUD_SequencerEntry(AUD_Reference 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::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 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(); +} diff --git a/intern/audaspace/intern/AUD_SequencerHandle.cpp b/intern/audaspace/intern/AUD_SequencerHandle.cpp new file mode 100644 index 00000000000..c9cf46ccdc3 --- /dev/null +++ b/intern/audaspace/intern/AUD_SequencerHandle.cpp @@ -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 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(m_handle); + } +} + +AUD_SequencerHandle::~AUD_SequencerHandle() +{ + stop(); +} + +int AUD_SequencerHandle::compare(AUD_Reference 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(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(); + } +}