diff options
author | Joerg Mueller <nexyon@gmail.com> | 2010-08-16 15:41:07 +0400 |
---|---|---|
committer | Joerg Mueller <nexyon@gmail.com> | 2010-08-16 15:41:07 +0400 |
commit | 25fec1592efade86233c0ba71212dc973b618ad1 (patch) | |
tree | 8c6eccaf24d7bf4fa72c5cfc1ca86511d2df0c9d | |
parent | a91d538f47171a40463016b91c22d39d694d923a (diff) | |
parent | 2b7a774ab0dfd3bc66240b387a586b5122ab2661 (diff) |
Audaspace (GSoC): First merging commit
* All audaspace changes from the GSoC branch including the aud Python module
* This commit also includes some minor changes in source/gameengine/Ketsji/KX_PythonInit.cpp:
- Fixing names of some constants
- removing outdated stopDSP() python function
- Autoinclusion of bge instead of GameLogic
- Fix for some error messages: GameLogic -> bge.logic
161 files changed, 7410 insertions, 4175 deletions
diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt index 0965a467201..c1d59dcd3e9 100644 --- a/intern/audaspace/CMakeLists.txt +++ b/intern/audaspace/CMakeLists.txt @@ -60,6 +60,12 @@ IF(WITH_FFTW3) ADD_DEFINITIONS(-DWITH_FFTW3) ENDIF(WITH_FFTW3) -SET(SRC ${SRC} ${FFMPEGSRC} ${SNDFILESRC} ${FFTW3SRC} ${SDLSRC} ${OPENALSRC} ${JACKSRC}) +IF(WITH_PYTHON) + SET(INC ${INC} Python ${PYTHON_INC}) + FILE(GLOB PYTHONSRC Python/*.cpp) + ADD_DEFINITIONS(-DWITH_PYTHON) +ENDIF(WITH_PYTHON) + +SET(SRC ${SRC} ${FFMPEGSRC} ${SNDFILESRC} ${FFTW3SRC} ${SDLSRC} ${OPENALSRC} ${JACKSRC} ${PYTHONSRC}) BLENDERLIB(bf_audaspace "${SRC}" "${INC}") diff --git a/intern/audaspace/FX/AUD_AccumulatorFactory.cpp b/intern/audaspace/FX/AUD_AccumulatorFactory.cpp index 20709c57ee5..0c51e5241e4 100644 --- a/intern/audaspace/FX/AUD_AccumulatorFactory.cpp +++ b/intern/audaspace/FX/AUD_AccumulatorFactory.cpp @@ -24,26 +24,37 @@ */ #include "AUD_AccumulatorFactory.h" -#include "AUD_AccumulatorReader.h" +#include "AUD_CallbackIIRFilterReader.h" + +sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless) +{ + float in = reader->x(0); + float lastin = reader->x(-1); + float out = reader->y(-1) + in - lastin; + if(in > lastin) + out += in - lastin; + return out; +} + +sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless) +{ + float in = reader->x(0); + float lastin = reader->x(-1); + float out = reader->y(-1); + if(in > lastin) + out += in - lastin; + return out; +} AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_IFactory* factory, bool additive) : AUD_EffectFactory(factory), - m_additive(additive) {} - -AUD_AccumulatorFactory::AUD_AccumulatorFactory(bool additive) : - AUD_EffectFactory(0), - m_additive(additive) {} - -AUD_IReader* AUD_AccumulatorFactory::createReader() + m_additive(additive) { - AUD_IReader* reader = getReader(); - - if(reader != 0) - { - reader = new AUD_AccumulatorReader(reader, m_additive); - AUD_NEW("reader") - } +} - return reader; +AUD_IReader* AUD_AccumulatorFactory::createReader() const +{ + return new AUD_CallbackIIRFilterReader(getReader(), 2, 2, + m_additive ? accumulatorFilterAdditive : accumulatorFilter); } diff --git a/intern/audaspace/FX/AUD_AccumulatorFactory.h b/intern/audaspace/FX/AUD_AccumulatorFactory.h index e475a19ccf6..2b90fa43bdf 100644 --- a/intern/audaspace/FX/AUD_AccumulatorFactory.h +++ b/intern/audaspace/FX/AUD_AccumulatorFactory.h @@ -37,7 +37,11 @@ private: /** * Whether the accumulator is additive. */ - bool m_additive; + const bool m_additive; + + // hide copy constructor and operator= + AUD_AccumulatorFactory(const AUD_AccumulatorFactory&); + AUD_AccumulatorFactory& operator=(const AUD_AccumulatorFactory&); public: /** @@ -47,13 +51,7 @@ public: */ AUD_AccumulatorFactory(AUD_IFactory* factory, bool additive = false); - /** - * Creates a new accumulator factory. - * \param additive Whether the accumulator is additive. - */ - AUD_AccumulatorFactory(bool additive = false); - - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_ACCUMULATORFACTORY diff --git a/intern/audaspace/FX/AUD_AccumulatorReader.cpp b/intern/audaspace/FX/AUD_AccumulatorReader.cpp deleted file mode 100644 index 67ab4157f9c..00000000000 --- a/intern/audaspace/FX/AUD_AccumulatorReader.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN LGPL LICENSE BLOCK ***** - * - * Copyright 2009 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 Lesser General Public License as published by - * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#include "AUD_AccumulatorReader.h" -#include "AUD_Buffer.h" - -#include <cstring> - -#define CC specs.channels + channel - -AUD_AccumulatorReader::AUD_AccumulatorReader(AUD_IReader* reader, - bool additive) : - AUD_EffectReader(reader), - m_additive(additive) -{ - AUD_Specs specs = reader->getSpecs(); - int samplesize = AUD_SAMPLE_SIZE(specs); - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - - m_sums = new AUD_Buffer(samplesize); AUD_NEW("buffer") - memset(m_sums->getBuffer(), 0, samplesize); - - m_prevs = new AUD_Buffer(samplesize); AUD_NEW("buffer") - memset(m_prevs->getBuffer(), 0, samplesize); -} - -AUD_AccumulatorReader::~AUD_AccumulatorReader() -{ - delete m_buffer; AUD_DELETE("buffer") - delete m_sums; AUD_DELETE("buffer") - delete m_prevs; AUD_DELETE("buffer") -} - -void AUD_AccumulatorReader::read(int & length, sample_t* & buffer) -{ - sample_t* buf; - sample_t* sums; - sample_t* prevs; - sums = m_sums->getBuffer(); - prevs = m_prevs->getBuffer(); - - AUD_Specs specs = m_reader->getSpecs(); - - m_reader->read(length, buf); - if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs)) - m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); - - buffer = m_buffer->getBuffer(); - - if(m_additive) - { - for(int channel = 0; channel < specs.channels; channel++) - { - for(int i = 0; i < length; i++) - { - if(buf[i * CC] > prevs[channel]) - sums[channel] += buf[i * CC] - prevs[channel]; - buffer[i * CC] = sums[channel] + buf[i * CC]; - prevs[channel] = buf[i * CC]; - } - } - } - else - { - for(int channel = 0; channel < specs.channels; channel++) - { - for(int i = 0; i < length * specs.channels; i++) - { - if(buf[i * CC] > prevs[channel]) - sums[channel] += buf[i * CC] - prevs[channel]; - buffer[i * CC] = sums[channel]; - prevs[channel] = buf[i * CC]; - } - } - } -} diff --git a/intern/audaspace/FX/AUD_AccumulatorReader.h b/intern/audaspace/FX/AUD_AccumulatorReader.h deleted file mode 100644 index 8ad1dda30f6..00000000000 --- a/intern/audaspace/FX/AUD_AccumulatorReader.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN LGPL LICENSE BLOCK ***** - * - * Copyright 2009 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 Lesser General Public License as published by - * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#ifndef AUD_ACCUMULATORREADER -#define AUD_ACCUMULATORREADER - -#include "AUD_EffectReader.h" -class AUD_Buffer; - -/** - * This class represents an accumulator. - */ -class AUD_AccumulatorReader : public AUD_EffectReader -{ -private: - /** - * The playback buffer. - */ - AUD_Buffer *m_buffer; - - /** - * The sums of the specific channels. - */ - AUD_Buffer *m_sums; - - /** - * The previous results of the specific channels. - */ - AUD_Buffer *m_prevs; - - /** - * Whether the accumulator is additive. - */ - bool m_additive; - -public: - /** - * Creates a new accumulator reader. - * \param reader The reader to read from. - * \param additive Whether the accumulator is additive. - * \exception AUD_Exception Thrown if the reader specified is NULL. - */ - AUD_AccumulatorReader(AUD_IReader* reader, bool additive); - - /** - * Destroys the reader. - */ - virtual ~AUD_AccumulatorReader(); - - virtual void read(int & length, sample_t* & buffer); -}; - -#endif //AUD_ACCUMULATORREADER diff --git a/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp b/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp new file mode 100644 index 00000000000..9e14bcf0e40 --- /dev/null +++ b/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp @@ -0,0 +1,76 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_BaseIIRFilterReader.h" + +#include <cstring> + +#define CC m_channels + m_channel + +AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_IReader* reader, int in, + int out) : + AUD_EffectReader(reader), + m_channels(reader->getSpecs().channels), + m_xlen(in), m_ylen(out), + m_xpos(0), m_ypos(0), m_channel(0) +{ + m_x = new sample_t[in * m_channels]; + m_y = new sample_t[out * m_channels]; + + memset(m_x, 0, sizeof(sample_t) * in * m_channels); + memset(m_y, 0, sizeof(sample_t) * out * m_channels); +} + +AUD_BaseIIRFilterReader::~AUD_BaseIIRFilterReader() +{ + delete[] m_x; + delete[] m_y; +} + +void AUD_BaseIIRFilterReader::read(int & length, sample_t* & buffer) +{ + sample_t* buf; + + int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs()); + + m_reader->read(length, buf); + + if(m_buffer.getSize() < length * samplesize) + m_buffer.resize(length * samplesize); + + buffer = m_buffer.getBuffer(); + + for(m_channel = 0; m_channel < m_channels; m_channel++) + { + for(int i = 0; i < length; i++) + { + m_x[m_xpos * CC] = buf[i * CC]; + m_y[m_ypos * CC] = buffer[i * CC] = filter(); + + m_xpos = (m_xpos + 1) % m_xlen; + m_ypos = (m_ypos + 1) % m_ylen; + } + } +} diff --git a/intern/audaspace/FX/AUD_BaseIIRFilterReader.h b/intern/audaspace/FX/AUD_BaseIIRFilterReader.h new file mode 100644 index 00000000000..7e2b71983a0 --- /dev/null +++ b/intern/audaspace/FX/AUD_BaseIIRFilterReader.h @@ -0,0 +1,114 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_BASEIIRFILTERREADER +#define AUD_BASEIIRFILTERREADER + +#include "AUD_EffectReader.h" +#include "AUD_Buffer.h" + +/** + * This class is a base class for infinite impulse response filters. + */ +class AUD_BaseIIRFilterReader : public AUD_EffectReader +{ +private: + /** + * Channel count. + */ + const int m_channels; + + /** + * Length of input samples needed. + */ + const int m_xlen; + + /** + * Length of output samples needed. + */ + const int m_ylen; + + /** + * The playback buffer. + */ + AUD_Buffer m_buffer; + + /** + * The last in samples array. + */ + sample_t* m_x; + + /** + * The last out samples array. + */ + sample_t* m_y; + + /** + * Position of the current input sample in the input array. + */ + int m_xpos; + + /** + * Position of the current output sample in the output array. + */ + int m_ypos; + + /** + * Current channel. + */ + int m_channel; + + // hide copy constructor and operator= + AUD_BaseIIRFilterReader(const AUD_BaseIIRFilterReader&); + AUD_BaseIIRFilterReader& operator=(const AUD_BaseIIRFilterReader&); + +protected: + /** + * Creates a new base IIR filter reader. + * \param reader The reader to read from. + * \param in The count of past input samples needed. + * \param out The count of past output samples needed. + */ + AUD_BaseIIRFilterReader(AUD_IReader* reader, int in, int out); + +public: + inline sample_t x(int pos) + { + return m_x[(m_xpos + pos + m_xlen) % m_xlen * m_channels + m_channel]; + } + + inline sample_t y(int pos) + { + return m_y[(m_ypos + pos + m_ylen) % m_ylen * m_channels + m_channel]; + } + + virtual ~AUD_BaseIIRFilterReader(); + + virtual void read(int & length, sample_t* & buffer); + + virtual sample_t filter()=0; +}; + +#endif //AUD_BASEIIRFILTERREADER diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.cpp b/intern/audaspace/FX/AUD_ButterworthFactory.cpp index fd0a53def7c..874ff0f6351 100644 --- a/intern/audaspace/FX/AUD_ButterworthFactory.cpp +++ b/intern/audaspace/FX/AUD_ButterworthFactory.cpp @@ -24,26 +24,49 @@ */ #include "AUD_ButterworthFactory.h" -#include "AUD_ButterworthReader.h" +#include "AUD_IIRFilterReader.h" + +#include <cmath> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define BWPB41 0.76536686473 +#define BWPB42 1.84775906502 AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_IFactory* factory, float frequency) : AUD_EffectFactory(factory), - m_frequency(frequency) {} - -AUD_ButterworthFactory::AUD_ButterworthFactory(float frequency) : - AUD_EffectFactory(0), - m_frequency(frequency) {} + m_frequency(frequency) +{ +} -AUD_IReader* AUD_ButterworthFactory::createReader() +AUD_IReader* AUD_ButterworthFactory::createReader() const { AUD_IReader* reader = getReader(); - if(reader != 0) - { - reader = new AUD_ButterworthReader(reader, m_frequency); - AUD_NEW("reader") - } + // calculate coefficients + float omega = 2 * tan(m_frequency * M_PI / reader->getSpecs().rate); + float o2 = omega * omega; + float o4 = o2 * o2; + float x1 = o2 + 2 * BWPB41 * omega + 4; + float x2 = o2 + 2 * BWPB42 * omega + 4; + float y1 = o2 - 2 * BWPB41 * omega + 4; + float y2 = o2 - 2 * BWPB42 * omega + 4; + float o228 = 2 * o2 - 8; + float norm = x1 * x2; + std::vector<float> a, b; + a.push_back(1); + a.push_back((x1 + x2) * o228 / norm); + a.push_back((x1 * y2 + x2 * y1 + o228 * o228) / norm); + a.push_back((y1 + y2) * o228 / norm); + a.push_back(y1 * y2 / norm); + b.push_back(o4 / norm); + b.push_back(4 * o4 / norm); + b.push_back(6 * o4 / norm); + b.push_back(b[1]); + b.push_back(b[0]); - return reader; + return new AUD_IIRFilterReader(reader, b, a); } diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.h b/intern/audaspace/FX/AUD_ButterworthFactory.h index 69169531d70..30b7a402c57 100644 --- a/intern/audaspace/FX/AUD_ButterworthFactory.h +++ b/intern/audaspace/FX/AUD_ButterworthFactory.h @@ -37,7 +37,11 @@ private: /** * The attack value in seconds. */ - float m_frequency; + const float m_frequency; + + // hide copy constructor and operator= + AUD_ButterworthFactory(const AUD_ButterworthFactory&); + AUD_ButterworthFactory& operator=(const AUD_ButterworthFactory&); public: /** @@ -47,13 +51,7 @@ public: */ AUD_ButterworthFactory(AUD_IFactory* factory, float frequency); - /** - * Creates a new butterworth factory. - * \param frequency The cutoff frequency. - */ - AUD_ButterworthFactory(float frequency); - - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_BUTTERWORTHFACTORY diff --git a/intern/audaspace/FX/AUD_ButterworthReader.cpp b/intern/audaspace/FX/AUD_ButterworthReader.cpp deleted file mode 100644 index 2129dfef798..00000000000 --- a/intern/audaspace/FX/AUD_ButterworthReader.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN LGPL LICENSE BLOCK ***** - * - * Copyright 2009 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 Lesser General Public License as published by - * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#include "AUD_ButterworthReader.h" -#include "AUD_Buffer.h" - -#include <cstring> -#include <cmath> - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#define BWPB41 0.76536686473 -#define BWPB42 1.84775906502 -#define CC channels + channel - -AUD_ButterworthReader::AUD_ButterworthReader(AUD_IReader* reader, - float frequency) : - AUD_EffectReader(reader) -{ - AUD_Specs specs = reader->getSpecs(); - int samplesize = AUD_SAMPLE_SIZE(specs); - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - - m_outvalues = new AUD_Buffer(samplesize * 5); AUD_NEW("buffer") - memset(m_outvalues->getBuffer(), 0, samplesize * 5); - - m_invalues = new AUD_Buffer(samplesize * 5); AUD_NEW("buffer") - memset(m_invalues->getBuffer(), 0, samplesize * 5); - - m_position = 0; - - // calculate coefficients - float omega = 2 * tan(frequency * M_PI / specs.rate); - float o2 = omega * omega; - float o4 = o2 * o2; - float x1 = o2 + 2 * BWPB41 * omega + 4; - float x2 = o2 + 2 * BWPB42 * omega + 4; - float y1 = o2 - 2 * BWPB41 * omega + 4; - float y2 = o2 - 2 * BWPB42 * omega + 4; - float o228 = 2 * o2 - 8; - float norm = x1 * x2; - m_coeff[0][0] = 0; - m_coeff[0][1] = (x1 + x2) * o228 / norm; - m_coeff[0][2] = (x1 * y2 + x2 * y1 + o228 * o228) / norm; - m_coeff[0][3] = (y1 + y2) * o228 / norm; - m_coeff[0][4] = y1 * y2 / norm; - m_coeff[1][4] = m_coeff[1][0] = o4 / norm; - m_coeff[1][3] = m_coeff[1][1] = 4 * o4 / norm; - m_coeff[1][2] = 6 * o4 / norm; -} - -AUD_ButterworthReader::~AUD_ButterworthReader() -{ - delete m_buffer; AUD_DELETE("buffer") - - delete m_outvalues; AUD_DELETE("buffer") - delete m_invalues; AUD_DELETE("buffer"); -} - -void AUD_ButterworthReader::read(int & length, sample_t* & buffer) -{ - sample_t* buf; - sample_t* outvalues; - sample_t* invalues; - - outvalues = m_outvalues->getBuffer(); - invalues = m_invalues->getBuffer(); - - AUD_Specs specs = m_reader->getSpecs(); - - m_reader->read(length, buf); - - if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs)) - m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); - - buffer = m_buffer->getBuffer(); - int channels = specs.channels; - - for(int channel = 0; channel < channels; channel++) - { - for(int i = 0; i < length; i++) - { - invalues[m_position * CC] = buf[i * CC]; - outvalues[m_position * CC] = 0; - - for(int j = 0; j < 4; j++) - { - outvalues[m_position * CC] += m_coeff[1][j] * - invalues[((m_position + j) % 5) * CC] - - m_coeff[0][j] * - outvalues[((m_position + j) % 5) * CC]; - } - - buffer[i * CC] = outvalues[m_position * CC]; - - m_position = (m_position + 4) % 5; - } - } -} diff --git a/intern/audaspace/FX/AUD_ButterworthReader.h b/intern/audaspace/FX/AUD_ButterworthReader.h deleted file mode 100644 index b1cbd4e3820..00000000000 --- a/intern/audaspace/FX/AUD_ButterworthReader.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN LGPL LICENSE BLOCK ***** - * - * Copyright 2009 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 Lesser General Public License as published by - * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#ifndef AUD_BUTTERWORTHREADER -#define AUD_BUTTERWORTHREADER - -#include "AUD_EffectReader.h" -class AUD_Buffer; - -/** - * This class represents a butterworth filter. - */ -class AUD_ButterworthReader : public AUD_EffectReader -{ -private: - /** - * The playback buffer. - */ - AUD_Buffer *m_buffer; - - /** - * The last out values buffer. - */ - AUD_Buffer *m_outvalues; - - /** - * The last in values buffer. - */ - AUD_Buffer *m_invalues; - - /** - * The position for buffer cycling. - */ - int m_position; - - /** - * Filter coefficients. - */ - float m_coeff[2][5]; - -public: - /** - * Creates a new butterworth reader. - * \param reader The reader to read from. - * \param attack The attack value in seconds. - * \param release The release value in seconds. - * \param threshold The threshold value. - * \param arthreshold The attack/release threshold value. - * \exception AUD_Exception Thrown if the reader specified is NULL. - */ - AUD_ButterworthReader(AUD_IReader* reader, float frequency); - - /** - * Destroys the reader. - */ - virtual ~AUD_ButterworthReader(); - - virtual void read(int & length, sample_t* & buffer); -}; - -#endif //AUD_BUTTERWORTHREADER diff --git a/intern/audaspace/FX/AUD_RectifyReader.cpp b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp index 5d3ce80e811..02ab6e185fe 100644 --- a/intern/audaspace/FX/AUD_RectifyReader.cpp +++ b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp @@ -23,33 +23,25 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#include "AUD_RectifyReader.h" -#include "AUD_Buffer.h" - -#include <cmath> - -AUD_RectifyReader::AUD_RectifyReader(AUD_IReader* reader) : - AUD_EffectReader(reader) +#include "AUD_CallbackIIRFilterReader.h" + +AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(AUD_IReader* reader, + int in, int out, + doFilterIIR doFilter, + endFilterIIR endFilter, + void* data) : + AUD_BaseIIRFilterReader(reader, in, out), + m_filter(doFilter), m_endFilter(endFilter), m_data(data) { - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } -AUD_RectifyReader::~AUD_RectifyReader() +AUD_CallbackIIRFilterReader::~AUD_CallbackIIRFilterReader() { - delete m_buffer; AUD_DELETE("buffer") + if(m_endFilter) + m_endFilter(m_data); } -void AUD_RectifyReader::read(int & length, sample_t* & buffer) +sample_t AUD_CallbackIIRFilterReader::filter() { - sample_t* buf; - AUD_Specs specs = m_reader->getSpecs(); - - m_reader->read(length, buf); - if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs)) - m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); - - buffer = m_buffer->getBuffer(); - - for(int i = 0; i < length * specs.channels; i++) - buffer[i] = fabs(buf[i]); + return m_filter(this, m_data); } diff --git a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h new file mode 100644 index 00000000000..6472c7baad3 --- /dev/null +++ b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h @@ -0,0 +1,83 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_CALLBACKIIRFILTERREADER +#define AUD_CALLBACKIIRFILTERREADER + +#include "AUD_BaseIIRFilterReader.h" +#include "AUD_Buffer.h" + +class AUD_CallbackIIRFilterReader; + +typedef sample_t (*doFilterIIR)(AUD_CallbackIIRFilterReader*, void*); +typedef void (*endFilterIIR)(void*); + +/** + * This class provides an interface for infinite impulse response filters via a + * callback filter function. + */ +class AUD_CallbackIIRFilterReader : public AUD_BaseIIRFilterReader +{ +private: + /** + * Filter function. + */ + const doFilterIIR m_filter; + + /** + * End filter function. + */ + const endFilterIIR m_endFilter; + + /** + * Data pointer. + */ + void* m_data; + + // hide copy constructor and operator= + AUD_CallbackIIRFilterReader(const AUD_CallbackIIRFilterReader&); + AUD_CallbackIIRFilterReader& operator=(const AUD_CallbackIIRFilterReader&); + +public: + /** + * Creates a new callback IIR filter reader. + * \param reader The reader to read from. + * \param in The count of past input samples needed. + * \param out The count of past output samples needed. + * \param doFilter The filter callback. + * \param endFilter The finishing callback. + * \param data Data pointer for the callbacks. + */ + AUD_CallbackIIRFilterReader(AUD_IReader* reader, int in, int out, + doFilterIIR doFilter, + endFilterIIR endFilter = 0, + void* data = 0); + + virtual ~AUD_CallbackIIRFilterReader(); + + virtual sample_t filter(); +}; + +#endif //AUD_CALLBACKIIRFILTERREADER diff --git a/intern/audaspace/FX/AUD_DelayFactory.cpp b/intern/audaspace/FX/AUD_DelayFactory.cpp index 25ce4faed4c..f98743d6fb7 100644 --- a/intern/audaspace/FX/AUD_DelayFactory.cpp +++ b/intern/audaspace/FX/AUD_DelayFactory.cpp @@ -29,30 +29,16 @@ AUD_DelayFactory::AUD_DelayFactory(AUD_IFactory* factory, float delay) : AUD_EffectFactory(factory), - m_delay(delay) {} - -AUD_DelayFactory::AUD_DelayFactory(float delay) : - AUD_EffectFactory(0), - m_delay(delay) {} - -float AUD_DelayFactory::getDelay() + m_delay(delay) { - return m_delay; } -void AUD_DelayFactory::setDelay(float delay) +float AUD_DelayFactory::getDelay() const { - m_delay = delay; + return m_delay; } -AUD_IReader* AUD_DelayFactory::createReader() +AUD_IReader* AUD_DelayFactory::createReader() const { - AUD_IReader* reader = getReader(); - - if(reader != 0) - { - reader = new AUD_DelayReader(reader, m_delay); AUD_NEW("reader") - } - - return reader; + return new AUD_DelayReader(getReader(), m_delay); } diff --git a/intern/audaspace/FX/AUD_DelayFactory.h b/intern/audaspace/FX/AUD_DelayFactory.h index 5ad4b9ab996..721262fb73f 100644 --- a/intern/audaspace/FX/AUD_DelayFactory.h +++ b/intern/audaspace/FX/AUD_DelayFactory.h @@ -37,7 +37,11 @@ private: /** * The delay in samples. */ - float m_delay; + const float m_delay; + + // hide copy constructor and operator= + AUD_DelayFactory(const AUD_DelayFactory&); + AUD_DelayFactory& operator=(const AUD_DelayFactory&); public: /** @@ -45,26 +49,14 @@ public: * \param factory The input factory. * \param delay The desired delay in seconds. */ - AUD_DelayFactory(AUD_IFactory* factory = 0, float delay = 0); - - /** - * Creates a new delay factory. - * \param delay The desired delay in seconds. - */ - AUD_DelayFactory(float delay); + AUD_DelayFactory(AUD_IFactory* factory, float delay = 0); /** * Returns the delay in seconds. */ - float getDelay(); - - /** - * Sets the delay. - * \param delay The new delay value in seconds. - */ - void setDelay(float delay); + float getDelay() const; - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_DELAYFACTORY diff --git a/intern/audaspace/FX/AUD_DelayReader.cpp b/intern/audaspace/FX/AUD_DelayReader.cpp index f2521f645aa..e9f0c15b9b4 100644 --- a/intern/audaspace/FX/AUD_DelayReader.cpp +++ b/intern/audaspace/FX/AUD_DelayReader.cpp @@ -24,28 +24,19 @@ */ #include "AUD_DelayReader.h" -#include "AUD_Buffer.h" #include <cstring> AUD_DelayReader::AUD_DelayReader(AUD_IReader* reader, float delay) : - AUD_EffectReader(reader) + AUD_EffectReader(reader), + m_delay(int(delay * reader->getSpecs().rate)), + m_remdelay(int(delay * reader->getSpecs().rate)), + m_empty(true) { - m_delay = (int)(delay * reader->getSpecs().rate); - m_remdelay = m_delay; - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") -} - -AUD_DelayReader::~AUD_DelayReader() -{ - delete m_buffer; AUD_DELETE("buffer") } void AUD_DelayReader::seek(int position) { - if(position < 0) - return; - if(position < m_delay) { m_remdelay = m_delay - position; @@ -58,18 +49,18 @@ void AUD_DelayReader::seek(int position) } } -int AUD_DelayReader::getLength() +int AUD_DelayReader::getLength() const { int len = m_reader->getLength(); if(len < 0) return len; - return len+m_delay; + return len + m_delay; } -int AUD_DelayReader::getPosition() +int AUD_DelayReader::getPosition() const { if(m_remdelay > 0) - return m_delay-m_remdelay; + return m_delay - m_remdelay; return m_reader->getPosition() + m_delay; } @@ -80,26 +71,41 @@ void AUD_DelayReader::read(int & length, sample_t* & buffer) AUD_Specs specs = m_reader->getSpecs(); int samplesize = AUD_SAMPLE_SIZE(specs); - if(m_buffer->getSize() < length * samplesize) - m_buffer->resize(length * samplesize); + if(m_buffer.getSize() < length * samplesize) + { + m_buffer.resize(length * samplesize); + m_empty = false; + } + + buffer = m_buffer.getBuffer(); if(length > m_remdelay) { - memset(m_buffer->getBuffer(), 0, m_remdelay * samplesize); + if(!m_empty) + memset(buffer, 0, m_remdelay * samplesize); + int len = length - m_remdelay; - m_reader->read(len, buffer); - memcpy(m_buffer->getBuffer() + m_remdelay * specs.channels, - buffer, len * samplesize); + sample_t* buf; + m_reader->read(len, buf); + + memcpy(buffer + m_remdelay * specs.channels, + buf, len * samplesize); + if(len < length-m_remdelay) length = m_remdelay + len; + m_remdelay = 0; + m_empty = false; } else { - memset(m_buffer->getBuffer(), 0, length * samplesize); + if(!m_empty) + { + memset(buffer, 0, length * samplesize); + m_empty = true; + } m_remdelay -= length; } - buffer = m_buffer->getBuffer(); } else m_reader->read(length, buffer); diff --git a/intern/audaspace/FX/AUD_DelayReader.h b/intern/audaspace/FX/AUD_DelayReader.h index 4662b455dfc..121842b0c6b 100644 --- a/intern/audaspace/FX/AUD_DelayReader.h +++ b/intern/audaspace/FX/AUD_DelayReader.h @@ -27,7 +27,7 @@ #define AUD_DELAYREADER #include "AUD_EffectReader.h" -class AUD_Buffer; +#include "AUD_Buffer.h" /** * This class reads another reader and changes it's delay. @@ -38,35 +38,38 @@ private: /** * The playback buffer. */ - AUD_Buffer *m_buffer; + AUD_Buffer m_buffer; /** * The delay level. */ - int m_delay; + const int m_delay; /** * The remaining delay for playback. */ int m_remdelay; + /** + * Whether the buffer is currently filled with zeros. + */ + bool m_empty; + + // hide copy constructor and operator= + AUD_DelayReader(const AUD_DelayReader&); + AUD_DelayReader& operator=(const AUD_DelayReader&); + public: /** * Creates a new delay reader. * \param reader The reader to read from. * \param delay The delay in seconds. - * \exception AUD_Exception Thrown if the reader specified is NULL. */ AUD_DelayReader(AUD_IReader* reader, float delay); - /** - * Destroys the reader. - */ - virtual ~AUD_DelayReader(); - virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); + virtual int getLength() const; + virtual int getPosition() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/FX/AUD_DoubleFactory.cpp b/intern/audaspace/FX/AUD_DoubleFactory.cpp new file mode 100644 index 00000000000..9f625d0763f --- /dev/null +++ b/intern/audaspace/FX/AUD_DoubleFactory.cpp @@ -0,0 +1,50 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_DoubleFactory.h" +#include "AUD_DoubleReader.h" + +AUD_DoubleFactory::AUD_DoubleFactory(AUD_IFactory* factory1, AUD_IFactory* factory2) : + m_factory1(factory1), m_factory2(factory2) +{ +} + +AUD_IReader* AUD_DoubleFactory::createReader() const +{ + AUD_IReader* reader1 = m_factory1->createReader(); + AUD_IReader* reader2; + + try + { + reader2 = m_factory2->createReader(); + } + catch(AUD_Exception&) + { + delete reader1; + throw; + } + + return new AUD_DoubleReader(reader1, reader2); +} diff --git a/intern/audaspace/FX/AUD_SquareReader.h b/intern/audaspace/FX/AUD_DoubleFactory.h index 63dda351445..f2e83b2e27a 100644 --- a/intern/audaspace/FX/AUD_SquareReader.h +++ b/intern/audaspace/FX/AUD_DoubleFactory.h @@ -23,43 +23,41 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#ifndef AUD_SQUAREREADER -#define AUD_SQUAREREADER +#ifndef AUD_DOUBLEFACTORY +#define AUD_DOUBLEFACTORY -#include "AUD_EffectReader.h" -class AUD_Buffer; +#include "AUD_IFactory.h" /** - * This class changes another signal into a square signal. + * This factory plays two other factories behind each other. + * \note Readers from the underlying factories must have the same sample rate and channel count. */ -class AUD_SquareReader : public AUD_EffectReader +class AUD_DoubleFactory : public AUD_IFactory { private: /** - * The playback buffer. + * First played factory. */ - AUD_Buffer *m_buffer; + AUD_IFactory* m_factory1; /** - * The threshold level. + * Second played factory. */ - float m_threshold; + AUD_IFactory* m_factory2; -public: - /** - * Creates a new square reader. - * \param reader The reader to read from. - * \param threshold The size of the buffer. - * \exception AUD_Exception Thrown if the reader specified is NULL. - */ - AUD_SquareReader(AUD_IReader* reader, float threshold); + // hide copy constructor and operator= + AUD_DoubleFactory(const AUD_DoubleFactory&); + AUD_DoubleFactory& operator=(const AUD_DoubleFactory&); +public: /** - * Destroys the reader. + * Creates a new double factory. + * \param factory1 The first input factory. + * \param factory2 The second input factory. */ - virtual ~AUD_SquareReader(); + AUD_DoubleFactory(AUD_IFactory* factory1, AUD_IFactory* factory2); - virtual void read(int & length, sample_t* & buffer); + virtual AUD_IReader* createReader() const; }; -#endif //AUD_SQUAREREADER +#endif //AUD_DOUBLEFACTORY diff --git a/intern/audaspace/FX/AUD_DoubleReader.cpp b/intern/audaspace/FX/AUD_DoubleReader.cpp index 1e51a094427..5c6ca6a1fc5 100644 --- a/intern/audaspace/FX/AUD_DoubleReader.cpp +++ b/intern/audaspace/FX/AUD_DoubleReader.cpp @@ -24,80 +24,51 @@ */ #include "AUD_DoubleReader.h" -#include "AUD_Buffer.h" #include <cstring> +static const char* specs_error = "AUD_DoubleReader: Both readers have to have " + "the same specs."; + AUD_DoubleReader::AUD_DoubleReader(AUD_IReader* reader1, AUD_IReader* reader2) : - m_reader1(reader1), m_reader2(reader2) + m_reader1(reader1), m_reader2(reader2), m_finished1(false) { - try - { - if(!reader1) - AUD_THROW(AUD_ERROR_READER); - - if(!reader2) - AUD_THROW(AUD_ERROR_READER); - - AUD_Specs s1, s2; - s1 = reader1->getSpecs(); - s2 = reader2->getSpecs(); - if(memcmp(&s1, &s2, sizeof(AUD_Specs)) != 0) - AUD_THROW(AUD_ERROR_READER); - } - - catch(AUD_Exception) + AUD_Specs s1, s2; + s1 = reader1->getSpecs(); + s2 = reader2->getSpecs(); + if(memcmp(&s1, &s2, sizeof(AUD_Specs)) != 0) { - if(reader1) - { - delete reader1; AUD_DELETE("reader") - } - if(reader2) - { - delete reader2; AUD_DELETE("reader") - } - - throw; + delete reader1; + delete reader2; + AUD_THROW(AUD_ERROR_SPECS, specs_error); } - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - m_finished1 = false; } AUD_DoubleReader::~AUD_DoubleReader() { - delete m_reader1; AUD_DELETE("reader") - delete m_reader2; AUD_DELETE("reader") - delete m_buffer; AUD_DELETE("buffer") + delete m_reader1; + delete m_reader2; } -bool AUD_DoubleReader::isSeekable() +bool AUD_DoubleReader::isSeekable() const { - return false; + return m_reader1->isSeekable() && m_reader2->isSeekable(); } void AUD_DoubleReader::seek(int position) { - int length1 = m_reader1->getLength(); + m_reader1->seek(position); - if(position < 0) - position = 0; + int pos1 = m_reader1->getPosition(); - if(position < length1) - { - m_reader1->seek(position); - m_reader2->seek(0); - m_finished1 = false; - } + if((m_finished1 = (pos1 < position))) + m_reader2->seek(position - pos1); else - { - m_reader2->seek(position-length1); - m_finished1 = true; - } + m_reader2->seek(0); } -int AUD_DoubleReader::getLength() +int AUD_DoubleReader::getLength() const { int len1 = m_reader1->getLength(); int len2 = m_reader2->getLength(); @@ -106,49 +77,45 @@ int AUD_DoubleReader::getLength() return len1 + len2; } -int AUD_DoubleReader::getPosition() +int AUD_DoubleReader::getPosition() const { return m_reader1->getPosition() + m_reader2->getPosition(); } -AUD_Specs AUD_DoubleReader::getSpecs() +AUD_Specs AUD_DoubleReader::getSpecs() const { return m_reader1->getSpecs(); } -AUD_ReaderType AUD_DoubleReader::getType() -{ - if(m_reader1->getType() == AUD_TYPE_BUFFER && - m_reader2->getType() == AUD_TYPE_BUFFER) - return AUD_TYPE_BUFFER; - return AUD_TYPE_STREAM; -} - -bool AUD_DoubleReader::notify(AUD_Message &message) -{ - return m_reader1->notify(message) | m_reader2->notify(message); -} - void AUD_DoubleReader::read(int & length, sample_t* & buffer) { if(!m_finished1) { int len = length; m_reader1->read(len, buffer); + if(len < length) { AUD_Specs specs = m_reader1->getSpecs(); int samplesize = AUD_SAMPLE_SIZE(specs); - if(m_buffer->getSize() < length * samplesize) - m_buffer->resize(length * samplesize); - memcpy(m_buffer->getBuffer(), buffer, len * samplesize); + + if(m_buffer.getSize() < length * samplesize) + m_buffer.resize(length * samplesize); + + sample_t* buf = buffer; + buffer = m_buffer.getBuffer(); + + memcpy(buffer, buf, len * samplesize); + len = length - len; length -= len; - m_reader2->read(len, buffer); - memcpy(m_buffer->getBuffer() + length * specs.channels, buffer, + m_reader2->read(len, buf); + + memcpy(buffer + length * specs.channels, buf, len * samplesize); + length += len; - buffer = m_buffer->getBuffer(); + m_finished1 = true; } } diff --git a/intern/audaspace/FX/AUD_DoubleReader.h b/intern/audaspace/FX/AUD_DoubleReader.h index d82b81ec0ba..d80ba33dfe3 100644 --- a/intern/audaspace/FX/AUD_DoubleReader.h +++ b/intern/audaspace/FX/AUD_DoubleReader.h @@ -27,7 +27,7 @@ #define AUD_DOUBLEREADER #include "AUD_IReader.h" -class AUD_Buffer; +#include "AUD_Buffer.h" /** * This reader plays two readers with the same specs sequently. @@ -53,15 +53,18 @@ private: /** * The playback buffer for the intersecting part. */ - AUD_Buffer* m_buffer; + AUD_Buffer m_buffer; + + // hide copy constructor and operator= + AUD_DoubleReader(const AUD_DoubleReader&); + AUD_DoubleReader& operator=(const AUD_DoubleReader&); public: /** * Creates a new ping pong reader. * \param reader1 The first reader to read from. * \param reader2 The second reader to read from. - * \exception AUD_Exception Thrown if one of the reader specified is NULL - * or the specs from the readers differ. + * \exception AUD_Exception Thrown if the specs from the readers differ. */ AUD_DoubleReader(AUD_IReader* reader1, AUD_IReader* reader2); @@ -70,13 +73,11 @@ public: */ virtual ~AUD_DoubleReader(); - virtual bool isSeekable(); + virtual bool isSeekable() const; virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); - virtual AUD_Specs getSpecs(); - virtual AUD_ReaderType getType(); - virtual bool notify(AUD_Message &message); + virtual int getLength() const; + virtual int getPosition() const; + virtual AUD_Specs getSpecs() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/FX/AUD_EffectFactory.cpp b/intern/audaspace/FX/AUD_EffectFactory.cpp index 882499416b7..eda4e4e04b2 100644 --- a/intern/audaspace/FX/AUD_EffectFactory.cpp +++ b/intern/audaspace/FX/AUD_EffectFactory.cpp @@ -26,25 +26,16 @@ #include "AUD_EffectFactory.h" #include "AUD_IReader.h" -AUD_IReader* AUD_EffectFactory::getReader() -{ - if(m_factory != 0) - return m_factory->createReader(); - - return 0; -} - AUD_EffectFactory::AUD_EffectFactory(AUD_IFactory* factory) { m_factory = factory; } -void AUD_EffectFactory::setFactory(AUD_IFactory* factory) +AUD_EffectFactory::~AUD_EffectFactory() { - m_factory = factory; } -AUD_IFactory* AUD_EffectFactory::getFactory() +AUD_IFactory* AUD_EffectFactory::getFactory() const { return m_factory; } diff --git a/intern/audaspace/FX/AUD_EffectFactory.h b/intern/audaspace/FX/AUD_EffectFactory.h index 67259b9e6c3..fd3746d0da3 100644 --- a/intern/audaspace/FX/AUD_EffectFactory.h +++ b/intern/audaspace/FX/AUD_EffectFactory.h @@ -34,6 +34,11 @@ */ class AUD_EffectFactory : public AUD_IFactory { +private: + // hide copy constructor and operator= + AUD_EffectFactory(const AUD_EffectFactory&); + AUD_EffectFactory& operator=(const AUD_EffectFactory&); + protected: /** * If there is no reader it is created out of this factory. @@ -44,9 +49,12 @@ protected: * Returns the reader created out of the factory. * This method can be used for the createReader function of the implementing * classes. - * \return The reader created out of the factory or NULL if there is none. + * \return The reader created out of the factory. */ - AUD_IReader* getReader(); + inline AUD_IReader* getReader() const + { + return m_factory->createReader(); + } public: /** @@ -58,19 +66,13 @@ public: /** * Destroys the factory. */ - virtual ~AUD_EffectFactory() {} - - /** - * Sets the input factory. - * \param factory The input factory. - */ - void setFactory(AUD_IFactory* factory); + virtual ~AUD_EffectFactory(); /** * Returns the saved factory. * \return The factory or NULL if there has no factory been saved. */ - AUD_IFactory* getFactory(); + AUD_IFactory* getFactory() const; }; #endif //AUD_EFFECTFACTORY diff --git a/intern/audaspace/FX/AUD_EffectReader.cpp b/intern/audaspace/FX/AUD_EffectReader.cpp index 47026b88440..b54ca279088 100644 --- a/intern/audaspace/FX/AUD_EffectReader.cpp +++ b/intern/audaspace/FX/AUD_EffectReader.cpp @@ -27,17 +27,15 @@ AUD_EffectReader::AUD_EffectReader(AUD_IReader* reader) { - if(!reader) - AUD_THROW(AUD_ERROR_READER); m_reader = reader; } AUD_EffectReader::~AUD_EffectReader() { - delete m_reader; AUD_DELETE("reader") + delete m_reader; } -bool AUD_EffectReader::isSeekable() +bool AUD_EffectReader::isSeekable() const { return m_reader->isSeekable(); } @@ -47,31 +45,21 @@ void AUD_EffectReader::seek(int position) m_reader->seek(position); } -int AUD_EffectReader::getLength() +int AUD_EffectReader::getLength() const { return m_reader->getLength(); } -int AUD_EffectReader::getPosition() +int AUD_EffectReader::getPosition() const { return m_reader->getPosition(); } -AUD_Specs AUD_EffectReader::getSpecs() +AUD_Specs AUD_EffectReader::getSpecs() const { return m_reader->getSpecs(); } -AUD_ReaderType AUD_EffectReader::getType() -{ - return m_reader->getType(); -} - -bool AUD_EffectReader::notify(AUD_Message &message) -{ - return m_reader->notify(message); -} - void AUD_EffectReader::read(int & length, sample_t* & buffer) { m_reader->read(length, buffer); diff --git a/intern/audaspace/FX/AUD_EffectReader.h b/intern/audaspace/FX/AUD_EffectReader.h index f64bf34077d..c447f79bc6e 100644 --- a/intern/audaspace/FX/AUD_EffectReader.h +++ b/intern/audaspace/FX/AUD_EffectReader.h @@ -34,6 +34,11 @@ */ class AUD_EffectReader : public AUD_IReader { +private: + // hide copy constructor and operator= + AUD_EffectReader(const AUD_EffectReader&); + AUD_EffectReader& operator=(const AUD_EffectReader&); + protected: /** * The reader to read from. @@ -44,7 +49,6 @@ public: /** * Creates a new effect reader. * \param reader The reader to read from. - * \exception AUD_Exception Thrown if the reader specified is NULL. */ AUD_EffectReader(AUD_IReader* reader); @@ -53,13 +57,11 @@ public: */ virtual ~AUD_EffectReader(); - virtual bool isSeekable(); + virtual bool isSeekable() const; virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); - virtual AUD_Specs getSpecs(); - virtual AUD_ReaderType getType(); - virtual bool notify(AUD_Message &message); + virtual int getLength() const; + virtual int getPosition() const; + virtual AUD_Specs getSpecs() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.cpp b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp index c3b2c3f24fe..4777da70404 100644 --- a/intern/audaspace/FX/AUD_EnvelopeFactory.cpp +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp @@ -24,7 +24,31 @@ */ #include "AUD_EnvelopeFactory.h" -#include "AUD_EnvelopeReader.h" +#include "AUD_CallbackIIRFilterReader.h" + +#include <cmath> + +struct EnvelopeParameters +{ + float attack; + float release; + float threshold; + float arthreshold; +}; + +sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param) +{ + float in = fabs(reader->x(0)); + float out = reader->y(-1); + if(in < param->threshold) + in = 0.0f; + return (in > out ? param->attack : param->release) * (out - in) + in; +} + +void endEnvelopeFilter(EnvelopeParameters* param) +{ + delete param; +} AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, float release, float threshold, @@ -33,26 +57,22 @@ AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, m_attack(attack), m_release(release), m_threshold(threshold), - m_arthreshold(arthreshold) {} - -AUD_EnvelopeFactory::AUD_EnvelopeFactory(float attack, float release, - float threshold, float arthreshold) : - AUD_EffectFactory(0), - m_attack(attack), - m_release(release), - m_threshold(threshold), - m_arthreshold(arthreshold) {} + m_arthreshold(arthreshold) +{ +} -AUD_IReader* AUD_EnvelopeFactory::createReader() +AUD_IReader* AUD_EnvelopeFactory::createReader() const { AUD_IReader* reader = getReader(); - if(reader != 0) - { - reader = new AUD_EnvelopeReader(reader, m_attack, m_release, - m_threshold, m_arthreshold); - AUD_NEW("reader") - } + EnvelopeParameters* param = new EnvelopeParameters(); + param->arthreshold = m_arthreshold; + param->attack = pow(m_arthreshold, 1.0f/(reader->getSpecs().rate * m_attack)); + param->release = pow(m_arthreshold, 1.0f/(reader->getSpecs().rate * m_release)); + param->threshold = m_threshold; - return reader; + return new AUD_CallbackIIRFilterReader(reader, 1, 2, + (doFilterIIR) envelopeFilter, + (endFilterIIR) endEnvelopeFilter, + param); } diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.h b/intern/audaspace/FX/AUD_EnvelopeFactory.h index c79e5472e30..c31c6727d03 100644 --- a/intern/audaspace/FX/AUD_EnvelopeFactory.h +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.h @@ -37,22 +37,26 @@ private: /** * The attack value in seconds. */ - float m_attack; + const float m_attack; /** * The release value in seconds. */ - float m_release; + const float m_release; /** * The threshold value. */ - float m_threshold; + const float m_threshold; /** * The attack/release threshold value. */ - float m_arthreshold; + const float m_arthreshold; + + // hide copy constructor and operator= + AUD_EnvelopeFactory(const AUD_EnvelopeFactory&); + AUD_EnvelopeFactory& operator=(const AUD_EnvelopeFactory&); public: /** @@ -66,17 +70,7 @@ public: AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, float release, float threshold, float arthreshold); - /** - * Creates a new envelope factory. - * \param attack The attack value in seconds. - * \param release The release value in seconds. - * \param threshold The threshold value. - * \param arthreshold The attack/release threshold value. - */ - AUD_EnvelopeFactory(float attack, float release, float threshold, - float arthreshold); - - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_ENVELOPEFACTORY diff --git a/intern/audaspace/FX/AUD_EnvelopeReader.cpp b/intern/audaspace/FX/AUD_EnvelopeReader.cpp deleted file mode 100644 index 71ccbfd6503..00000000000 --- a/intern/audaspace/FX/AUD_EnvelopeReader.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN LGPL LICENSE BLOCK ***** - * - * Copyright 2009 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 Lesser General Public License as published by - * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#include "AUD_EnvelopeReader.h" -#include "AUD_Buffer.h" - -#include <cstring> -#include <cmath> - -AUD_EnvelopeReader::AUD_EnvelopeReader(AUD_IReader* reader, float attack, - float release, float threshold, - float arthreshold) : - AUD_EffectReader(reader), - m_threshold(threshold) -{ - AUD_Specs specs = reader->getSpecs(); - int samplesize = AUD_SAMPLE_SIZE(specs); - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - - m_envelopes = new AUD_Buffer(samplesize); - AUD_NEW("buffer") - memset(m_envelopes->getBuffer(), 0, samplesize); - - m_bAttack = pow(arthreshold, 1.0f/(specs.rate * attack)); - m_bRelease = pow(arthreshold, 1.0f/(specs.rate * release)); -} - -AUD_EnvelopeReader::~AUD_EnvelopeReader() -{ - delete m_buffer; AUD_DELETE("buffer") - delete m_envelopes; AUD_DELETE("buffer") -} - -void AUD_EnvelopeReader::read(int & length, sample_t* & buffer) -{ - sample_t* buf; - sample_t* envelopes; - envelopes = m_envelopes->getBuffer(); - - AUD_Specs specs = m_reader->getSpecs(); - - m_reader->read(length, buf); - if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs)) - m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); - - buffer = m_buffer->getBuffer(); - - sample_t value; - - for(int channel = 0; channel < specs.channels; channel++) - { - for(int i = 0; i < length; i++) - { - value = fabs(buf[i * specs.channels + channel]); - if(value < m_threshold) - value = 0.0f; - - buffer[i * specs.channels + channel] = envelopes[channel] = - ((value > envelopes[channel]) ? m_bAttack : m_bRelease) * - (envelopes[channel] - value) + value; - } - } -} diff --git a/intern/audaspace/FX/AUD_EnvelopeReader.h b/intern/audaspace/FX/AUD_EnvelopeReader.h deleted file mode 100644 index ff9dd23d34c..00000000000 --- a/intern/audaspace/FX/AUD_EnvelopeReader.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN LGPL LICENSE BLOCK ***** - * - * Copyright 2009 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 Lesser General Public License as published by - * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#ifndef AUD_ENVELOPEREADER -#define AUD_ENVELOPEREADER - -#include "AUD_EffectReader.h" -class AUD_Buffer; - -/** - * This class represents an envelope follower. - */ -class AUD_EnvelopeReader : public AUD_EffectReader -{ -private: - /** - * The playback buffer. - */ - AUD_Buffer *m_buffer; - - /** - * The last envelopes buffer. - */ - AUD_Buffer *m_envelopes; - - /** - * Attack b value. - */ - float m_bAttack; - - /** - * Release b value. - */ - float m_bRelease; - - /** - * Threshold value. - */ - float m_threshold; - -public: - /** - * Creates a new envelope reader. - * \param reader The reader to read from. - * \param attack The attack value in seconds. - * \param release The release value in seconds. - * \param threshold The threshold value. - * \param arthreshold The attack/release threshold value. - * \exception AUD_Exception Thrown if the reader specified is NULL. - */ - AUD_EnvelopeReader(AUD_IReader* reader, float attack, float release, - float threshold, float arthreshold); - - /** - * Destroys the reader. - */ - virtual ~AUD_EnvelopeReader(); - - virtual void read(int & length, sample_t* & buffer); -}; - -#endif //AUD_ENVELOPEREADER diff --git a/intern/audaspace/FX/AUD_FaderFactory.cpp b/intern/audaspace/FX/AUD_FaderFactory.cpp index 4357e11bd43..bbe9319c928 100644 --- a/intern/audaspace/FX/AUD_FaderFactory.cpp +++ b/intern/audaspace/FX/AUD_FaderFactory.cpp @@ -31,54 +31,26 @@ AUD_FaderFactory::AUD_FaderFactory(AUD_IFactory* factory, AUD_FadeType type, AUD_EffectFactory(factory), m_type(type), m_start(start), - m_length(length) {} - -AUD_FaderFactory::AUD_FaderFactory(AUD_FadeType type, - float start, float length) : - AUD_EffectFactory(0), - m_type(type), - m_start(start), - m_length(length) {} - -AUD_FadeType AUD_FaderFactory::getType() + m_length(length) { - return m_type; } -void AUD_FaderFactory::setType(AUD_FadeType type) +AUD_FadeType AUD_FaderFactory::getType() const { - m_type = type; + return m_type; } -float AUD_FaderFactory::getStart() +float AUD_FaderFactory::getStart() const { return m_start; } -void AUD_FaderFactory::setStart(float start) -{ - m_start = start; -} - -float AUD_FaderFactory::getLength() +float AUD_FaderFactory::getLength() const { return m_length; } -void AUD_FaderFactory::setLength(float length) +AUD_IReader* AUD_FaderFactory::createReader() const { - m_length = length; -} - -AUD_IReader* AUD_FaderFactory::createReader() -{ - AUD_IReader* reader = getReader(); - - if(reader != 0) - { - reader = new AUD_FaderReader(reader, m_type, m_start, m_length); - AUD_NEW("reader") - } - - return reader; + return new AUD_FaderReader(getReader(), m_type, m_start, m_length); } diff --git a/intern/audaspace/FX/AUD_FaderFactory.h b/intern/audaspace/FX/AUD_FaderFactory.h index 4999ccac8f1..af5d18538ea 100644 --- a/intern/audaspace/FX/AUD_FaderFactory.h +++ b/intern/audaspace/FX/AUD_FaderFactory.h @@ -39,17 +39,21 @@ private: /** * The fading type. */ - AUD_FadeType m_type; + const AUD_FadeType m_type; /** * The fading start. */ - float m_start; + const float m_start; /** * The fading length. */ - float m_length; + const float m_length; + + // hide copy constructor and operator= + AUD_FaderFactory(const AUD_FaderFactory&); + AUD_FaderFactory& operator=(const AUD_FaderFactory&); public: /** @@ -59,53 +63,26 @@ public: * \param start The time where fading should start in seconds. * \param length How long fading should last in seconds. */ - AUD_FaderFactory(AUD_IFactory* factory = 0, + AUD_FaderFactory(AUD_IFactory* factory, AUD_FadeType type = AUD_FADE_IN, float start = 0.0f, float length = 1.0f); /** - * Creates a new fader factory. - * \param type The fading type. - * \param start The time where fading should start in seconds. - * \param length How long fading should last in seconds. - */ - AUD_FaderFactory(AUD_FadeType type = AUD_FADE_IN, - float start = 0.0f, float length = 1.0f); - - /** * Returns the fading type. */ - AUD_FadeType getType(); - - /** - * Sets the fading type. - * \param type The new fading type: AUD_FADE_IN or AUD_FADE_OUT. - */ - void setType(AUD_FadeType type); + AUD_FadeType getType() const; /** * Returns the fading start. */ - float getStart(); - - /** - * Sets the fading start. - * \param start The new fading start. - */ - void setStart(float start); + float getStart() const; /** * Returns the fading length. */ - float getLength(); - - /** - * Sets the fading length. - * \param start The new fading length. - */ - void setLength(float length); + float getLength() const; - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_FADERFACTORY diff --git a/intern/audaspace/FX/AUD_FaderReader.cpp b/intern/audaspace/FX/AUD_FaderReader.cpp index 4e919fff323..2292fa06102 100644 --- a/intern/audaspace/FX/AUD_FaderReader.cpp +++ b/intern/audaspace/FX/AUD_FaderReader.cpp @@ -24,7 +24,6 @@ */ #include "AUD_FaderReader.h" -#include "AUD_Buffer.h" #include <cstring> @@ -33,19 +32,9 @@ AUD_FaderReader::AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type, AUD_EffectReader(reader), m_type(type), m_start(start), - m_length(length) + m_length(length), + m_empty(true) { - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") -} - -AUD_FaderReader::~AUD_FaderReader() -{ - delete m_buffer; AUD_DELETE("buffer") -} - -bool AUD_FaderReader::notify(AUD_Message &message) -{ - return m_reader->notify(message); } void AUD_FaderReader::read(int & length, sample_t* & buffer) @@ -56,28 +45,50 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer) m_reader->read(length, buffer); - if(m_buffer->getSize() < length * samplesize) - m_buffer->resize(length * samplesize); - if((position + length) / (float)specs.rate <= m_start) { if(m_type != AUD_FADE_OUT) { - buffer = m_buffer->getBuffer(); - memset(buffer, 0, length * samplesize); + if(m_buffer.getSize() < length * samplesize) + { + m_buffer.resize(length * samplesize); + m_empty = false; + } + + buffer = m_buffer.getBuffer(); + + if(!m_empty) + { + memset(buffer, 0, length * samplesize); + m_empty = true; + } } } else if(position / (float)specs.rate >= m_start+m_length) { if(m_type == AUD_FADE_OUT) { - buffer = m_buffer->getBuffer(); - memset(buffer, 0, length * samplesize); + if(m_buffer.getSize() < length * samplesize) + { + m_buffer.resize(length * samplesize); + m_empty = false; + } + + buffer = m_buffer.getBuffer(); + + if(!m_empty) + { + memset(buffer, 0, length * samplesize); + m_empty = true; + } } } else { - sample_t* buf = m_buffer->getBuffer(); + if(m_buffer.getSize() < length * samplesize) + m_buffer.resize(length * samplesize); + + sample_t* buf = m_buffer.getBuffer(); float volume = 1.0f; for(int i = 0; i < length * specs.channels; i++) @@ -98,5 +109,6 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer) } buffer = buf; + m_empty = false; } } diff --git a/intern/audaspace/FX/AUD_FaderReader.h b/intern/audaspace/FX/AUD_FaderReader.h index a75ac6e7a47..d9d685af956 100644 --- a/intern/audaspace/FX/AUD_FaderReader.h +++ b/intern/audaspace/FX/AUD_FaderReader.h @@ -27,7 +27,7 @@ #define AUD_FADERREADER #include "AUD_EffectReader.h" -class AUD_Buffer; +#include "AUD_Buffer.h" /** * This class fades another reader. @@ -38,24 +38,33 @@ class AUD_FaderReader : public AUD_EffectReader { private: /** - * The playback buffer. - */ - AUD_Buffer *m_buffer; - - /** * The fading type. */ - AUD_FadeType m_type; + const AUD_FadeType m_type; /** * The fading start. */ - float m_start; + const float m_start; /** * The fading length. */ - float m_length; + const float m_length; + + /** + * The playback buffer. + */ + AUD_Buffer m_buffer; + + /** + * Whether the buffer is empty. + */ + bool m_empty; + + // hide copy constructor and operator= + AUD_FaderReader(const AUD_FaderReader&); + AUD_FaderReader& operator=(const AUD_FaderReader&); public: /** @@ -63,17 +72,10 @@ public: * \param type The fading type. * \param start The time where fading should start in seconds. * \param length How long fading should last in seconds. - * \exception AUD_Exception Thrown if the reader specified is NULL. */ AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type, float start,float length); - /** - * Destroys the reader. - */ - virtual ~AUD_FaderReader(); - - virtual bool notify(AUD_Message &message); virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/FX/AUD_HighpassFactory.cpp b/intern/audaspace/FX/AUD_HighpassFactory.cpp index 384d36beab7..d222e7f615e 100644 --- a/intern/audaspace/FX/AUD_HighpassFactory.cpp +++ b/intern/audaspace/FX/AUD_HighpassFactory.cpp @@ -24,28 +24,38 @@ */ #include "AUD_HighpassFactory.h" -#include "AUD_HighpassReader.h" +#include "AUD_IIRFilterReader.h" + +#include <cmath> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif AUD_HighpassFactory::AUD_HighpassFactory(AUD_IFactory* factory, float frequency, float Q) : AUD_EffectFactory(factory), m_frequency(frequency), - m_Q(Q) {} - -AUD_HighpassFactory::AUD_HighpassFactory(float frequency, float Q) : - AUD_EffectFactory(0), - m_frequency(frequency), - m_Q(Q) {} + m_Q(Q) +{ +} -AUD_IReader* AUD_HighpassFactory::createReader() +AUD_IReader* AUD_HighpassFactory::createReader() const { AUD_IReader* reader = getReader(); - if(reader != 0) - { - reader = new AUD_HighpassReader(reader, m_frequency, m_Q); - AUD_NEW("reader") - } + // calculate coefficients + float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate; + float alpha = sin(w0) / (2 * m_Q); + float norm = 1 + alpha; + float c = cos(w0); + std::vector<float> a, b; + a.push_back(1); + a.push_back(-2 * c / norm); + a.push_back((1 - alpha) / norm); + b.push_back((1 + c) / (2 * norm)); + b.push_back((-1 - c) / norm); + b.push_back(b[0]); - return reader; + return new AUD_IIRFilterReader(reader, b, a); } diff --git a/intern/audaspace/FX/AUD_HighpassFactory.h b/intern/audaspace/FX/AUD_HighpassFactory.h index 5e31053ed6c..1220157a776 100644 --- a/intern/audaspace/FX/AUD_HighpassFactory.h +++ b/intern/audaspace/FX/AUD_HighpassFactory.h @@ -37,12 +37,16 @@ private: /** * The attack value in seconds. */ - float m_frequency; + const float m_frequency; /** * The Q factor. */ - float m_Q; + const float m_Q; + + // hide copy constructor and operator= + AUD_HighpassFactory(const AUD_HighpassFactory&); + AUD_HighpassFactory& operator=(const AUD_HighpassFactory&); public: /** @@ -53,14 +57,7 @@ public: */ AUD_HighpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0f); - /** - * Creates a new highpass factory. - * \param frequency The cutoff frequency. - * \param Q The Q factor. - */ - AUD_HighpassFactory(float frequency, float Q = 1.0f); - - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_HIGHPASSFACTORY diff --git a/intern/audaspace/FX/AUD_HighpassReader.cpp b/intern/audaspace/FX/AUD_HighpassReader.cpp deleted file mode 100644 index 36b1bb8082e..00000000000 --- a/intern/audaspace/FX/AUD_HighpassReader.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN LGPL LICENSE BLOCK ***** - * - * Copyright 2009 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 Lesser General Public License as published by - * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#include "AUD_HighpassReader.h" -#include "AUD_Buffer.h" - -#include <cstring> -#include <cmath> - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#define CC channels + channel - -AUD_HighpassReader::AUD_HighpassReader(AUD_IReader* reader, float frequency, - float Q) : - AUD_EffectReader(reader) -{ - AUD_Specs specs = reader->getSpecs(); - int samplesize = AUD_SAMPLE_SIZE(specs); - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - - m_outvalues = new AUD_Buffer(samplesize * AUD_HIGHPASS_ORDER); - AUD_NEW("buffer") - memset(m_outvalues->getBuffer(), 0, samplesize * AUD_HIGHPASS_ORDER); - - m_invalues = new AUD_Buffer(samplesize * AUD_HIGHPASS_ORDER); - AUD_NEW("buffer") - memset(m_invalues->getBuffer(), 0, samplesize * AUD_HIGHPASS_ORDER); - - m_position = 0; - - // calculate coefficients - float w0 = 2 * M_PI * frequency / specs.rate; - float alpha = sin(w0) / (2 * Q); - float norm = 1 + alpha; - m_coeff[0][0] = 0; - m_coeff[0][1] = -2 * cos(w0) / norm; - m_coeff[0][2] = (1 - alpha) / norm; - m_coeff[1][2] = m_coeff[1][0] = (1 + cos(w0)) / (2 * norm); - m_coeff[1][1] = (-1 - cos(w0)) / norm; -} - -AUD_HighpassReader::~AUD_HighpassReader() -{ - delete m_buffer; AUD_DELETE("buffer") - - delete m_outvalues; AUD_DELETE("buffer") - delete m_invalues; AUD_DELETE("buffer"); -} - -void AUD_HighpassReader::read(int & length, sample_t* & buffer) -{ - sample_t* buf; - sample_t* outvalues; - sample_t* invalues; - - outvalues = m_outvalues->getBuffer(); - invalues = m_invalues->getBuffer(); - - AUD_Specs specs = m_reader->getSpecs(); - - m_reader->read(length, buf); - - if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs)) - m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); - - buffer = m_buffer->getBuffer(); - int channels = specs.channels; - - for(int channel = 0; channel < channels; channel++) - { - for(int i = 0; i < length; i++) - { - invalues[m_position * CC] = buf[i * CC]; - outvalues[m_position * CC] = 0; - - for(int j = 0; j < AUD_HIGHPASS_ORDER; j++) - { - outvalues[m_position * CC] += m_coeff[1][j] * - invalues[((m_position + j) % AUD_HIGHPASS_ORDER) * CC] - - m_coeff[0][j] * - outvalues[((m_position + j) % AUD_HIGHPASS_ORDER) * CC]; - } - - buffer[i * CC] = outvalues[m_position * CC]; - - m_position = (m_position + AUD_HIGHPASS_ORDER-1) % - AUD_HIGHPASS_ORDER; - } - } -} diff --git a/intern/audaspace/FX/AUD_HighpassReader.h b/intern/audaspace/FX/AUD_HighpassReader.h deleted file mode 100644 index dc28a62e45b..00000000000 --- a/intern/audaspace/FX/AUD_HighpassReader.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN LGPL LICENSE BLOCK ***** - * - * Copyright 2009 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 Lesser General Public License as published by - * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#ifndef AUD_HIGHPASSREADER -#define AUD_HIGHPASSREADER - -#include "AUD_EffectReader.h" -class AUD_Buffer; - -#define AUD_HIGHPASS_ORDER 3 - -/** - * This class represents a highpass filter. - */ -class AUD_HighpassReader : public AUD_EffectReader -{ -private: - /** - * The playback buffer. - */ - AUD_Buffer *m_buffer; - - /** - * The last out values buffer. - */ - AUD_Buffer *m_outvalues; - - /** - * The last in values buffer. - */ - AUD_Buffer *m_invalues; - - /** - * The position for buffer cycling. - */ - int m_position; - - /** - * Filter coefficients. - */ - float m_coeff[2][AUD_HIGHPASS_ORDER]; - -public: - /** - * Creates a new highpass reader. - * \param reader The reader to read from. - * \param frequency The cutoff frequency. - * \param Q The Q factor. - * \exception AUD_Exception Thrown if the reader specified is NULL. - */ - AUD_HighpassReader(AUD_IReader* reader, float frequency, float Q); - - /** - * Destroys the reader. - */ - virtual ~AUD_HighpassReader(); - - virtual void read(int & length, sample_t* & buffer); -}; - -#endif //AUD_HIGHPASSREADER diff --git a/intern/audaspace/FX/AUD_IIRFilterFactory.cpp b/intern/audaspace/FX/AUD_IIRFilterFactory.cpp new file mode 100644 index 00000000000..8cd49a03708 --- /dev/null +++ b/intern/audaspace/FX/AUD_IIRFilterFactory.cpp @@ -0,0 +1,39 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_IIRFilterFactory.h" +#include "AUD_IIRFilterReader.h" + +AUD_IIRFilterFactory::AUD_IIRFilterFactory(AUD_IFactory* factory, + std::vector<float> b, + std::vector<float> a) : + AUD_EffectFactory(factory), m_a(a), m_b(b) +{ +} + +AUD_IReader* AUD_IIRFilterFactory::createReader() const +{ + return new AUD_IIRFilterReader(getReader(), m_b, m_a); +} diff --git a/intern/audaspace/FX/AUD_IIRFilterFactory.h b/intern/audaspace/FX/AUD_IIRFilterFactory.h new file mode 100644 index 00000000000..567d4f354fe --- /dev/null +++ b/intern/audaspace/FX/AUD_IIRFilterFactory.h @@ -0,0 +1,66 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_IIRFILTERFACTORY +#define AUD_IIRFILTERFACTORY + +#include "AUD_EffectFactory.h" + +#include <vector> + +/** + * This factory creates a IIR filter reader. + */ +class AUD_IIRFilterFactory : public AUD_EffectFactory +{ +private: + /** + * Output filter coefficients. + */ + std::vector<float> m_a; + + /** + * Input filter coefficients. + */ + std::vector<float> m_b; + + // hide copy constructor and operator= + AUD_IIRFilterFactory(const AUD_IIRFilterFactory&); + AUD_IIRFilterFactory& operator=(const AUD_IIRFilterFactory&); + +public: + /** + * Creates a new IIR filter factory. + * \param factory The input factory. + * \param b The input filter coefficients. + * \param a The output filter coefficients. + */ + AUD_IIRFilterFactory(AUD_IFactory* factory, std::vector<float> b, + std::vector<float> a); + + virtual AUD_IReader* createReader() const; +}; + +#endif //AUD_IIRFILTERFACTORY diff --git a/intern/audaspace/FX/AUD_IIRFilterReader.cpp b/intern/audaspace/FX/AUD_IIRFilterReader.cpp new file mode 100644 index 00000000000..120c9f8d0ae --- /dev/null +++ b/intern/audaspace/FX/AUD_IIRFilterReader.cpp @@ -0,0 +1,50 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_IIRFilterReader.h" + +AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_IReader* reader, + std::vector<float> b, + std::vector<float> a) : + AUD_BaseIIRFilterReader(reader, b.size(), a.size()), m_a(a), m_b(b) +{ + for(int i = 1; i < m_a.size(); i++) + m_a[i] /= m_a[0]; + for(int i = 0; i < m_b.size(); i++) + m_b[i] /= m_a[0]; + m_a[0] = 1; +} + +sample_t AUD_IIRFilterReader::filter() +{ + sample_t out = 0; + + for(int i = 1; i < m_a.size(); i++) + out -= y(-i) * m_a[i]; + for(int i = 0; i < m_b.size(); i++) + out += x(-i) * m_b[i]; + + return out; +} diff --git a/intern/audaspace/FX/AUD_VolumeReader.h b/intern/audaspace/FX/AUD_IIRFilterReader.h index 489f85b10f2..303bc6d92df 100644 --- a/intern/audaspace/FX/AUD_VolumeReader.h +++ b/intern/audaspace/FX/AUD_IIRFilterReader.h @@ -23,44 +23,44 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#ifndef AUD_VOLUMEREADER -#define AUD_VOLUMEREADER +#ifndef AUD_IIRFILTERREADER +#define AUD_IIRFILTERREADER -#include "AUD_EffectReader.h" -class AUD_Buffer; +#include "AUD_BaseIIRFilterReader.h" + +#include <vector> /** - * This class reads another reader and changes it's volume. + * This class is for infinite impulse response filters with simple coefficients. */ -class AUD_VolumeReader : public AUD_EffectReader +class AUD_IIRFilterReader : public AUD_BaseIIRFilterReader { private: /** - * The playback buffer. + * Output filter coefficients. */ - AUD_Buffer *m_buffer; + std::vector<float> m_a; /** - * The volume level. + * Input filter coefficients. */ - float m_volume; + std::vector<float> m_b; + + // hide copy constructor and operator= + AUD_IIRFilterReader(const AUD_IIRFilterReader&); + AUD_IIRFilterReader& operator=(const AUD_IIRFilterReader&); public: /** - * Creates a new volume reader. + * Creates a new IIR filter reader. * \param reader The reader to read from. - * \param volume The size of the buffer. - * \exception AUD_Exception Thrown if the reader specified is NULL. - */ - AUD_VolumeReader(AUD_IReader* reader, float volume); - - /** - * Destroys the reader. + * \param b The input filter coefficients. + * \param a The output filter coefficients. */ - virtual ~AUD_VolumeReader(); + AUD_IIRFilterReader(AUD_IReader* reader, std::vector<float> b, + std::vector<float> a); - virtual bool notify(AUD_Message &message); - virtual void read(int & length, sample_t* & buffer); + virtual sample_t filter(); }; -#endif //AUD_VOLUMEREADER +#endif //AUD_IIRFILTERREADER diff --git a/intern/audaspace/FX/AUD_LimiterFactory.cpp b/intern/audaspace/FX/AUD_LimiterFactory.cpp index 6f19575240a..75501afcec3 100644 --- a/intern/audaspace/FX/AUD_LimiterFactory.cpp +++ b/intern/audaspace/FX/AUD_LimiterFactory.cpp @@ -31,37 +31,21 @@ AUD_LimiterFactory::AUD_LimiterFactory(AUD_IFactory* factory, float start, float end) : AUD_EffectFactory(factory), m_start(start), - m_end(end) {} - -float AUD_LimiterFactory::getStart() + m_end(end) { - return m_start; } -void AUD_LimiterFactory::setStart(float start) +float AUD_LimiterFactory::getStart() const { - m_start = start; + return m_start; } -float AUD_LimiterFactory::getEnd() +float AUD_LimiterFactory::getEnd() const { return m_end; } -void AUD_LimiterFactory::setEnd(float end) -{ - m_end = end; -} - -AUD_IReader* AUD_LimiterFactory::createReader() +AUD_IReader* AUD_LimiterFactory::createReader() const { - AUD_IReader* reader = getReader(); - - if(reader != 0) - { - reader = new AUD_LimiterReader(reader, m_start, m_end); - AUD_NEW("reader") - } - - return reader; + return new AUD_LimiterReader(getReader(), m_start, m_end); } diff --git a/intern/audaspace/FX/AUD_LimiterFactory.h b/intern/audaspace/FX/AUD_LimiterFactory.h index 588fea6eb4b..5d9491f60aa 100644 --- a/intern/audaspace/FX/AUD_LimiterFactory.h +++ b/intern/audaspace/FX/AUD_LimiterFactory.h @@ -37,12 +37,16 @@ private: /** * The start time. */ - float m_start; + const float m_start; /** * The end time. */ - float m_end; + const float m_end; + + // hide copy constructor and operator= + AUD_LimiterFactory(const AUD_LimiterFactory&); + AUD_LimiterFactory& operator=(const AUD_LimiterFactory&); public: /** @@ -52,33 +56,20 @@ public: * \param end The desired end time, a negative value signals that it should * play to the end. */ - AUD_LimiterFactory(AUD_IFactory* factory = 0, + AUD_LimiterFactory(AUD_IFactory* factory, float start = 0, float end = -1); /** * Returns the start time. */ - float getStart(); - - /** - * Sets the start time. - * \param start The new start time. - */ - void setStart(float start); + float getStart() const; /** * Returns the end time. */ - float getEnd(); - - /** - * Sets the end time. - * \param end The new end time, a negative value signals that it should play - * to the end. - */ - void setEnd(float end); + float getEnd() const; - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_LIMITERFACTORY diff --git a/intern/audaspace/FX/AUD_LimiterReader.cpp b/intern/audaspace/FX/AUD_LimiterReader.cpp index 05882369001..dd7301213c9 100644 --- a/intern/audaspace/FX/AUD_LimiterReader.cpp +++ b/intern/audaspace/FX/AUD_LimiterReader.cpp @@ -30,31 +30,27 @@ AUD_LimiterReader::AUD_LimiterReader(AUD_IReader* reader, float start, float end) : - AUD_EffectReader(reader) + AUD_EffectReader(reader), + m_start(int(start * reader->getSpecs().rate)), + m_end(int(end * reader->getSpecs().rate)) { - m_end = (int)(end * reader->getSpecs().rate); - - if(start <= 0) - m_start = 0; - else + if(m_start > 0) { - m_start = (int)(start * reader->getSpecs().rate); if(m_reader->isSeekable()) m_reader->seek(m_start); else { // skip first m_start samples by reading them - int length; + int length = AUD_DEFAULT_BUFFER_SIZE; sample_t* buffer; - for(int i = m_start; - i >= AUD_DEFAULT_BUFFER_SIZE; - i -= AUD_DEFAULT_BUFFER_SIZE) + for(int len = m_start; + length == AUD_DEFAULT_BUFFER_SIZE; + len -= AUD_DEFAULT_BUFFER_SIZE) { - length = AUD_DEFAULT_BUFFER_SIZE; + if(len < AUD_DEFAULT_BUFFER_SIZE) + length = len; m_reader->read(length, buffer); - length = i; } - m_reader->read(length, buffer); } } } @@ -64,18 +60,18 @@ void AUD_LimiterReader::seek(int position) m_reader->seek(position + m_start); } -int AUD_LimiterReader::getLength() +int AUD_LimiterReader::getLength() const { int len = m_reader->getLength(); - if(m_reader->getType() != AUD_TYPE_BUFFER || len < 0 || - (len > m_end && m_end >= 0)) + if(len < 0 || (len > m_end && m_end >= 0)) len = m_end; return len - m_start; } -int AUD_LimiterReader::getPosition() +int AUD_LimiterReader::getPosition() const { - return m_reader->getPosition() - m_start; + int pos = m_reader->getPosition(); + return AUD_MIN(pos, m_end) - m_start; } void AUD_LimiterReader::read(int & length, sample_t* & buffer) @@ -83,7 +79,7 @@ void AUD_LimiterReader::read(int & length, sample_t* & buffer) if(m_end >= 0) { int position = m_reader->getPosition(); - if(position+length > m_end) + if(position + length > m_end) length = m_end - position; if(length < 0) { diff --git a/intern/audaspace/FX/AUD_LimiterReader.h b/intern/audaspace/FX/AUD_LimiterReader.h index 9921f5ee1b0..59d6096dcba 100644 --- a/intern/audaspace/FX/AUD_LimiterReader.h +++ b/intern/audaspace/FX/AUD_LimiterReader.h @@ -37,12 +37,16 @@ private: /** * The start sample: inclusive. */ - int m_start; + const int m_start; /** * The end sample: exlusive. */ - int m_end; + const int m_end; + + // hide copy constructor and operator= + AUD_LimiterReader(const AUD_LimiterReader&); + AUD_LimiterReader& operator=(const AUD_LimiterReader&); public: /** @@ -51,13 +55,12 @@ public: * \param start The desired start sample (inclusive). * \param end The desired end sample (exklusive), a negative value signals * that it should play to the end. - * \exception AUD_Exception Thrown if the reader specified is NULL. */ AUD_LimiterReader(AUD_IReader* reader, float start = 0, float end = -1); virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); + virtual int getLength() const; + virtual int getPosition() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/FX/AUD_LoopFactory.cpp b/intern/audaspace/FX/AUD_LoopFactory.cpp index 90186f623ff..6805a8e4b42 100644 --- a/intern/audaspace/FX/AUD_LoopFactory.cpp +++ b/intern/audaspace/FX/AUD_LoopFactory.cpp @@ -28,30 +28,16 @@ AUD_LoopFactory::AUD_LoopFactory(AUD_IFactory* factory, int loop) : AUD_EffectFactory(factory), - m_loop(loop) {} - -AUD_LoopFactory::AUD_LoopFactory(int loop) : - AUD_EffectFactory(0), - m_loop(loop) {} - -int AUD_LoopFactory::getLoop() + m_loop(loop) { - return m_loop; } -void AUD_LoopFactory::setLoop(int loop) +int AUD_LoopFactory::getLoop() const { - m_loop = loop; + return m_loop; } -AUD_IReader* AUD_LoopFactory::createReader() +AUD_IReader* AUD_LoopFactory::createReader() const { - AUD_IReader* reader = getReader(); - - if(reader != 0) - { - reader = new AUD_LoopReader(reader, m_loop); AUD_NEW("reader") - } - - return reader; + return new AUD_LoopReader(getReader(), m_loop); } diff --git a/intern/audaspace/FX/AUD_LoopFactory.h b/intern/audaspace/FX/AUD_LoopFactory.h index c81d906b82e..f9e358af52d 100644 --- a/intern/audaspace/FX/AUD_LoopFactory.h +++ b/intern/audaspace/FX/AUD_LoopFactory.h @@ -38,7 +38,11 @@ private: /** * The loop count. */ - int m_loop; + const int m_loop; + + // hide copy constructor and operator= + AUD_LoopFactory(const AUD_LoopFactory&); + AUD_LoopFactory& operator=(const AUD_LoopFactory&); public: /** @@ -47,28 +51,14 @@ public: * \param loop The desired loop count, negative values result in endless * looping. */ - AUD_LoopFactory(AUD_IFactory* factory = 0, int loop = -1); - - /** - * Creates a new loop factory. - * \param loop The desired loop count, negative values result in endless - * looping. - */ - AUD_LoopFactory(int loop); + AUD_LoopFactory(AUD_IFactory* factory, int loop = -1); /** * Returns the loop count. */ - int getLoop(); - - /** - * Sets the loop count. - * \param loop The desired loop count, negative values result in endless - * looping. - */ - void setLoop(int loop); + int getLoop() const; - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_LOOPFACTORY diff --git a/intern/audaspace/FX/AUD_LoopReader.cpp b/intern/audaspace/FX/AUD_LoopReader.cpp index 3bcd8c2f9d3..7521f914a5c 100644 --- a/intern/audaspace/FX/AUD_LoopReader.cpp +++ b/intern/audaspace/FX/AUD_LoopReader.cpp @@ -29,36 +29,37 @@ #include <cstring> AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) : - AUD_EffectReader(reader), m_loop(loop) + AUD_EffectReader(reader), m_count(loop), m_left(loop) { - m_samples = -1; - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } -AUD_LoopReader::~AUD_LoopReader() +void AUD_LoopReader::seek(int position) { - delete m_buffer; AUD_DELETE("buffer") + int len = m_reader->getLength(); + if(len < 0) + m_reader->seek(position); + else + { + if(m_count >= 0) + { + m_left = m_count - (position / len); + if(m_left < 0) + m_left = 0; + } + m_reader->seek(position % len); + } } -AUD_ReaderType AUD_LoopReader::getType() +int AUD_LoopReader::getLength() const { - if(m_loop < 0) - return AUD_TYPE_STREAM; - return m_reader->getType(); + if(m_count < 0) + return -1; + return m_reader->getLength() * m_count; } -bool AUD_LoopReader::notify(AUD_Message &message) +int AUD_LoopReader::getPosition() const { - if(message.type == AUD_MSG_LOOP) - { - m_loop = message.loopcount; - m_samples = message.time * m_reader->getSpecs().rate; - - m_reader->notify(message); - - return true; - } - return m_reader->notify(message); + return m_reader->getPosition() * (m_count < 0 ? 1 : m_count); } void AUD_LoopReader::read(int & length, sample_t* & buffer) @@ -66,50 +67,44 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer) AUD_Specs specs = m_reader->getSpecs(); int samplesize = AUD_SAMPLE_SIZE(specs); - if(m_samples >= 0) - { - if(length > m_samples) - length = m_samples; - m_samples -= length; - } - int len = length; m_reader->read(len, buffer); - if(len < length && m_loop != 0) + if(len < length && m_left) { int pos = 0; - if(m_buffer->getSize() < length * samplesize) - m_buffer->resize(length * samplesize); + if(m_buffer.getSize() < length * samplesize) + m_buffer.resize(length * samplesize); + + sample_t* buf = m_buffer.getBuffer(); - memcpy(m_buffer->getBuffer() + pos * specs.channels, - buffer, len * samplesize); + memcpy(buf + pos * specs.channels, buffer, len * samplesize); pos += len; - while(pos < length && m_loop != 0) + while(pos < length && m_left) { - if(m_loop > 0) - m_loop--; + if(m_left > 0) + m_left--; m_reader->seek(0); len = length - pos; m_reader->read(len, buffer); + // prevent endless loop if(!len) break; - memcpy(m_buffer->getBuffer() + pos * specs.channels, - buffer, len * samplesize); + memcpy(buf + pos * specs.channels, buffer, len * samplesize); pos += len; } length = pos; - buffer = m_buffer->getBuffer(); + buffer = buf; } else length = len; diff --git a/intern/audaspace/FX/AUD_LoopReader.h b/intern/audaspace/FX/AUD_LoopReader.h index e61a49cb0db..e0ed4cb6bf3 100644 --- a/intern/audaspace/FX/AUD_LoopReader.h +++ b/intern/audaspace/FX/AUD_LoopReader.h @@ -27,7 +27,7 @@ #define AUD_LOOPREADER #include "AUD_EffectReader.h" -class AUD_Buffer; +#include "AUD_Buffer.h" /** * This class reads another reader and loops it. @@ -39,17 +39,21 @@ private: /** * The playback buffer. */ - AUD_Buffer *m_buffer; + AUD_Buffer m_buffer; /** - * The left loop count. + * The loop count. */ - int m_loop; + const int m_count; /** - * The left samples. + * The left loop count. */ - int m_samples; + int m_left; + + // hide copy constructor and operator= + AUD_LoopReader(const AUD_LoopReader&); + AUD_LoopReader& operator=(const AUD_LoopReader&); public: /** @@ -57,17 +61,12 @@ public: * \param reader The reader to read from. * \param loop The desired loop count, negative values result in endless * looping. - * \exception AUD_Exception Thrown if the reader specified is NULL. */ AUD_LoopReader(AUD_IReader* reader, int loop); - /** - * Destroys the reader. - */ - virtual ~AUD_LoopReader(); - - virtual AUD_ReaderType getType(); - virtual bool notify(AUD_Message &message); + virtual void seek(int position); + virtual int getLength() const; + virtual int getPosition() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/FX/AUD_LowpassFactory.cpp b/intern/audaspace/FX/AUD_LowpassFactory.cpp index 05dc5ff3994..9244e07631b 100644 --- a/intern/audaspace/FX/AUD_LowpassFactory.cpp +++ b/intern/audaspace/FX/AUD_LowpassFactory.cpp @@ -24,28 +24,38 @@ */ #include "AUD_LowpassFactory.h" -#include "AUD_LowpassReader.h" +#include "AUD_IIRFilterReader.h" + +#include <cmath> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif AUD_LowpassFactory::AUD_LowpassFactory(AUD_IFactory* factory, float frequency, float Q) : AUD_EffectFactory(factory), m_frequency(frequency), - m_Q(Q) {} - -AUD_LowpassFactory::AUD_LowpassFactory(float frequency, float Q) : - AUD_EffectFactory(0), - m_frequency(frequency), - m_Q(Q) {} + m_Q(Q) +{ +} -AUD_IReader* AUD_LowpassFactory::createReader() +AUD_IReader* AUD_LowpassFactory::createReader() const { AUD_IReader* reader = getReader(); - if(reader != 0) - { - reader = new AUD_LowpassReader(reader, m_frequency, m_Q); - AUD_NEW("reader") - } + // calculate coefficients + float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate; + float alpha = sin(w0) / (2 * m_Q); + float norm = 1 + alpha; + float c = cos(w0); + std::vector<float> a, b; + a.push_back(1); + a.push_back(-2 * c / norm); + a.push_back((1 - alpha) / norm); + b.push_back((1 - c) / (2 * norm)); + b.push_back((1 - c) / norm); + b.push_back(b[0]); - return reader; + return new AUD_IIRFilterReader(reader, b, a); } diff --git a/intern/audaspace/FX/AUD_LowpassFactory.h b/intern/audaspace/FX/AUD_LowpassFactory.h index 8a419823de0..61b76510a9e 100644 --- a/intern/audaspace/FX/AUD_LowpassFactory.h +++ b/intern/audaspace/FX/AUD_LowpassFactory.h @@ -37,12 +37,16 @@ private: /** * The attack value in seconds. */ - float m_frequency; + const float m_frequency; /** * The Q factor. */ - float m_Q; + const float m_Q; + + // hide copy constructor and operator= + AUD_LowpassFactory(const AUD_LowpassFactory&); + AUD_LowpassFactory& operator=(const AUD_LowpassFactory&); public: /** @@ -53,14 +57,7 @@ public: */ AUD_LowpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0f); - /** - * Creates a new lowpass factory. - * \param frequency The cutoff frequency. - * \param Q The Q factor. - */ - AUD_LowpassFactory(float frequency, float Q = 1.0f); - - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_LOWPASSFACTORY diff --git a/intern/audaspace/FX/AUD_LowpassReader.cpp b/intern/audaspace/FX/AUD_LowpassReader.cpp deleted file mode 100644 index 6dc0bf66a96..00000000000 --- a/intern/audaspace/FX/AUD_LowpassReader.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN LGPL LICENSE BLOCK ***** - * - * Copyright 2009 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 Lesser General Public License as published by - * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#include "AUD_LowpassReader.h" -#include "AUD_Buffer.h" - -#include <cstring> -#include <cmath> - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#define CC channels + channel - -AUD_LowpassReader::AUD_LowpassReader(AUD_IReader* reader, float frequency, - float Q) : - AUD_EffectReader(reader) -{ - AUD_Specs specs = reader->getSpecs(); - int samplesize = AUD_SAMPLE_SIZE(specs); - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - - m_outvalues = new AUD_Buffer(samplesize * AUD_LOWPASS_ORDER); - AUD_NEW("buffer") - memset(m_outvalues->getBuffer(), 0, samplesize * AUD_LOWPASS_ORDER); - - m_invalues = new AUD_Buffer(samplesize * AUD_LOWPASS_ORDER); - AUD_NEW("buffer") - memset(m_invalues->getBuffer(), 0, samplesize * AUD_LOWPASS_ORDER); - - m_position = 0; - - // calculate coefficients - float w0 = 2 * M_PI * frequency / specs.rate; - float alpha = sin(w0) / (2 * Q); - float norm = 1 + alpha; - m_coeff[0][0] = 0; - m_coeff[0][1] = -2 * cos(w0) / norm; - m_coeff[0][2] = (1 - alpha) / norm; - m_coeff[1][2] = m_coeff[1][0] = (1 - cos(w0)) / (2 * norm); - m_coeff[1][1] = (1 - cos(w0)) / norm; -} - -AUD_LowpassReader::~AUD_LowpassReader() -{ - delete m_buffer; AUD_DELETE("buffer") - - delete m_outvalues; AUD_DELETE("buffer") - delete m_invalues; AUD_DELETE("buffer"); -} - -void AUD_LowpassReader::read(int & length, sample_t* & buffer) -{ - sample_t* buf; - sample_t* outvalues; - sample_t* invalues; - - outvalues = m_outvalues->getBuffer(); - invalues = m_invalues->getBuffer(); - - AUD_Specs specs = m_reader->getSpecs(); - - m_reader->read(length, buf); - - if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs)) - m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); - - buffer = m_buffer->getBuffer(); - int channels = specs.channels; - - for(int channel = 0; channel < channels; channel++) - { - for(int i = 0; i < length; i++) - { - invalues[m_position * CC] = buf[i * CC]; - outvalues[m_position * CC] = 0; - - for(int j = 0; j < AUD_LOWPASS_ORDER; j++) - { - outvalues[m_position * CC] += m_coeff[1][j] * - invalues[((m_position + j) % AUD_LOWPASS_ORDER) * CC] - - m_coeff[0][j] * - outvalues[((m_position + j) % AUD_LOWPASS_ORDER) * CC]; - } - - buffer[i * CC] = outvalues[m_position * CC]; - - m_position = (m_position + AUD_LOWPASS_ORDER-1) % AUD_LOWPASS_ORDER; - } - } -} diff --git a/intern/audaspace/FX/AUD_PingPongFactory.cpp b/intern/audaspace/FX/AUD_PingPongFactory.cpp index 8b72afe05e7..b3aaa9e80a4 100644 --- a/intern/audaspace/FX/AUD_PingPongFactory.cpp +++ b/intern/audaspace/FX/AUD_PingPongFactory.cpp @@ -28,40 +28,25 @@ #include "AUD_ReverseFactory.h" AUD_PingPongFactory::AUD_PingPongFactory(AUD_IFactory* factory) : - AUD_EffectFactory(factory) {} - -AUD_IReader* AUD_PingPongFactory::createReader() + AUD_EffectFactory(factory) { - if(m_factory == 0) - return 0; +} - AUD_IReader* reader = m_factory->createReader(); +AUD_IReader* AUD_PingPongFactory::createReader() const +{ + AUD_IReader* reader = getReader(); + AUD_IReader* reader2; + AUD_ReverseFactory factory(m_factory); - if(reader != 0) + try { - AUD_IReader* reader2; - AUD_ReverseFactory factory(m_factory); - - try - { - reader2 = factory.createReader(); - } - catch(AUD_Exception) - { - reader2 = 0; - } - - if(reader2 != 0) - { - reader = new AUD_DoubleReader(reader, reader2); - AUD_NEW("reader") - } - else - { - delete reader; AUD_DELETE("reader") - reader = 0; - } + reader2 = factory.createReader(); + } + catch(AUD_Exception&) + { + delete reader; + throw; } - return reader; + return new AUD_DoubleReader(reader, reader2); } diff --git a/intern/audaspace/FX/AUD_PingPongFactory.h b/intern/audaspace/FX/AUD_PingPongFactory.h index b8854da550a..82aedca8f7f 100644 --- a/intern/audaspace/FX/AUD_PingPongFactory.h +++ b/intern/audaspace/FX/AUD_PingPongFactory.h @@ -34,18 +34,19 @@ */ class AUD_PingPongFactory : public AUD_EffectFactory { +private: + // hide copy constructor and operator= + AUD_PingPongFactory(const AUD_PingPongFactory&); + AUD_PingPongFactory& operator=(const AUD_PingPongFactory&); + public: /** * Creates a new ping pong factory. * \param factory The input factory. */ - AUD_PingPongFactory(AUD_IFactory* factory = 0); - - /** - * Destroys the factory. - */ + AUD_PingPongFactory(AUD_IFactory* factory); - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_PINGPONGFACTORY diff --git a/intern/audaspace/FX/AUD_PitchFactory.cpp b/intern/audaspace/FX/AUD_PitchFactory.cpp index 5f814283c12..be285562db3 100644 --- a/intern/audaspace/FX/AUD_PitchFactory.cpp +++ b/intern/audaspace/FX/AUD_PitchFactory.cpp @@ -29,20 +29,11 @@ AUD_PitchFactory::AUD_PitchFactory(AUD_IFactory* factory, float pitch) : AUD_EffectFactory(factory), - m_pitch(pitch) {} - -AUD_PitchFactory::AUD_PitchFactory(float pitch) : - AUD_EffectFactory(0), - m_pitch(pitch) {} - -AUD_IReader* AUD_PitchFactory::createReader() + m_pitch(pitch) { - AUD_IReader* reader = getReader(); - - if(reader != 0) - { - reader = new AUD_PitchReader(reader, m_pitch); AUD_NEW("reader") - } +} - return reader; +AUD_IReader* AUD_PitchFactory::createReader() const +{ + return new AUD_PitchReader(getReader(), m_pitch); } diff --git a/intern/audaspace/FX/AUD_PitchFactory.h b/intern/audaspace/FX/AUD_PitchFactory.h index 96c4d0d7e92..52b9b7d99e5 100644 --- a/intern/audaspace/FX/AUD_PitchFactory.h +++ b/intern/audaspace/FX/AUD_PitchFactory.h @@ -37,7 +37,11 @@ private: /** * The pitch. */ - float m_pitch; + const float m_pitch; + + // hide copy constructor and operator= + AUD_PitchFactory(const AUD_PitchFactory&); + AUD_PitchFactory& operator=(const AUD_PitchFactory&); public: /** @@ -45,26 +49,9 @@ public: * \param factory The input factory. * \param pitch The desired pitch. */ - AUD_PitchFactory(AUD_IFactory* factory = 0, float pitch = 1.0f); - - /** - * Creates a new pitch factory. - * \param pitch The desired pitch. - */ - AUD_PitchFactory(float pitch); - - /** - * Returns the pitch. - */ - float getPitch(); - - /** - * Sets the pitch. - * \param pitch The new pitch value. Should be between 0.0 and 1.0. - */ - void setPitch(float pitch); + AUD_PitchFactory(AUD_IFactory* factory, float pitch); - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_PITCHFACTORY diff --git a/intern/audaspace/FX/AUD_PitchReader.cpp b/intern/audaspace/FX/AUD_PitchReader.cpp index c53264e1350..19c3be31968 100644 --- a/intern/audaspace/FX/AUD_PitchReader.cpp +++ b/intern/audaspace/FX/AUD_PitchReader.cpp @@ -26,12 +26,11 @@ #include "AUD_PitchReader.h" AUD_PitchReader::AUD_PitchReader(AUD_IReader* reader, float pitch) : - AUD_EffectReader(reader) + AUD_EffectReader(reader), m_pitch(pitch) { - m_pitch = pitch; } -AUD_Specs AUD_PitchReader::getSpecs() +AUD_Specs AUD_PitchReader::getSpecs() const { AUD_Specs specs = m_reader->getSpecs(); specs.rate = (AUD_SampleRate)((int)(specs.rate * m_pitch)); diff --git a/intern/audaspace/FX/AUD_PitchReader.h b/intern/audaspace/FX/AUD_PitchReader.h index 440e9cc843c..cc188cf0ee4 100644 --- a/intern/audaspace/FX/AUD_PitchReader.h +++ b/intern/audaspace/FX/AUD_PitchReader.h @@ -37,18 +37,21 @@ private: /** * The pitch level. */ - float m_pitch; + const float m_pitch; + + // hide copy constructor and operator= + AUD_PitchReader(const AUD_PitchReader&); + AUD_PitchReader& operator=(const AUD_PitchReader&); public: /** * Creates a new pitch reader. * \param reader The reader to read from. * \param pitch The size of the buffer. - * \exception AUD_Exception Thrown if the reader specified is NULL. */ AUD_PitchReader(AUD_IReader* reader, float pitch); - virtual AUD_Specs getSpecs(); + virtual AUD_Specs getSpecs() const; }; #endif //AUD_PITCHREADER diff --git a/intern/audaspace/FX/AUD_RectifyFactory.cpp b/intern/audaspace/FX/AUD_RectifyFactory.cpp index f97defd793b..2228f949dfe 100644 --- a/intern/audaspace/FX/AUD_RectifyFactory.cpp +++ b/intern/audaspace/FX/AUD_RectifyFactory.cpp @@ -24,22 +24,21 @@ */ #include "AUD_RectifyFactory.h" -#include "AUD_RectifyReader.h" +#include "AUD_CallbackIIRFilterReader.h" -AUD_RectifyFactory::AUD_RectifyFactory(AUD_IFactory* factory) : - AUD_EffectFactory(factory) {} - -AUD_RectifyFactory::AUD_RectifyFactory() : - AUD_EffectFactory(0) {} +#include <cmath> -AUD_IReader* AUD_RectifyFactory::createReader() +sample_t rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless) { - AUD_IReader* reader = getReader(); + return fabs(reader->x(0)); +} - if(reader != 0) - { - reader = new AUD_RectifyReader(reader); AUD_NEW("reader") - } +AUD_RectifyFactory::AUD_RectifyFactory(AUD_IFactory* factory) : + AUD_EffectFactory(factory) +{ +} - return reader; +AUD_IReader* AUD_RectifyFactory::createReader() const +{ + return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, rectifyFilter); } diff --git a/intern/audaspace/FX/AUD_RectifyFactory.h b/intern/audaspace/FX/AUD_RectifyFactory.h index ed00620d318..d8b39e83fdf 100644 --- a/intern/audaspace/FX/AUD_RectifyFactory.h +++ b/intern/audaspace/FX/AUD_RectifyFactory.h @@ -33,19 +33,19 @@ */ class AUD_RectifyFactory : public AUD_EffectFactory { +private: + // hide copy constructor and operator= + AUD_RectifyFactory(const AUD_RectifyFactory&); + AUD_RectifyFactory& operator=(const AUD_RectifyFactory&); + public: /** * Creates a new rectify factory. * \param factory The input factory. */ - AUD_RectifyFactory(AUD_IFactory* factory = 0); - - /** - * Creates a new rectify factory. - */ - AUD_RectifyFactory(); + AUD_RectifyFactory(AUD_IFactory* factory); - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_RECTIFYFACTORY diff --git a/intern/audaspace/FX/AUD_ReverseFactory.cpp b/intern/audaspace/FX/AUD_ReverseFactory.cpp index 1242641c350..1002e2de87e 100644 --- a/intern/audaspace/FX/AUD_ReverseFactory.cpp +++ b/intern/audaspace/FX/AUD_ReverseFactory.cpp @@ -28,16 +28,11 @@ #include "AUD_Space.h" AUD_ReverseFactory::AUD_ReverseFactory(AUD_IFactory* factory) : - AUD_EffectFactory(factory) {} - -AUD_IReader* AUD_ReverseFactory::createReader() + AUD_EffectFactory(factory) { - AUD_IReader* reader = getReader(); - - if(reader != 0) - { - reader = new AUD_ReverseReader(reader); AUD_NEW("reader") - } +} - return reader; +AUD_IReader* AUD_ReverseFactory::createReader() const +{ + return new AUD_ReverseReader(getReader()); } diff --git a/intern/audaspace/FX/AUD_ReverseFactory.h b/intern/audaspace/FX/AUD_ReverseFactory.h index 4b664c47281..a1995ee68f9 100644 --- a/intern/audaspace/FX/AUD_ReverseFactory.h +++ b/intern/audaspace/FX/AUD_ReverseFactory.h @@ -34,17 +34,19 @@ */ class AUD_ReverseFactory : public AUD_EffectFactory { +private: + // hide copy constructor and operator= + AUD_ReverseFactory(const AUD_ReverseFactory&); + AUD_ReverseFactory& operator=(const AUD_ReverseFactory&); + public: /** * Creates a new reverse factory. * \param factory The input factory. */ - AUD_ReverseFactory(AUD_IFactory* factory = 0); + AUD_ReverseFactory(AUD_IFactory* factory); - /** - * Destroys the factory. - */ - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_REVERSEFACTORY diff --git a/intern/audaspace/FX/AUD_ReverseReader.cpp b/intern/audaspace/FX/AUD_ReverseReader.cpp index 82d6c70ce53..c651ea79577 100644 --- a/intern/audaspace/FX/AUD_ReverseReader.cpp +++ b/intern/audaspace/FX/AUD_ReverseReader.cpp @@ -24,27 +24,19 @@ */ #include "AUD_ReverseReader.h" -#include "AUD_Buffer.h" #include <cstring> -AUD_ReverseReader::AUD_ReverseReader(AUD_IReader* reader) : - AUD_EffectReader(reader) -{ - if(reader->getType() != AUD_TYPE_BUFFER) - AUD_THROW(AUD_ERROR_READER); - - m_length = reader->getLength(); - if(m_length < 0) - AUD_THROW(AUD_ERROR_READER); +static const char* props_error = "AUD_ReverseReader: The reader has to be " + "seekable and a finite length."; - m_position = 0; - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") -} - -AUD_ReverseReader::~AUD_ReverseReader() +AUD_ReverseReader::AUD_ReverseReader(AUD_IReader* reader) : + AUD_EffectReader(reader), + m_length(reader->getLength()), + m_position(0) { - delete m_buffer; AUD_DELETE("buffer") + if(m_length < 0 || !reader->isSeekable()) + AUD_THROW(AUD_ERROR_PROPS, props_error); } void AUD_ReverseReader::seek(int position) @@ -52,12 +44,12 @@ void AUD_ReverseReader::seek(int position) m_position = position; } -int AUD_ReverseReader::getLength() +int AUD_ReverseReader::getLength() const { return m_length; } -int AUD_ReverseReader::getPosition() +int AUD_ReverseReader::getPosition() const { return m_position; } @@ -66,7 +58,7 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer) { // first correct the length if(m_position + length > m_length) - length = m_length-m_position; + length = m_length - m_position; if(length <= 0) { @@ -78,10 +70,10 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer) int samplesize = AUD_SAMPLE_SIZE(specs); // resize buffer if needed - if(m_buffer->getSize() < length * samplesize) - m_buffer->resize(length * samplesize); + if(m_buffer.getSize() < length * samplesize) + m_buffer.resize(length * samplesize); - buffer = m_buffer->getBuffer(); + buffer = m_buffer.getBuffer(); sample_t* buf; int len = length; @@ -105,5 +97,5 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer) m_position += length; - buffer = m_buffer->getBuffer(); + buffer = m_buffer.getBuffer(); } diff --git a/intern/audaspace/FX/AUD_ReverseReader.h b/intern/audaspace/FX/AUD_ReverseReader.h index 045d2ac5a8e..8eb960a5dee 100644 --- a/intern/audaspace/FX/AUD_ReverseReader.h +++ b/intern/audaspace/FX/AUD_ReverseReader.h @@ -27,7 +27,7 @@ #define AUD_REVERSEREADER #include "AUD_EffectReader.h" -class AUD_Buffer; +#include "AUD_Buffer.h" /** * This class reads another reader from back to front. @@ -37,37 +37,36 @@ class AUD_ReverseReader : public AUD_EffectReader { private: /** - * The current position. + * The sample count. */ - int m_position; + const int m_length; /** - * The sample count. + * The current position. */ - int m_length; + int m_position; /** * The playback buffer. */ - AUD_Buffer* m_buffer; + AUD_Buffer m_buffer; + + // hide copy constructor and operator= + AUD_ReverseReader(const AUD_ReverseReader&); + AUD_ReverseReader& operator=(const AUD_ReverseReader&); public: /** * Creates a new reverse reader. * \param reader The reader to read from. - * \exception AUD_Exception Thrown if the reader specified is NULL or not - * a buffer. + * \exception AUD_Exception Thrown if the reader specified has an + * undeterminable/infinite length or is not seekable. */ AUD_ReverseReader(AUD_IReader* reader); - /** - * Destroys the reader. - */ - virtual ~AUD_ReverseReader(); - virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); + virtual int getLength() const; + virtual int getPosition() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/FX/AUD_SquareFactory.cpp b/intern/audaspace/FX/AUD_SquareFactory.cpp index 638acaa9a32..c321a13d79a 100644 --- a/intern/audaspace/FX/AUD_SquareFactory.cpp +++ b/intern/audaspace/FX/AUD_SquareFactory.cpp @@ -24,34 +24,39 @@ */ #include "AUD_SquareFactory.h" -#include "AUD_SquareReader.h" +#include "AUD_CallbackIIRFilterReader.h" -AUD_SquareFactory::AUD_SquareFactory(AUD_IFactory* factory, float threshold) : - AUD_EffectFactory(factory), - m_threshold(threshold) {} - -AUD_SquareFactory::AUD_SquareFactory(float threshold) : - AUD_EffectFactory(0), - m_threshold(threshold) {} - -float AUD_SquareFactory::getThreshold() +sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold) { - return m_threshold; + float in = reader->x(0); + if(in >= *threshold) + return 1; + else if(in <= -*threshold) + return -1; + else + return 0; } -void AUD_SquareFactory::setThreshold(float threshold) +void endSquareFilter(float* threshold) { - m_threshold = threshold; + delete threshold; } -AUD_IReader* AUD_SquareFactory::createReader() +AUD_SquareFactory::AUD_SquareFactory(AUD_IFactory* factory, float threshold) : + AUD_EffectFactory(factory), + m_threshold(threshold) { - AUD_IReader* reader = getReader(); +} - if(reader != 0) - { - reader = new AUD_SquareReader(reader, m_threshold); AUD_NEW("reader") - } +float AUD_SquareFactory::getThreshold() const +{ + return m_threshold; +} - return reader; +AUD_IReader* AUD_SquareFactory::createReader() const +{ + return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, + (doFilterIIR) squareFilter, + (endFilterIIR) endSquareFilter, + new float(m_threshold)); } diff --git a/intern/audaspace/FX/AUD_SquareFactory.h b/intern/audaspace/FX/AUD_SquareFactory.h index dfbe5ae2887..da87dc6f888 100644 --- a/intern/audaspace/FX/AUD_SquareFactory.h +++ b/intern/audaspace/FX/AUD_SquareFactory.h @@ -37,7 +37,11 @@ private: /** * The threshold. */ - float m_threshold; + const float m_threshold; + + // hide copy constructor and operator= + AUD_SquareFactory(const AUD_SquareFactory&); + AUD_SquareFactory& operator=(const AUD_SquareFactory&); public: /** @@ -45,26 +49,14 @@ public: * \param factory The input factory. * \param threshold The threshold. */ - AUD_SquareFactory(AUD_IFactory* factory = 0, float threshold = 0.0f); - - /** - * Creates a new square factory. - * \param threshold The threshold. - */ - AUD_SquareFactory(float threshold); + AUD_SquareFactory(AUD_IFactory* factory, float threshold = 0.0f); /** * Returns the threshold. */ - float getThreshold(); - - /** - * Sets the threshold. - * \param threshold The new threshold value. Should be between 0.0 and 1.0. - */ - void setThreshold(float threshold); + float getThreshold() const; - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_SQUAREFACTORY diff --git a/intern/audaspace/FX/AUD_SumFactory.cpp b/intern/audaspace/FX/AUD_SumFactory.cpp index f7990aab8a1..a128e50504c 100644 --- a/intern/audaspace/FX/AUD_SumFactory.cpp +++ b/intern/audaspace/FX/AUD_SumFactory.cpp @@ -24,20 +24,18 @@ */ #include "AUD_SumFactory.h" -#include "AUD_SumReader.h" +#include "AUD_IIRFilterReader.h" AUD_SumFactory::AUD_SumFactory(AUD_IFactory* factory) : - AUD_EffectFactory(factory) {} - -AUD_IReader* AUD_SumFactory::createReader() + AUD_EffectFactory(factory) { - AUD_IReader* reader = getReader(); - - if(reader != 0) - { - reader = new AUD_SumReader(reader); - AUD_NEW("reader") - } +} - return reader; +AUD_IReader* AUD_SumFactory::createReader() const +{ + std::vector<float> a, b; + a.push_back(1); + a.push_back(-1); + b.push_back(1); + return new AUD_IIRFilterReader(getReader(), b, a); } diff --git a/intern/audaspace/FX/AUD_SumFactory.h b/intern/audaspace/FX/AUD_SumFactory.h index 5cb48e26b10..045a0a3a625 100644 --- a/intern/audaspace/FX/AUD_SumFactory.h +++ b/intern/audaspace/FX/AUD_SumFactory.h @@ -33,14 +33,19 @@ */ class AUD_SumFactory : public AUD_EffectFactory { +private: + // hide copy constructor and operator= + AUD_SumFactory(const AUD_SumFactory&); + AUD_SumFactory& operator=(const AUD_SumFactory&); + public: /** * Creates a new sum factory. * \param factory The input factory. */ - AUD_SumFactory(AUD_IFactory* factory = 0); + AUD_SumFactory(AUD_IFactory* factory); - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_SUMFACTORY diff --git a/intern/audaspace/FX/AUD_SumReader.cpp b/intern/audaspace/FX/AUD_SumReader.cpp deleted file mode 100644 index 08747790fc9..00000000000 --- a/intern/audaspace/FX/AUD_SumReader.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN LGPL LICENSE BLOCK ***** - * - * Copyright 2009 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 Lesser General Public License as published by - * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#include "AUD_SumReader.h" -#include "AUD_Buffer.h" - -#include <cstring> - -#define CC specs.channels + channel - -AUD_SumReader::AUD_SumReader(AUD_IReader* reader) : - AUD_EffectReader(reader) -{ - AUD_Specs specs = reader->getSpecs(); - int samplesize = AUD_SAMPLE_SIZE(specs); - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - - m_sums = new AUD_Buffer(samplesize); AUD_NEW("buffer") - memset(m_sums->getBuffer(), 0, samplesize); -} - -AUD_SumReader::~AUD_SumReader() -{ - delete m_buffer; AUD_DELETE("buffer") - delete m_sums; AUD_DELETE("buffer") -} - -void AUD_SumReader::read(int & length, sample_t* & buffer) -{ - sample_t* buf; - sample_t* sums; - sums = m_sums->getBuffer(); - - AUD_Specs specs = m_reader->getSpecs(); - - m_reader->read(length, buf); - if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs)) - m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); - - buffer = m_buffer->getBuffer(); - - for(int channel = 0; channel < specs.channels; channel++) - for(int i = 0; i < length * specs.channels; i++) - buffer[i * CC] = sums[channel] = sums[channel] + buf[i * CC]; -} diff --git a/intern/audaspace/FX/AUD_SuperposeFactory.cpp b/intern/audaspace/FX/AUD_SuperposeFactory.cpp new file mode 100644 index 00000000000..6bfc1125ca6 --- /dev/null +++ b/intern/audaspace/FX/AUD_SuperposeFactory.cpp @@ -0,0 +1,49 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_SuperposeFactory.h" +#include "AUD_SuperposeReader.h" + +AUD_SuperposeFactory::AUD_SuperposeFactory(AUD_IFactory* factory1, AUD_IFactory* factory2) : + m_factory1(factory1), m_factory2(factory2) +{ +} + +AUD_IReader* AUD_SuperposeFactory::createReader() const +{ + AUD_IReader* reader1 = m_factory1->createReader(); + AUD_IReader* reader2; + try + { + reader2 = m_factory2->createReader(); + } + catch(AUD_Exception&) + { + delete reader1; + throw; + } + + return new AUD_SuperposeReader(reader1, reader2); +} diff --git a/intern/audaspace/FX/AUD_SuperposeFactory.h b/intern/audaspace/FX/AUD_SuperposeFactory.h new file mode 100644 index 00000000000..a7fde2c182f --- /dev/null +++ b/intern/audaspace/FX/AUD_SuperposeFactory.h @@ -0,0 +1,63 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_SUPERPOSEFACTORY +#define AUD_SUPERPOSEFACTORY + +#include "AUD_IFactory.h" + +/** + * This factory plays two other factories behind each other. + * \note Readers from the underlying factories must have the same sample rate and channel count. + */ +class AUD_SuperposeFactory : public AUD_IFactory +{ +private: + /** + * First played factory. + */ + AUD_IFactory* m_factory1; + + /** + * Second played factory. + */ + AUD_IFactory* m_factory2; + + // hide copy constructor and operator= + AUD_SuperposeFactory(const AUD_SuperposeFactory&); + AUD_SuperposeFactory& operator=(const AUD_SuperposeFactory&); + +public: + /** + * Creates a new superpose factory. + * \param factory1 The first input factory. + * \param factory2 The second input factory. + */ + AUD_SuperposeFactory(AUD_IFactory* factory1, AUD_IFactory* factory2); + + virtual AUD_IReader* createReader() const; +}; + +#endif //AUD_SUPERPOSEFACTORY diff --git a/intern/audaspace/FX/AUD_SuperposeReader.cpp b/intern/audaspace/FX/AUD_SuperposeReader.cpp new file mode 100644 index 00000000000..546b79a3a77 --- /dev/null +++ b/intern/audaspace/FX/AUD_SuperposeReader.cpp @@ -0,0 +1,115 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_SuperposeReader.h" + +#include <cstring> + +static const char* specs_error = "AUD_SuperposeReader: Both readers have to " + "have the same specs."; + +AUD_SuperposeReader::AUD_SuperposeReader(AUD_IReader* reader1, AUD_IReader* reader2) : + m_reader1(reader1), m_reader2(reader2) +{ + try + { + AUD_Specs s1, s2; + s1 = reader1->getSpecs(); + s2 = reader2->getSpecs(); + if(memcmp(&s1, &s2, sizeof(AUD_Specs))) + AUD_THROW(AUD_ERROR_SPECS, specs_error); + } + catch(AUD_Exception&) + { + delete reader1; + delete reader2; + + throw; + } +} + +AUD_SuperposeReader::~AUD_SuperposeReader() +{ + delete m_reader1; + delete m_reader2; +} + +bool AUD_SuperposeReader::isSeekable() const +{ + return m_reader1->isSeekable() && m_reader2->isSeekable(); +} + +void AUD_SuperposeReader::seek(int position) +{ + m_reader1->seek(position); + m_reader2->seek(position); +} + +int AUD_SuperposeReader::getLength() const +{ + int len1 = m_reader1->getLength(); + int len2 = m_reader2->getLength(); + if((len1 < 0) || (len2 < 0)) + return -1; + return AUD_MIN(len1, len2); +} + +int AUD_SuperposeReader::getPosition() const +{ + int pos1 = m_reader1->getPosition(); + int pos2 = m_reader2->getPosition(); + return AUD_MAX(pos1, pos2); +} + +AUD_Specs AUD_SuperposeReader::getSpecs() const +{ + return m_reader1->getSpecs(); +} + +void AUD_SuperposeReader::read(int & length, sample_t* & buffer) +{ + AUD_Specs specs = m_reader1->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); + + if(m_buffer.getSize() < length * samplesize) + m_buffer.resize(length * samplesize); + buffer = m_buffer.getBuffer(); + + int len1 = length; + sample_t* buf; + m_reader1->read(len1, buf); + memcpy(buffer, buf, len1 * samplesize); + + if(len1 < length) + memset(buffer + len1 * specs.channels, 0, (length - len1) * samplesize); + + int len2 = length; + m_reader2->read(len2, buf); + + for(int i = 0; i < len2 * specs.channels; i++) + buffer[i] += buf[i]; + + length = AUD_MAX(len1, len2); +} diff --git a/intern/audaspace/FX/AUD_SuperposeReader.h b/intern/audaspace/FX/AUD_SuperposeReader.h new file mode 100644 index 00000000000..eeceb9adfeb --- /dev/null +++ b/intern/audaspace/FX/AUD_SuperposeReader.h @@ -0,0 +1,79 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_SUPERPOSEREADER +#define AUD_SUPERPOSEREADER + +#include "AUD_IReader.h" +#include "AUD_Buffer.h" + +/** + * This reader plays two readers with the same specs sequently. + */ +class AUD_SuperposeReader : public AUD_IReader +{ +private: + /** + * The first reader. + */ + AUD_IReader* m_reader1; + + /** + * The second reader. + */ + AUD_IReader* m_reader2; + + /** + * The playback buffer for the intersecting part. + */ + AUD_Buffer m_buffer; + + // hide copy constructor and operator= + AUD_SuperposeReader(const AUD_SuperposeReader&); + AUD_SuperposeReader& operator=(const AUD_SuperposeReader&); + +public: + /** + * Creates a new superpose reader. + * \param reader1 The first reader to read from. + * \param reader2 The second reader to read from. + * \exception AUD_Exception Thrown if the specs from the readers differ. + */ + AUD_SuperposeReader(AUD_IReader* reader1, AUD_IReader* reader2); + + /** + * Destroys the reader. + */ + virtual ~AUD_SuperposeReader(); + + virtual bool isSeekable() const; + virtual void seek(int position); + virtual int getLength() const; + virtual int getPosition() const; + virtual AUD_Specs getSpecs() const; + virtual void read(int & length, sample_t* & buffer); +}; + +#endif //AUD_SUPERPOSEREADER diff --git a/intern/audaspace/FX/AUD_VolumeFactory.cpp b/intern/audaspace/FX/AUD_VolumeFactory.cpp index fbde608aa12..1b341a5a51a 100644 --- a/intern/audaspace/FX/AUD_VolumeFactory.cpp +++ b/intern/audaspace/FX/AUD_VolumeFactory.cpp @@ -24,34 +24,23 @@ */ #include "AUD_VolumeFactory.h" -#include "AUD_VolumeReader.h" +#include "AUD_IIRFilterReader.h" AUD_VolumeFactory::AUD_VolumeFactory(AUD_IFactory* factory, float volume) : AUD_EffectFactory(factory), - m_volume(volume) {} - -AUD_VolumeFactory::AUD_VolumeFactory(float volume) : - AUD_EffectFactory(0), - m_volume(volume) {} - -float AUD_VolumeFactory::getVolume() + m_volume(volume) { - return m_volume; } -void AUD_VolumeFactory::setVolume(float volume) +float AUD_VolumeFactory::getVolume() const { - m_volume = volume; + return m_volume; } -AUD_IReader* AUD_VolumeFactory::createReader() +AUD_IReader* AUD_VolumeFactory::createReader() const { - AUD_IReader* reader = getReader(); - - if(reader != 0) - { - reader = new AUD_VolumeReader(reader, m_volume); AUD_NEW("reader") - } - - return reader; + std::vector<float> a, b; + a.push_back(1); + b.push_back(m_volume); + return new AUD_IIRFilterReader(getReader(), b, a); } diff --git a/intern/audaspace/FX/AUD_VolumeFactory.h b/intern/audaspace/FX/AUD_VolumeFactory.h index 09f91241b47..a086aab4640 100644 --- a/intern/audaspace/FX/AUD_VolumeFactory.h +++ b/intern/audaspace/FX/AUD_VolumeFactory.h @@ -39,7 +39,11 @@ private: /** * The volume. */ - float m_volume; + const float m_volume; + + // hide copy constructor and operator= + AUD_VolumeFactory(const AUD_VolumeFactory&); + AUD_VolumeFactory& operator=(const AUD_VolumeFactory&); public: /** @@ -47,26 +51,14 @@ public: * \param factory The input factory. * \param volume The desired volume. */ - AUD_VolumeFactory(AUD_IFactory* factory = 0, float volume = 1.0f); - - /** - * Creates a new volume factory. - * \param volume The desired volume. - */ - AUD_VolumeFactory(float volume); + AUD_VolumeFactory(AUD_IFactory* factory, float volume); /** * Returns the volume. */ - float getVolume(); - - /** - * Sets the volume. - * \param volume The new volume value. Should be between 0.0 and 1.0. - */ - void setVolume(float volume); + float getVolume() const; - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_VOLUMEFACTORY diff --git a/intern/audaspace/FX/AUD_VolumeReader.cpp b/intern/audaspace/FX/AUD_VolumeReader.cpp deleted file mode 100644 index f094c1e4ea3..00000000000 --- a/intern/audaspace/FX/AUD_VolumeReader.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN LGPL LICENSE BLOCK ***** - * - * Copyright 2009 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 Lesser General Public License as published by - * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. - * - * ***** END LGPL LICENSE BLOCK ***** - */ - -#include "AUD_VolumeReader.h" -#include "AUD_Buffer.h" - -#include <cstring> - -AUD_VolumeReader::AUD_VolumeReader(AUD_IReader* reader, float volume) : - AUD_EffectReader(reader), - m_volume(volume) -{ - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") -} - -AUD_VolumeReader::~AUD_VolumeReader() -{ - delete m_buffer; AUD_DELETE("buffer") -} - -bool AUD_VolumeReader::notify(AUD_Message &message) -{ - if(message.type == AUD_MSG_VOLUME) - { - m_volume = message.volume; - - m_reader->notify(message); - - return true; - } - return m_reader->notify(message); -} - -void AUD_VolumeReader::read(int & length, sample_t* & buffer) -{ - sample_t* buf; - AUD_Specs specs = m_reader->getSpecs(); - - m_reader->read(length, buf); - if(m_buffer->getSize() < length*AUD_SAMPLE_SIZE(specs)) - m_buffer->resize(length*AUD_SAMPLE_SIZE(specs)); - - buffer = m_buffer->getBuffer(); - - for(int i = 0; i < length * specs.channels; i++) - buffer[i] = buf[i] * m_volume; -} diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp index 796764989ba..aa7cfcfd880 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp @@ -24,9 +24,9 @@ */ #include "AUD_OpenALDevice.h" +#include "AUD_IFactory.h" #include "AUD_IReader.h" -#include "AUD_ConverterFactory.h" -#include "AUD_SourceCaps.h" +#include "AUD_ConverterReader.h" #include <cstring> #include <limits> @@ -65,6 +65,15 @@ struct AUD_OpenALHandle : AUD_Handle /// Whether the stream doesn't return any more data. bool data_end; + + /// The loop count of the source. + int loopcount; + + /// The stop callback. + stopCallback stop; + + /// Stop callback data. + void* stop_data; }; struct AUD_OpenALBufferedFactory @@ -128,13 +137,9 @@ void AUD_OpenALDevice::updateStreams() { // for all sounds - AUD_HandleIterator it = m_playingSounds->begin(); - while(it != m_playingSounds->end()) + for(AUD_HandleIterator it = m_playingSounds->begin(); it != m_playingSounds->end(); it++) { sound = *it; - // increment the iterator to make sure it's valid, - // in case the sound gets deleted after stopping - ++it; // is it a streamed sound? if(!sound->isBuffered) @@ -156,6 +161,18 @@ void AUD_OpenALDevice::updateStreams() length = m_buffersize; sound->reader->read(length, buffer); + // looping necessary? + if(length == 0 && sound->loopcount) + { + if(sound->loopcount > 0) + sound->loopcount--; + + sound->reader->seek(0); + + length = m_buffersize; + sound->reader->read(length, buffer); + } + // read nothing? if(length == 0) { @@ -212,12 +229,21 @@ void AUD_OpenALDevice::updateStreams() // if it really stopped if(sound->data_end) { + if(sound->stop) + sound->stop(sound->stop_data); + + // increment the iterator to the next value, + // because the sound gets deleted in the list here. + ++it; // pause or if(sound->keep) pause(sound); // stop else stop(sound); + // decrement again, so that we get the next sound in the + // next loop run + --it; } // continue playing else @@ -263,6 +289,8 @@ bool AUD_OpenALDevice::isValid(AUD_Handle* handle) return false; } +static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened."; + AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) { // cannot determine how many channels or which format OpenAL uses, but @@ -287,7 +315,7 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) m_device = alcOpenDevice(NULL); if(!m_device) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, open_error); // at least try to set the frequency ALCint attribs[] = { ALC_FREQUENCY, specs.rate, 0 }; @@ -302,12 +330,7 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) // check for specific formats and channel counts to be played back if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE) - { specs.format = AUD_FORMAT_FLOAT32; - m_converter = NULL; - } - else - m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory") m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE; @@ -317,10 +340,9 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) m_buffersize = buffersize; m_playing = false; - m_playingSounds = new std::list<AUD_OpenALHandle*>(); AUD_NEW("list") - m_pausedSounds = new std::list<AUD_OpenALHandle*>(); AUD_NEW("list") + m_playingSounds = new std::list<AUD_OpenALHandle*>(); + m_pausedSounds = new std::list<AUD_OpenALHandle*>(); m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>(); - AUD_NEW("list") pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); @@ -345,10 +367,10 @@ AUD_OpenALDevice::~AUD_OpenALDevice() alDeleteSources(1, &sound->source); if(!sound->isBuffered) { - delete sound->reader; AUD_DELETE("reader") + delete sound->reader; alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); } - delete sound; AUD_DELETE("handle") + delete sound; m_playingSounds->erase(m_playingSounds->begin()); } @@ -359,10 +381,10 @@ AUD_OpenALDevice::~AUD_OpenALDevice() alDeleteSources(1, &sound->source); if(!sound->isBuffered) { - delete sound->reader; AUD_DELETE("reader") + delete sound->reader; alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); } - delete sound; AUD_DELETE("handle") + delete sound; m_pausedSounds->erase(m_pausedSounds->begin()); } @@ -370,7 +392,7 @@ AUD_OpenALDevice::~AUD_OpenALDevice() while(!m_bufferedFactories->empty()) { alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer); - delete *m_bufferedFactories->begin(); AUD_DELETE("bufferedfactory"); + delete *m_bufferedFactories->begin(); m_bufferedFactories->erase(m_bufferedFactories->begin()); } @@ -385,22 +407,19 @@ AUD_OpenALDevice::~AUD_OpenALDevice() else unlock(); - delete m_playingSounds; AUD_DELETE("list") - delete m_pausedSounds; AUD_DELETE("list") - delete m_bufferedFactories; AUD_DELETE("list") + delete m_playingSounds; + delete m_pausedSounds; + delete m_bufferedFactories; // quit OpenAL alcMakeContextCurrent(NULL); alcDestroyContext(m_context); alcCloseDevice(m_device); - if(m_converter) - delete m_converter; AUD_DELETE("factory") - pthread_mutex_destroy(&m_mutex); } -AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() +AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() const { return m_specs; } @@ -496,6 +515,15 @@ bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs) return valid; } +static const char* genbuffer_error = "AUD_OpenALDevice: Buffer couldn't be " + "generated."; +static const char* gensource_error = "AUD_OpenALDevice: Source couldn't be " + "generated."; +static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be " + "queued to the source."; +static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be " + "filled with data."; + AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) { lock(); @@ -511,11 +539,14 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) if((*i)->factory == factory) { // create the handle - sound = new AUD_OpenALHandle; AUD_NEW("handle") + sound = new AUD_OpenALHandle; sound->keep = keep; sound->current = -1; sound->isBuffered = true; sound->data_end = true; + sound->loopcount = 0; + sound->stop = NULL; + sound->stop_data = NULL; alcSuspendContext(m_context); @@ -524,23 +555,23 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) { alGenSources(1, &sound->source); if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, gensource_error); try { alSourcei(sound->source, AL_BUFFER, (*i)->buffer); if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, queue_error); } - catch(AUD_Exception) + catch(AUD_Exception&) { alDeleteSources(1, &sound->source); throw; } } - catch(AUD_Exception) + catch(AUD_Exception&) { - delete sound; AUD_DELETE("handle") + delete sound; alcProcessContext(m_context); throw; } @@ -555,7 +586,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) } } } - catch(AUD_Exception) + catch(AUD_Exception&) { unlock(); throw; @@ -568,35 +599,32 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) AUD_IReader* reader = factory->createReader(); - if(reader == NULL) - AUD_THROW(AUD_ERROR_READER); - AUD_DeviceSpecs specs = m_specs; specs.specs = reader->getSpecs(); // check format bool valid = specs.channels != AUD_CHANNELS_INVALID; - if(m_converter) - { - m_converter->setReader(reader); - reader = m_converter->createReader(); - } + if(m_specs.format != AUD_FORMAT_FLOAT32) + reader = new AUD_ConverterReader(reader, m_specs); // create the handle - sound = new AUD_OpenALHandle; AUD_NEW("handle") + sound = new AUD_OpenALHandle; sound->keep = keep; sound->reader = reader; sound->current = 0; sound->isBuffered = false; sound->data_end = false; + sound->loopcount = 0; + sound->stop = NULL; + sound->stop_data = NULL; valid &= getFormat(sound->format, specs.specs); if(!valid) { - delete sound; AUD_DELETE("handle") - delete reader; AUD_DELETE("reader") + delete sound; + delete reader; return NULL; } @@ -608,7 +636,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) { alGenBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error); try { @@ -623,36 +651,36 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error); } alGenSources(1, &sound->source); if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, gensource_error); try { alSourceQueueBuffers(sound->source, AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); + AUD_THROW(AUD_ERROR_OPENAL, queue_error); } - catch(AUD_Exception) + catch(AUD_Exception&) { alDeleteSources(1, &sound->source); throw; } } - catch(AUD_Exception) + catch(AUD_Exception&) { alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); throw; } } - catch(AUD_Exception) + catch(AUD_Exception&) { - delete sound; AUD_DELETE("handle") - delete reader; AUD_DELETE("reader") + delete sound; + delete reader; alcProcessContext(m_context); unlock(); throw; @@ -737,10 +765,10 @@ bool AUD_OpenALDevice::stop(AUD_Handle* handle) alDeleteSources(1, &sound->source); if(!sound->isBuffered) { - delete sound->reader; AUD_DELETE("reader") + delete sound->reader; alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); } - delete *i; AUD_DELETE("handle") + delete *i; m_playingSounds->erase(i); result = true; break; @@ -757,10 +785,10 @@ bool AUD_OpenALDevice::stop(AUD_Handle* handle) alDeleteSources(1, &sound->source); if(!sound->isBuffered) { - delete sound->reader; AUD_DELETE("reader") + delete sound->reader; alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); } - delete *i; AUD_DELETE("handle") + delete *i; m_pausedSounds->erase(i); result = true; break; @@ -773,43 +801,31 @@ bool AUD_OpenALDevice::stop(AUD_Handle* handle) return result; } -bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep) +bool AUD_OpenALDevice::getKeep(AUD_Handle* handle) { bool result = false; lock(); if(isValid(handle)) - { - ((AUD_OpenALHandle*)handle)->keep = keep; - result = true; - } + result = ((AUD_OpenALHandle*)handle)->keep; unlock(); return result; } -bool AUD_OpenALDevice::sendMessage(AUD_Handle* handle, AUD_Message &message) +bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep) { bool result = false; lock(); - if(handle == 0) + if(isValid(handle)) { - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) - if(!(*i)->isBuffered) - result |= (*i)->reader->notify(message); - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) - if(!(*i)->isBuffered) - result |= (*i)->reader->notify(message); + ((AUD_OpenALHandle*)handle)->keep = keep; + result = true; } - else if(isValid(handle)) - if(!((AUD_OpenALHandle*)handle)->isBuffered) - result = ((AUD_OpenALHandle*)handle)->reader->notify(message); unlock(); @@ -947,440 +963,657 @@ void AUD_OpenALDevice::unlock() pthread_mutex_unlock(&m_mutex); } -/******************************************************************************/ -/**************************** Capabilities Code *******************************/ -/******************************************************************************/ +float AUD_OpenALDevice::getVolume() const +{ + float result; + alGetListenerf(AL_GAIN, &result); + return result; +} -bool AUD_OpenALDevice::checkCapability(int capability) +void AUD_OpenALDevice::setVolume(float volume) { - return capability == AUD_CAPS_3D_DEVICE || - capability == AUD_CAPS_VOLUME || - capability == AUD_CAPS_SOURCE_VOLUME || - capability == AUD_CAPS_SOURCE_PITCH || - capability == AUD_CAPS_BUFFERED_FACTORY; + alListenerf(AL_GAIN, volume); +} + +float AUD_OpenALDevice::getVolume(AUD_Handle* handle) +{ + lock(); + float result = std::numeric_limits<float>::quiet_NaN(); + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_GAIN, &result); + unlock(); + return result; } -bool AUD_OpenALDevice::setCapability(int capability, void *value) +bool AUD_OpenALDevice::setVolume(AUD_Handle* handle, float volume) +{ + lock(); + bool result = isValid(handle); + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_GAIN, volume); + unlock(); + return result; +} + +float AUD_OpenALDevice::getPitch(AUD_Handle* handle) +{ + lock(); + float result = std::numeric_limits<float>::quiet_NaN(); + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_PITCH, &result); + unlock(); + return result; +} + +bool AUD_OpenALDevice::setPitch(AUD_Handle* handle, float pitch) +{ + lock(); + bool result = isValid(handle); + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_PITCH, pitch); + unlock(); + return result; +} + +int AUD_OpenALDevice::getLoopCount(AUD_Handle* handle) +{ + lock(); + int result = 0; + if(isValid(handle)) + result = ((AUD_OpenALHandle*)handle)->loopcount; + unlock(); + return result; +} + +bool AUD_OpenALDevice::setLoopCount(AUD_Handle* handle, int count) +{ + lock(); + bool result = isValid(handle); + if(result) + ((AUD_OpenALHandle*)handle)->loopcount = count; + unlock(); + return result; +} + +bool AUD_OpenALDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data) +{ + lock(); + bool result = isValid(handle); + if(result) + { + AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle; + h->stop = callback; + h->stop_data = data; + } + unlock(); + return result; +} + +/* AUD_XXX Temorary disabled + +bool AUD_OpenALDevice::bufferFactory(void *value) { bool result = false; - switch(capability) + AUD_IFactory* factory = (AUD_IFactory*) value; + + // load the factory into an OpenAL buffer + if(factory) { - case AUD_CAPS_VOLUME: - alListenerf(AL_GAIN, *((float*)value)); - return true; - case AUD_CAPS_SOURCE_VOLUME: + // check if the factory is already buffered + lock(); + for(AUD_BFIterator i = m_bufferedFactories->begin(); + i != m_bufferedFactories->end(); i++) { - AUD_SourceCaps* caps = (AUD_SourceCaps*) value; - lock(); - if(isValid(caps->handle)) + if((*i)->factory == factory) { - alSourcef(((AUD_OpenALHandle*)caps->handle)->source, - AL_GAIN, caps->value); result = true; + break; } - unlock(); } - break; - case AUD_CAPS_SOURCE_PITCH: + unlock(); + if(result) + return result; + + AUD_IReader* reader = factory->createReader(); + + if(reader == NULL) + return false; + + AUD_DeviceSpecs specs = m_specs; + specs.specs = reader->getSpecs(); + + if(m_specs.format != AUD_FORMAT_FLOAT32) + reader = new AUD_ConverterReader(reader, m_specs); + + ALenum format; + + if(!getFormat(format, specs.specs)) { - AUD_SourceCaps* caps = (AUD_SourceCaps*) value; - lock(); - if(isValid(caps->handle)) - { - alSourcef(((AUD_OpenALHandle*)caps->handle)->source, - AL_PITCH, caps->value); - result = true; - } - unlock(); + delete reader; + return false; } - break; - case AUD_CAPS_BUFFERED_FACTORY: + + // load into a buffer + lock(); + alcSuspendContext(m_context); + + AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory; + bf->factory = factory; + + try { - AUD_IFactory* factory = (AUD_IFactory*) value; + alGenBuffers(1, &bf->buffer); + if(alGetError() != AL_NO_ERROR) + AUD_THROW(AUD_ERROR_OPENAL); - // load the factory into an OpenAL buffer - if(factory) + try { - // check if the factory is already buffered - lock(); - for(AUD_BFIterator i = m_bufferedFactories->begin(); - i != m_bufferedFactories->end(); i++) - { - if((*i)->factory == factory) - { - result = true; - break; - } - } - unlock(); - if(result) - return result; + sample_t* buf; + int length = reader->getLength(); - AUD_IReader* reader = factory->createReader(); + reader->read(length, buf); + alBufferData(bf->buffer, format, buf, + length * AUD_DEVICE_SAMPLE_SIZE(specs), + specs.rate); + if(alGetError() != AL_NO_ERROR) + AUD_THROW(AUD_ERROR_OPENAL); + } + catch(AUD_Exception&) + { + alDeleteBuffers(1, &bf->buffer); + throw; + } + } + catch(AUD_Exception&) + { + delete bf; + delete reader; + alcProcessContext(m_context); + unlock(); + return false; + } - if(reader == NULL) - return false; + m_bufferedFactories->push_back(bf); - AUD_DeviceSpecs specs = m_specs; - specs.specs = reader->getSpecs(); + alcProcessContext(m_context); + unlock(); + } + else + { + // stop all playing and paused buffered sources + lock(); + alcSuspendContext(m_context); - // determine format - bool valid = reader->getType() == AUD_TYPE_BUFFER; + AUD_OpenALHandle* sound; + AUD_HandleIterator it = m_playingSounds->begin(); + while(it != m_playingSounds->end()) + { + sound = *it; + ++it; - if(valid) - { - if(m_converter) - { - m_converter->setReader(reader); - reader = m_converter->createReader(); - } - } + if(sound->isBuffered) + stop(sound); + } + alcProcessContext(m_context); - ALenum format; + while(!m_bufferedFactories->empty()) + { + alDeleteBuffers(1, + &(*(m_bufferedFactories->begin()))->buffer); + delete *m_bufferedFactories->begin(); + m_bufferedFactories->erase(m_bufferedFactories->begin()); + } + unlock(); + } - if(valid) - valid = getFormat(format, specs.specs); + return true; +}*/ - if(!valid) - { - delete reader; AUD_DELETE("reader") - return false; - } +/******************************************************************************/ +/**************************** 3D Device Code **********************************/ +/******************************************************************************/ - // load into a buffer - lock(); - alcSuspendContext(m_context); +AUD_Vector3 AUD_OpenALDevice::getListenerLocation() const +{ + ALfloat p[3]; + alGetListenerfv(AL_POSITION, p); + return AUD_Vector3(p[0], p[1], p[2]); +} - AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory; - AUD_NEW("bufferedfactory"); - bf->factory = factory; +void AUD_OpenALDevice::setListenerLocation(const AUD_Vector3& location) +{ + alListenerfv(AL_POSITION, (ALfloat*)location.get()); +} - try - { - alGenBuffers(1, &bf->buffer); - if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); +AUD_Vector3 AUD_OpenALDevice::getListenerVelocity() const +{ + ALfloat v[3]; + alGetListenerfv(AL_VELOCITY, v); + return AUD_Vector3(v[0], v[1], v[2]); +} - try - { - sample_t* buf; - int length = reader->getLength(); +void AUD_OpenALDevice::setListenerVelocity(const AUD_Vector3& velocity) +{ + alListenerfv(AL_VELOCITY, (ALfloat*)velocity.get()); +} - reader->read(length, buf); - alBufferData(bf->buffer, format, buf, - length * AUD_DEVICE_SAMPLE_SIZE(specs), - specs.rate); - if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL); - } - catch(AUD_Exception) - { - alDeleteBuffers(1, &bf->buffer); - throw; - } - } - catch(AUD_Exception) - { - delete bf; AUD_DELETE("bufferedfactory") - delete reader; AUD_DELETE("reader") - alcProcessContext(m_context); - unlock(); - return false; - } +AUD_Quaternion AUD_OpenALDevice::getListenerOrientation() const +{ + // AUD_XXX not implemented yet + return AUD_Quaternion(0, 0, 0, 0); +} - m_bufferedFactories->push_back(bf); +void AUD_OpenALDevice::setListenerOrientation(const AUD_Quaternion& orientation) +{ + ALfloat direction[6]; + direction[0] = -2 * (orientation.w() * orientation.y() + + orientation.x() * orientation.z()); + direction[1] = 2 * (orientation.x() * orientation.w() - + orientation.z() * orientation.y()); + direction[2] = 2 * (orientation.x() * orientation.x() + + orientation.y() * orientation.y()) - 1; + direction[3] = 2 * (orientation.x() * orientation.y() - + orientation.w() * orientation.z()); + direction[4] = 1 - 2 * (orientation.x() * orientation.x() + + orientation.z() * orientation.z()); + direction[5] = 2 * (orientation.w() * orientation.x() + + orientation.y() * orientation.z()); + alListenerfv(AL_ORIENTATION, direction); +} - alcProcessContext(m_context); - unlock(); - } - else - { - // stop all playing and paused buffered sources - lock(); - alcSuspendContext(m_context); +float AUD_OpenALDevice::getSpeedOfSound() const +{ + return alGetFloat(AL_SPEED_OF_SOUND); +} - AUD_OpenALHandle* sound; - AUD_HandleIterator it = m_playingSounds->begin(); - while(it != m_playingSounds->end()) - { - sound = *it; - ++it; +void AUD_OpenALDevice::setSpeedOfSound(float speed) +{ + alSpeedOfSound(speed); +} - if(sound->isBuffered) - stop(sound); - } - alcProcessContext(m_context); +float AUD_OpenALDevice::getDopplerFactor() const +{ + return alGetFloat(AL_DOPPLER_FACTOR); +} - while(!m_bufferedFactories->empty()) - { - alDeleteBuffers(1, - &(*(m_bufferedFactories->begin()))->buffer); - delete *m_bufferedFactories->begin(); - AUD_DELETE("bufferedfactory"); - m_bufferedFactories->erase(m_bufferedFactories->begin()); - } - unlock(); - } +void AUD_OpenALDevice::setDopplerFactor(float factor) +{ + alDopplerFactor(factor); +} - return true; - } - break; +AUD_DistanceModel AUD_OpenALDevice::getDistanceModel() const +{ + switch(alGetInteger(AL_DISTANCE_MODEL)) + { + case AL_INVERSE_DISTANCE: + return AUD_DISTANCE_MODEL_INVERSE; + case AL_INVERSE_DISTANCE_CLAMPED: + return AUD_DISTANCE_MODEL_INVERSE_CLAMPED; + case AL_LINEAR_DISTANCE: + return AUD_DISTANCE_MODEL_LINEAR; + case AL_LINEAR_DISTANCE_CLAMPED: + return AUD_DISTANCE_MODEL_LINEAR_CLAMPED; + case AL_EXPONENT_DISTANCE: + return AUD_DISTANCE_MODEL_EXPONENT; + case AL_EXPONENT_DISTANCE_CLAMPED: + return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED; + default: + return AUD_DISTANCE_MODEL_INVALID; } - return result; } -bool AUD_OpenALDevice::getCapability(int capability, void *value) +void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model) { - bool result = false; - - switch(capability) + switch(model) { - case AUD_CAPS_VOLUME: - alGetListenerf(AL_GAIN, (float*)value); - return true; - case AUD_CAPS_SOURCE_VOLUME: - { - AUD_SourceCaps* caps = (AUD_SourceCaps*) value; - lock(); - if(isValid(caps->handle)) - { - alGetSourcef(((AUD_OpenALHandle*)caps->handle)->source, - AL_GAIN, &caps->value); - result = true; - } - unlock(); - } + case AUD_DISTANCE_MODEL_INVERSE: + alDistanceModel(AL_INVERSE_DISTANCE); break; - case AUD_CAPS_SOURCE_PITCH: - { - AUD_SourceCaps* caps = (AUD_SourceCaps*) value; - lock(); - if(isValid(caps->handle)) - { - alGetSourcef(((AUD_OpenALHandle*)caps->handle)->source, - AL_PITCH, &caps->value); - result = true; - } - unlock(); - } + case AUD_DISTANCE_MODEL_INVERSE_CLAMPED: + alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); + break; + case AUD_DISTANCE_MODEL_LINEAR: + alDistanceModel(AL_LINEAR_DISTANCE); + break; + case AUD_DISTANCE_MODEL_LINEAR_CLAMPED: + alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); + break; + case AUD_DISTANCE_MODEL_EXPONENT: + alDistanceModel(AL_EXPONENT_DISTANCE); break; + case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED: + alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED); + break; + default: + alDistanceModel(AL_NONE); } +} + +AUD_Vector3 AUD_OpenALDevice::getSourceLocation(AUD_Handle* handle) +{ + AUD_Vector3 result = AUD_Vector3(0, 0, 0); + ALfloat p[3]; + lock(); + if(isValid(handle)) + { + alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION, p); + result = AUD_Vector3(p[0], p[1], p[2]); + } + + unlock(); return result; } -/******************************************************************************/ -/**************************** 3D Device Code **********************************/ -/******************************************************************************/ +bool AUD_OpenALDevice::setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION, + (ALfloat*)location.get()); -AUD_Handle* AUD_OpenALDevice::play3D(AUD_IFactory* factory, bool keep) + unlock(); + return result; +} + +AUD_Vector3 AUD_OpenALDevice::getSourceVelocity(AUD_Handle* handle) { - AUD_OpenALHandle* handle = (AUD_OpenALHandle*)play(factory, keep); - if(handle) - alSourcei(handle->source, AL_SOURCE_RELATIVE, 0); - return handle; + AUD_Vector3 result = AUD_Vector3(0, 0, 0); + ALfloat v[3]; + lock(); + + if(isValid(handle)) + { + alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY, v); + result = AUD_Vector3(v[0], v[1], v[2]); + } + + unlock(); + return result; } -bool AUD_OpenALDevice::updateListener(AUD_3DData &data) +bool AUD_OpenALDevice::setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity) { - alListenerfv(AL_POSITION, (ALfloat*)data.position); - alListenerfv(AL_VELOCITY, (ALfloat*)data.velocity); - alListenerfv(AL_ORIENTATION, (ALfloat*)&(data.orientation[3])); + lock(); + bool result = isValid(handle); - return true; + if(result) + alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY, + (ALfloat*)velocity.get()); + + unlock(); + return result; } -bool AUD_OpenALDevice::setSetting(AUD_3DSetting setting, float value) +AUD_Quaternion AUD_OpenALDevice::getSourceOrientation(AUD_Handle* handle) { - switch(setting) - { - case AUD_3DS_DISTANCE_MODEL: - if(value == AUD_DISTANCE_MODEL_NONE) - alDistanceModel(AL_NONE); - else if(value == AUD_DISTANCE_MODEL_INVERSE) - alDistanceModel(AL_INVERSE_DISTANCE); - else if(value == AUD_DISTANCE_MODEL_INVERSE_CLAMPED) - alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); - else if(value == AUD_DISTANCE_MODEL_LINEAR) - alDistanceModel(AL_LINEAR_DISTANCE); - else if(value == AUD_DISTANCE_MODEL_LINEAR_CLAMPED) - alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED); - else if(value == AUD_DISTANCE_MODEL_EXPONENT) - alDistanceModel(AL_EXPONENT_DISTANCE); - else if(value == AUD_DISTANCE_MODEL_EXPONENT_CLAMPED) - alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED); - else - return false; - return true; - case AUD_3DS_DOPPLER_FACTOR: - alDopplerFactor(value); - return true; - case AUD_3DS_SPEED_OF_SOUND: - alSpeedOfSound(value); - return true; - default: - return false; - } + // AUD_XXX not implemented yet + return AUD_Quaternion(0, 0, 0, 0); } -float AUD_OpenALDevice::getSetting(AUD_3DSetting setting) +bool AUD_OpenALDevice::setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation) { - switch(setting) + lock(); + bool result = isValid(handle); + + if(result) { - case AUD_3DS_DISTANCE_MODEL: - switch(alGetInteger(AL_DISTANCE_MODEL)) - { - case AL_NONE: - return AUD_DISTANCE_MODEL_NONE; - case AL_INVERSE_DISTANCE: - return AUD_DISTANCE_MODEL_INVERSE; - case AL_INVERSE_DISTANCE_CLAMPED: - return AUD_DISTANCE_MODEL_INVERSE_CLAMPED; - case AL_LINEAR_DISTANCE: - return AUD_DISTANCE_MODEL_LINEAR; - case AL_LINEAR_DISTANCE_CLAMPED: - return AUD_DISTANCE_MODEL_LINEAR_CLAMPED; - case AL_EXPONENT_DISTANCE: - return AUD_DISTANCE_MODEL_EXPONENT; - case AL_EXPONENT_DISTANCE_CLAMPED: - return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED; - } - case AUD_3DS_DOPPLER_FACTOR: - return alGetFloat(AL_DOPPLER_FACTOR); - case AUD_3DS_SPEED_OF_SOUND: - return alGetFloat(AL_SPEED_OF_SOUND); - default: - return std::numeric_limits<float>::quiet_NaN(); + ALfloat direction[3]; + direction[0] = -2 * (orientation.w() * orientation.y() + + orientation.x() * orientation.z()); + direction[1] = 2 * (orientation.x() * orientation.w() - + orientation.z() * orientation.y()); + direction[2] = 2 * (orientation.x() * orientation.x() + + orientation.y() * orientation.y()) - 1; + alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_DIRECTION, + direction); } + + unlock(); + return result; } -bool AUD_OpenALDevice::updateSource(AUD_Handle* handle, AUD_3DData &data) +bool AUD_OpenALDevice::isRelative(AUD_Handle* handle) { - bool result = false; + int result = std::numeric_limits<float>::quiet_NaN();; lock(); if(isValid(handle)) - { - int source = ((AUD_OpenALHandle*)handle)->source; - alSourcefv(source, AL_POSITION, (ALfloat*)data.position); - alSourcefv(source, AL_VELOCITY, (ALfloat*)data.velocity); - alSourcefv(source, AL_DIRECTION, (ALfloat*)&(data.orientation[3])); - result = true; - } + alGetSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE, + &result); unlock(); + return result; +} +bool AUD_OpenALDevice::setRelative(AUD_Handle* handle, bool relative) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE, + relative); + + unlock(); return result; } -bool AUD_OpenALDevice::setSourceSetting(AUD_Handle* handle, - AUD_3DSourceSetting setting, - float value) +float AUD_OpenALDevice::getVolumeMaximum(AUD_Handle* handle) { + float result = std::numeric_limits<float>::quiet_NaN();; + lock(); - bool result = false; + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN, + &result); + + unlock(); + return result; +} + +bool AUD_OpenALDevice::setVolumeMaximum(AUD_Handle* handle, float volume) +{ + lock(); + bool result = isValid(handle); + + if(result) + + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN, + volume); + + unlock(); + return result; +} + +float AUD_OpenALDevice::getVolumeMinimum(AUD_Handle* handle) +{ + float result = std::numeric_limits<float>::quiet_NaN();; + + lock(); if(isValid(handle)) - { - int source = ((AUD_OpenALHandle*)handle)->source; + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN, + &result); - switch(setting) - { - case AUD_3DSS_CONE_INNER_ANGLE: - alSourcef(source, AL_CONE_INNER_ANGLE, value); - result = true; - break; - case AUD_3DSS_CONE_OUTER_ANGLE: - alSourcef(source, AL_CONE_OUTER_ANGLE, value); - result = true; - break; - case AUD_3DSS_CONE_OUTER_GAIN: - alSourcef(source, AL_CONE_OUTER_GAIN, value); - result = true; - break; - case AUD_3DSS_IS_RELATIVE: - alSourcei(source, AL_SOURCE_RELATIVE, value > 0.0f); - result = true; - break; - case AUD_3DSS_MAX_DISTANCE: - alSourcef(source, AL_MAX_DISTANCE, value); - result = true; - break; - case AUD_3DSS_MAX_GAIN: - alSourcef(source, AL_MAX_GAIN, value); - result = true; - break; - case AUD_3DSS_MIN_GAIN: - alSourcef(source, AL_MIN_GAIN, value); - result = true; - break; - case AUD_3DSS_REFERENCE_DISTANCE: - alSourcef(source, AL_REFERENCE_DISTANCE, value); - result = true; - break; - case AUD_3DSS_ROLLOFF_FACTOR: - alSourcef(source, AL_ROLLOFF_FACTOR, value); - result = true; - break; - default: - break; - } - } + unlock(); + return result; +} + +bool AUD_OpenALDevice::setVolumeMinimum(AUD_Handle* handle, float volume) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN, + volume); unlock(); return result; } -float AUD_OpenALDevice::getSourceSetting(AUD_Handle* handle, - AUD_3DSourceSetting setting) +float AUD_OpenALDevice::getDistanceMaximum(AUD_Handle* handle) { float result = std::numeric_limits<float>::quiet_NaN();; lock(); if(isValid(handle)) - { - int source = ((AUD_OpenALHandle*)handle)->source; + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE, + &result); - switch(setting) - { - case AUD_3DSS_CONE_INNER_ANGLE: - alGetSourcef(source, AL_CONE_INNER_ANGLE, &result); - break; - case AUD_3DSS_CONE_OUTER_ANGLE: - alGetSourcef(source, AL_CONE_OUTER_ANGLE, &result); - break; - case AUD_3DSS_CONE_OUTER_GAIN: - alGetSourcef(source, AL_CONE_OUTER_GAIN, &result); - break; - case AUD_3DSS_IS_RELATIVE: - { - ALint i; - alGetSourcei(source, AL_SOURCE_RELATIVE, &i); - result = i ? 1.0f : 0.0f; - break; - } - case AUD_3DSS_MAX_DISTANCE: - alGetSourcef(source, AL_MAX_DISTANCE, &result); - break; - case AUD_3DSS_MAX_GAIN: - alGetSourcef(source, AL_MAX_GAIN, &result); - break; - case AUD_3DSS_MIN_GAIN: - alGetSourcef(source, AL_MIN_GAIN, &result); - break; - case AUD_3DSS_REFERENCE_DISTANCE: - alGetSourcef(source, AL_REFERENCE_DISTANCE, &result); - break; - case AUD_3DSS_ROLLOFF_FACTOR: - alGetSourcef(source, AL_ROLLOFF_FACTOR, &result); - break; - default: - break; - } - } + unlock(); + return result; +} + +bool AUD_OpenALDevice::setDistanceMaximum(AUD_Handle* handle, float distance) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE, + distance); + + unlock(); + return result; +} + +float AUD_OpenALDevice::getDistanceReference(AUD_Handle* handle) +{ + float result = std::numeric_limits<float>::quiet_NaN();; + + lock(); + + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE, + &result); + + unlock(); + return result; +} + +bool AUD_OpenALDevice::setDistanceReference(AUD_Handle* handle, float distance) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE, + distance); + + unlock(); + return result; +} + +float AUD_OpenALDevice::getAttenuation(AUD_Handle* handle) +{ + float result = std::numeric_limits<float>::quiet_NaN();; + + lock(); + + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR, + &result); + + unlock(); + return result; +} + +bool AUD_OpenALDevice::setAttenuation(AUD_Handle* handle, float factor) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR, + factor); + + unlock(); + return result; +} + +float AUD_OpenALDevice::getConeAngleOuter(AUD_Handle* handle) +{ + float result = std::numeric_limits<float>::quiet_NaN();; + + lock(); + + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE, + &result); + + unlock(); + return result; +} + +bool AUD_OpenALDevice::setConeAngleOuter(AUD_Handle* handle, float angle) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE, + angle); + + unlock(); + return result; +} + +float AUD_OpenALDevice::getConeAngleInner(AUD_Handle* handle) +{ + float result = std::numeric_limits<float>::quiet_NaN();; + + lock(); + + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE, + &result); + + unlock(); + return result; +} + +bool AUD_OpenALDevice::setConeAngleInner(AUD_Handle* handle, float angle) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE, + angle); + + unlock(); + return result; +} + +float AUD_OpenALDevice::getConeVolumeOuter(AUD_Handle* handle) +{ + float result = std::numeric_limits<float>::quiet_NaN();; + + lock(); + + if(isValid(handle)) + alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN, + &result); + + unlock(); + return result; +} + +bool AUD_OpenALDevice::setConeVolumeOuter(AUD_Handle* handle, float volume) +{ + lock(); + bool result = isValid(handle); + + if(result) + alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN, + volume); unlock(); return result; diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.h b/intern/audaspace/OpenAL/AUD_OpenALDevice.h index cb8c83ab810..985954fc20b 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.h +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.h @@ -30,7 +30,6 @@ #include "AUD_I3DDevice.h" struct AUD_OpenALHandle; struct AUD_OpenALBufferedFactory; -class AUD_ConverterFactory; #include <AL/al.h> #include <AL/alc.h> @@ -64,11 +63,6 @@ private: bool m_useMC; /** - * The converter factory for readers with wrong input format. - */ - AUD_ConverterFactory* m_converter; - - /** * The list of sounds that are currently playing. */ std::list<AUD_OpenALHandle*>* m_playingSounds; @@ -123,6 +117,10 @@ private: */ bool getFormat(ALenum &format, AUD_Specs specs); + // hide copy constructor and operator= + AUD_OpenALDevice(const AUD_OpenALDevice&); + AUD_OpenALDevice& operator=(const AUD_OpenALDevice&); + public: /** * Opens the OpenAL audio device for playback. @@ -142,31 +140,64 @@ public: virtual ~AUD_OpenALDevice(); - virtual AUD_DeviceSpecs getSpecs(); + virtual AUD_DeviceSpecs getSpecs() const; virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false); virtual bool pause(AUD_Handle* handle); virtual bool resume(AUD_Handle* handle); virtual bool stop(AUD_Handle* handle); + virtual bool getKeep(AUD_Handle* handle); virtual bool setKeep(AUD_Handle* handle, bool keep); - virtual bool sendMessage(AUD_Handle* handle, AUD_Message &message); virtual bool seek(AUD_Handle* handle, float position); virtual float getPosition(AUD_Handle* handle); virtual AUD_Status getStatus(AUD_Handle* handle); virtual void lock(); virtual void unlock(); - virtual bool checkCapability(int capability); - virtual bool setCapability(int capability, void *value); - virtual bool getCapability(int capability, void *value); - - virtual AUD_Handle* play3D(AUD_IFactory* factory, bool keep = false); - virtual bool updateListener(AUD_3DData &data); - virtual bool setSetting(AUD_3DSetting setting, float value); - virtual float getSetting(AUD_3DSetting setting); - virtual bool updateSource(AUD_Handle* handle, AUD_3DData &data); - virtual bool setSourceSetting(AUD_Handle* handle, - AUD_3DSourceSetting setting, float value); - virtual float getSourceSetting(AUD_Handle* handle, - AUD_3DSourceSetting setting); + virtual float getVolume() const; + virtual void setVolume(float volume); + virtual float getVolume(AUD_Handle* handle); + virtual bool setVolume(AUD_Handle* handle, float volume); + virtual float getPitch(AUD_Handle* handle); + virtual bool setPitch(AUD_Handle* handle, float pitch); + virtual int getLoopCount(AUD_Handle* handle); + virtual bool setLoopCount(AUD_Handle* handle, int count); + virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = NULL, void* data = NULL); + + virtual AUD_Vector3 getListenerLocation() const; + virtual void setListenerLocation(const AUD_Vector3& location); + virtual AUD_Vector3 getListenerVelocity() const; + virtual void setListenerVelocity(const AUD_Vector3& velocity); + virtual AUD_Quaternion getListenerOrientation() const; + virtual void setListenerOrientation(const AUD_Quaternion& orientation); + virtual float getSpeedOfSound() const; + virtual void setSpeedOfSound(float speed); + virtual float getDopplerFactor() const; + virtual void setDopplerFactor(float factor); + virtual AUD_DistanceModel getDistanceModel() const; + virtual void setDistanceModel(AUD_DistanceModel model); + virtual AUD_Vector3 getSourceLocation(AUD_Handle* handle); + virtual bool setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location); + virtual AUD_Vector3 getSourceVelocity(AUD_Handle* handle); + virtual bool setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity); + virtual AUD_Quaternion getSourceOrientation(AUD_Handle* handle); + virtual bool setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation); + virtual bool isRelative(AUD_Handle* handle); + virtual bool setRelative(AUD_Handle* handle, bool relative); + virtual float getVolumeMaximum(AUD_Handle* handle); + virtual bool setVolumeMaximum(AUD_Handle* handle, float volume); + virtual float getVolumeMinimum(AUD_Handle* handle); + virtual bool setVolumeMinimum(AUD_Handle* handle, float volume); + virtual float getDistanceMaximum(AUD_Handle* handle); + virtual bool setDistanceMaximum(AUD_Handle* handle, float distance); + virtual float getDistanceReference(AUD_Handle* handle); + virtual bool setDistanceReference(AUD_Handle* handle, float distance); + virtual float getAttenuation(AUD_Handle* handle); + virtual bool setAttenuation(AUD_Handle* handle, float factor); + virtual float getConeAngleOuter(AUD_Handle* handle); + virtual bool setConeAngleOuter(AUD_Handle* handle, float angle); + virtual float getConeAngleInner(AUD_Handle* handle); + virtual bool setConeAngleInner(AUD_Handle* handle, float angle); + virtual float getConeVolumeOuter(AUD_Handle* handle); + virtual bool setConeVolumeOuter(AUD_Handle* handle, float volume); }; #endif //AUD_OPENALDEVICE diff --git a/intern/audaspace/Python/AUD_PyAPI.cpp b/intern/audaspace/Python/AUD_PyAPI.cpp new file mode 100644 index 00000000000..4b1298b04a4 --- /dev/null +++ b/intern/audaspace/Python/AUD_PyAPI.cpp @@ -0,0 +1,2976 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_PyAPI.h" +#include "structmember.h" + +#include "AUD_I3DDevice.h" +#include "AUD_NULLDevice.h" +#include "AUD_DelayFactory.h" +#include "AUD_DoubleFactory.h" +#include "AUD_FaderFactory.h" +#include "AUD_HighpassFactory.h" +#include "AUD_LimiterFactory.h" +#include "AUD_LoopFactory.h" +#include "AUD_LowpassFactory.h" +#include "AUD_PingPongFactory.h" +#include "AUD_PitchFactory.h" +#include "AUD_ReverseFactory.h" +#include "AUD_SinusFactory.h" +#include "AUD_FileFactory.h" +#include "AUD_SquareFactory.h" +#include "AUD_StreamBufferFactory.h" +#include "AUD_SuperposeFactory.h" +#include "AUD_VolumeFactory.h" +#include "AUD_IIRFilterFactory.h" + +#ifdef WITH_SDL +#include "AUD_SDLDevice.h" +#endif + +#ifdef WITH_OPENAL +#include "AUD_OpenALDevice.h" +#endif + +#ifdef WITH_JACK +#include "AUD_JackDevice.h" +#endif + +#include <cstdlib> +#include <unistd.h> + +// ==================================================================== + +typedef enum +{ + AUD_DEVICE_NULL = 0, + AUD_DEVICE_OPENAL, + AUD_DEVICE_SDL, + AUD_DEVICE_JACK, + AUD_DEVICE_READ, +} AUD_DeviceTypes; + +// ==================================================================== + +#define PY_MODULE_ADD_CONSTANT(module, name) PyModule_AddIntConstant(module, #name, name) + +// ==================================================================== + +static PyObject* AUDError; + +static const char* device_not_3d_error = "Device is not a 3D device!"; + +// ==================================================================== + +static void +Factory_dealloc(Factory* self) +{ + if(self->factory) + delete self->factory; + Py_XDECREF(self->child_list); + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * +Factory_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + Factory *self; + + self = (Factory*)type->tp_alloc(type, 0); + if(self != NULL) + { + static const char *kwlist[] = {"filename", NULL}; + const char* filename = NULL; + + if(!PyArg_ParseTupleAndKeywords(args, kwds, "s:Factory", const_cast<char**>(kwlist), &filename)) + { + Py_DECREF(self); + return NULL; + } + + try + { + self->factory = new AUD_FileFactory(filename); + } + catch(AUD_Exception& e) + { + Py_DECREF(self); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)self; +} + +PyDoc_STRVAR(M_aud_Factory_sine_doc, + "sine(frequency, rate=44100)\n\n" + "Creates a sine factory which plays a sine wave.\n\n" + ":arg frequency: The frequency of the sine wave in Hz.\n" + ":type frequency: float\n" + ":arg rate: The sampling rate in Hz. It's recommended to set this " + "value to the playback device's samling rate to avoid resamping.\n" + ":type rate: int\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`"); + +static PyObject * +Factory_sine(PyTypeObject* type, PyObject* args) +{ + float frequency; + int rate = 44100; + + if(!PyArg_ParseTuple(args, "f|i:sine", &frequency, &rate)) + return NULL; + + Factory *self; + + self = (Factory*)type->tp_alloc(type, 0); + if(self != NULL) + { + try + { + self->factory = new AUD_SinusFactory(frequency, (AUD_SampleRate)rate); + } + catch(AUD_Exception& e) + { + Py_DECREF(self); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)self; +} + +PyDoc_STRVAR(M_aud_Factory_file_doc, + "file(filename)\n\n" + "Creates a factory object of a sound file.\n\n" + ":arg filename: Path of the file.\n" + ":type filename: string\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`\n\n" + ".. warning:: If the file doesn't exist or can't be read you will " + "not get an exception immediately, but when you try to start " + "playback of that factory."); + +static PyObject * +Factory_file(PyTypeObject* type, PyObject* args) +{ + const char* filename = NULL; + + if(!PyArg_ParseTuple(args, "s:file", &filename)) + return NULL; + + Factory *self; + + self = (Factory*)type->tp_alloc(type, 0); + if(self != NULL) + { + try + { + self->factory = new AUD_FileFactory(filename); + } + catch(AUD_Exception& e) + { + Py_DECREF(self); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)self; +} + +PyDoc_STRVAR(M_aud_Factory_lowpass_doc, + "lowpass(frequency, Q=0.5)\n\n" + "Creates a second order lowpass filter based on the transfer " + "function H(s) = 1 / (s^2 + s/Q + 1)\n\n" + ":arg frequency: The cut off trequency of the lowpass.\n" + ":type frequency: float\n" + ":arg Q: Q factor of the lowpass.\n" + ":type Q: float\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`"); + +static PyObject * +Factory_lowpass(Factory* self, PyObject* args) +{ + float frequency; + float Q = 0.5; + + if(!PyArg_ParseTuple(args, "f|f:lowpass", &frequency, &Q)) + return NULL; + + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + Py_INCREF(self); + parent->child_list = (PyObject*)self; + + try + { + parent->factory = new AUD_LowpassFactory(self->factory, frequency, Q); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_delay_doc, + "delay(time)\n\n" + "Delays by playing adding silence in front of the other factory's " + "data.\n\n" + ":arg time: How many seconds of silence should be added before " + "the factory.\n" + ":type time: float\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`"); + +static PyObject * +Factory_delay(Factory* self, PyObject* args) +{ + float delay; + + if(!PyArg_ParseTuple(args, "f:delay", &delay)) + return NULL; + + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + Py_INCREF(self); + parent->child_list = (PyObject*)self; + + try + { + parent->factory = new AUD_DelayFactory(self->factory, delay); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_join_doc, + "join(factory)\n\n" + "Plays two factories in sequence.\n\n" + ":arg factory: The factory to play second.\n" + ":type factory: :class:`Factory`\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`\n\n" + ".. note:: The two factories have to have the same specifications " + "(channels and samplerate)."); + +static PyObject * +Factory_join(Factory* self, PyObject* object) +{ + PyTypeObject* type = ((PyObject*)self)->ob_type; + + if(!PyObject_TypeCheck(object, type)) + { + PyErr_SetString(PyExc_TypeError, "Object has to be of type Factory!"); + return NULL; + } + + Factory *parent; + Factory *child = (Factory*)object; + + parent = (Factory*)type->tp_alloc(type, 0); + if(parent != NULL) + { + parent->child_list = Py_BuildValue("(OO)", self, object); + + try + { + parent->factory = new AUD_DoubleFactory(self->factory, child->factory); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_highpass_doc, + "highpass(frequency, Q=0.5)\n\n" + "Creates a second order highpass filter based on the transfer " + "function H(s) = s^2 / (s^2 + s/Q + 1)\n\n" + ":arg frequency: The cut off trequency of the highpass.\n" + ":type frequency: float\n" + ":arg Q: Q factor of the lowpass.\n" + ":type Q: float\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`"); + +static PyObject * +Factory_highpass(Factory* self, PyObject* args) +{ + float frequency; + float Q = 0.5; + + if(!PyArg_ParseTuple(args, "f|f:highpass", &frequency, &Q)) + return NULL; + + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + Py_INCREF(self); + parent->child_list = (PyObject*)self; + + try + { + parent->factory = new AUD_HighpassFactory(self->factory, frequency, Q); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_limit_doc, + "limit(start, end)\n\n" + "Limits a factory within a specific start and end time.\n\n" + ":arg start: Start time in seconds.\n" + ":type start: float\n" + ":arg end: End time in seconds.\n" + ":type end: float\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`"); + +static PyObject * +Factory_limit(Factory* self, PyObject* args) +{ + float start, end; + + if(!PyArg_ParseTuple(args, "ff:limit", &start, &end)) + return NULL; + + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + Py_INCREF(self); + parent->child_list = (PyObject*)self; + + try + { + parent->factory = new AUD_LimiterFactory(self->factory, start, end); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_pitch_doc, + "pitch(factor)\n\n" + "Changes the pitch of a factory with a specific factor.\n\n" + ":arg factor: The factor to change the pitch with.\n" + ":type factor: float\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`\n\n" + ".. note:: This is done by changing the sample rate of the " + "underlying factory, which has to be an integer, so the factor " + "value rounded and the factor may not be 100 % accurate.\n\n" + ".. note:: This is a filter function, you might consider using " + ":attr:`Handle.pitch` instead."); + +static PyObject * +Factory_pitch(Factory* self, PyObject* args) +{ + float factor; + + if(!PyArg_ParseTuple(args, "f:pitch", &factor)) + return NULL; + + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + Py_INCREF(self); + parent->child_list = (PyObject*)self; + + try + { + parent->factory = new AUD_PitchFactory(self->factory, factor); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_volume_doc, + "volume(volume)\n\n" + "Changes the volume of a factory.\n\n" + ":arg volume: The new volume..\n" + ":type volume: float\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`\n\n" + ".. note:: Should be in the range [0, 1] to avoid clipping.\n\n" + ".. note:: This is a filter function, you might consider using " + ":attr:`Handle.volume` instead."); + +static PyObject * +Factory_volume(Factory* self, PyObject* args) +{ + float volume; + + if(!PyArg_ParseTuple(args, "f:volume", &volume)) + return NULL; + + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + Py_INCREF(self); + parent->child_list = (PyObject*)self; + + try + { + parent->factory = new AUD_VolumeFactory(self->factory, volume); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_fadein_doc, + "fadein(start, length)\n\n" + "Fades a factory in by raising the volume linearly in the given " + "time interval.\n\n" + ":arg start: Time in seconds when the fading should start.\n" + ":type start: float\n" + ":arg length: Time in seconds how long the fading should last.\n" + ":type length: float\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`\n\n" + ".. note:: Before the fade starts it plays silence."); + +static PyObject * +Factory_fadein(Factory* self, PyObject* args) +{ + float start, length; + + if(!PyArg_ParseTuple(args, "ff:fadein", &start, &length)) + return NULL; + + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + Py_INCREF(self); + parent->child_list = (PyObject*)self; + + try + { + parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_IN, start, length); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_fadeout_doc, + "fadeout(start, length)\n\n" + "Fades a factory in by lowering the volume linearly in the given " + "time interval.\n\n" + ":arg start: Time in seconds when the fading should start.\n" + ":type start: float\n" + ":arg length: Time in seconds how long the fading should last.\n" + ":type length: float\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`\n\n" + ".. note:: After the fade this factory plays silence, so that " + "the length of the factory is not altered."); + +static PyObject * +Factory_fadeout(Factory* self, PyObject* args) +{ + float start, length; + + if(!PyArg_ParseTuple(args, "ff:fadeout", &start, &length)) + return NULL; + + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + Py_INCREF(self); + parent->child_list = (PyObject*)self; + + try + { + parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_OUT, start, length); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_loop_doc, + "loop(count)\n\n" + "Loops a factory.\n\n" + ":arg count: How often the factory should be looped. " + "Negative values mean endlessly.\n" + ":type count: integer\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`\n\n" + ".. note:: This is a filter function, you might consider using " + ":attr:`Handle.loop_count` instead."); + +static PyObject * +Factory_loop(Factory* self, PyObject* args) +{ + int loop; + + if(!PyArg_ParseTuple(args, "i:loop", &loop)) + return NULL; + + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + Py_INCREF(self); + parent->child_list = (PyObject*)self; + + try + { + parent->factory = new AUD_LoopFactory(self->factory, loop); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_mix_doc, + "mix(factory)\n\n" + "Mixes two factories.\n\n" + ":arg factory: The factory to mix over the other.\n" + ":type factory: :class:`Factory`\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`\n\n" + ".. note:: The two factories have to have the same specifications " + "(channels and samplerate)."); + +static PyObject * +Factory_mix(Factory* self, PyObject* object) +{ + PyTypeObject* type = ((PyObject*)self)->ob_type; + + if(!PyObject_TypeCheck(object, type)) + { + PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!"); + return NULL; + } + + Factory *parent = (Factory*)type->tp_alloc(type, 0); + Factory *child = (Factory*)object; + + if(parent != NULL) + { + parent->child_list = Py_BuildValue("(OO)", self, object); + + try + { + parent->factory = new AUD_SuperposeFactory(self->factory, child->factory); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_pingpong_doc, + "pingpong()\n\n" + "Plays a factory forward and then backward.\n" + "This is like joining a factory with its reverse.\n\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`"); + +static PyObject * +Factory_pingpong(Factory* self) +{ + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + Py_INCREF(self); + parent->child_list = (PyObject*)self; + + try + { + parent->factory = new AUD_PingPongFactory(self->factory); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_reverse_doc, + "reverse()\n\n" + "Plays a factory reversed.\n\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`\n\n" + ".. note:: The factory has to have a finite length and has to be " + "seekable. It's recommended to use this only with factories with " + "fast and accurate seeking, which is not true for encoded audio " + "files, such ones should be buffered using :meth:`buffer` before " + "being played reversed.\n\n" + ".. warning:: If seeking is not accurate in the underlying factory " + "you'll likely hear skips/jumps/cracks."); + +static PyObject * +Factory_reverse(Factory* self) +{ + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + Py_INCREF(self); + parent->child_list = (PyObject*)self; + + try + { + parent->factory = new AUD_ReverseFactory(self->factory); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_buffer_doc, + "buffer()\n\n" + "Buffers a factory into RAM.\n" + "This saves CPU usage needed for decoding and file access if the " + "underlying factory reads from a file on the harddisk, but it " + "consumes a lot of memory.\n\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`\n\n" + ".. note:: Only known-length factories can be buffered.\n\n" + ".. warning:: Raw PCM data needs a lot of space, only buffer " + "short factories."); + +static PyObject * +Factory_buffer(Factory* self) +{ + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + try + { + parent->factory = new AUD_StreamBufferFactory(self->factory); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_square_doc, + "square(threshold = 0)\n\n" + "Makes a square wave out of an audio wave by setting all samples " + "with a amplitude >= threshold to 1, all <= -threshold to -1 and " + "all between to 0.\n\n" + ":arg threshold: Threshold value over which an amplitude counts " + "non-zero.\n" + ":type threshold: float\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`"); + +static PyObject * +Factory_square(Factory* self, PyObject* args) +{ + float threshold = 0; + + if(!PyArg_ParseTuple(args, "|f:square", &threshold)) + return NULL; + + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + Py_INCREF(self); + parent->child_list = (PyObject*)self; + + try + { + parent->factory = new AUD_SquareFactory(self->factory, threshold); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +PyDoc_STRVAR(M_aud_Factory_filter_doc, + "filter(b, a = (1))\n\n" + "Filters a factory with the supplied IIR filter coefficients.\n" + "Without the second parameter you'll get a FIR filter.\n" + "If the first value of the a sequence is 0 it will be set to 1 " + "automatically.\n" + "If the first value of the a sequence is neither 0 nor 1, all " + "filter coefficients will be scaled by this value so that it is 1 " + "in the end, you don't have to scale yourself.\n\n" + ":arg b: The nominator filter coefficients.\n" + ":type b: sequence of float\n" + ":arg a: The denominator filter coefficients.\n" + ":type a: sequence of float\n" + ":return: The created :class:`Factory` object.\n" + ":rtype: :class:`Factory`"); + +static PyObject * +Factory_filter(Factory* self, PyObject* args) +{ + PyObject* py_b; + PyObject* py_a = NULL; + + if(!PyArg_ParseTuple(args, "O|O:filter", &py_b, &py_a)) + return NULL; + + if(!PySequence_Check(py_b) || (py_a != NULL && !PySequence_Check(py_a))) + { + PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!"); + return NULL; + } + + if(!PySequence_Length(py_b) || (py_a != NULL && !PySequence_Length(py_a))) + { + PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!"); + return NULL; + } + + std::vector<float> a, b; + PyObject* py_value; + float value; + int result; + + for(int i = 0; i < PySequence_Length(py_b); i++) + { + py_value = PySequence_GetItem(py_b, i); + result = PyArg_Parse(py_value, "f:filter", &value); + Py_DECREF(py_value); + + if(!result) + return NULL; + + b.push_back(value); + } + + if(py_a) + { + for(int i = 0; i < PySequence_Length(py_a); i++) + { + py_value = PySequence_GetItem(py_a, i); + result = PyArg_Parse(py_value, "f:filter", &value); + Py_DECREF(py_value); + + if(!result) + return NULL; + + a.push_back(value); + } + + if(a[0] == 0) + a[0] = 1; + } + else + a.push_back(1); + + PyTypeObject* type = ((PyObject*)self)->ob_type; + Factory *parent = (Factory*)type->tp_alloc(type, 0); + + if(parent != NULL) + { + Py_INCREF(self); + parent->child_list = (PyObject*)self; + + try + { + parent->factory = new AUD_IIRFilterFactory(self->factory, b, a); + } + catch(AUD_Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)parent; +} + +static PyMethodDef Factory_methods[] = { + {"sine", (PyCFunction)Factory_sine, METH_VARARGS | METH_CLASS, + M_aud_Factory_sine_doc + }, + {"file", (PyCFunction)Factory_file, METH_VARARGS | METH_CLASS, + M_aud_Factory_file_doc + }, + {"lowpass", (PyCFunction)Factory_lowpass, METH_VARARGS, + M_aud_Factory_lowpass_doc + }, + {"delay", (PyCFunction)Factory_delay, METH_VARARGS, + M_aud_Factory_delay_doc + }, + {"join", (PyCFunction)Factory_join, METH_O, + M_aud_Factory_join_doc + }, + {"highpass", (PyCFunction)Factory_highpass, METH_VARARGS, + M_aud_Factory_highpass_doc + }, + {"limit", (PyCFunction)Factory_limit, METH_VARARGS, + M_aud_Factory_limit_doc + }, + {"pitch", (PyCFunction)Factory_pitch, METH_VARARGS, + M_aud_Factory_pitch_doc + }, + {"volume", (PyCFunction)Factory_volume, METH_VARARGS, + M_aud_Factory_volume_doc + }, + {"fadein", (PyCFunction)Factory_fadein, METH_VARARGS, + M_aud_Factory_fadein_doc + }, + {"fadeout", (PyCFunction)Factory_fadeout, METH_VARARGS, + M_aud_Factory_fadeout_doc + }, + {"loop", (PyCFunction)Factory_loop, METH_VARARGS, + M_aud_Factory_loop_doc + }, + {"mix", (PyCFunction)Factory_mix, METH_O, + M_aud_Factory_mix_doc + }, + {"pingpong", (PyCFunction)Factory_pingpong, METH_NOARGS, + M_aud_Factory_pingpong_doc + }, + {"reverse", (PyCFunction)Factory_reverse, METH_NOARGS, + M_aud_Factory_reverse_doc + }, + {"buffer", (PyCFunction)Factory_buffer, METH_NOARGS, + M_aud_Factory_buffer_doc + }, + {"square", (PyCFunction)Factory_square, METH_VARARGS, + M_aud_Factory_square_doc + }, + {"filter", (PyCFunction)Factory_filter, METH_VARARGS, + M_aud_Factory_filter_doc + }, + {NULL} /* Sentinel */ +}; + +PyDoc_STRVAR(M_aud_Factory_doc, + "Factory objects are immutable and represent a sound that can be " + "played simultaneously multiple times. They are called factories " + "because they create reader objects internally that are used for " + "playback."); + +static PyTypeObject FactoryType = { + PyVarObject_HEAD_INIT(NULL, 0) + "aud.Factory", /* tp_name */ + sizeof(Factory), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)Factory_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + M_aud_Factory_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + Factory_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + Factory_new, /* tp_new */ +}; + +// ========== Handle ================================================== + +static void +Handle_dealloc(Handle* self) +{ + Py_XDECREF(self->device); + Py_TYPE(self)->tp_free((PyObject*)self); +} + +PyDoc_STRVAR(M_aud_Handle_pause_doc, + "pause()\n\n" + "Pauses playback.\n\n" + ":return: Whether the action succeeded.\n" + ":rtype: bool"); + +static PyObject * +Handle_pause(Handle *self) +{ + Device* device = (Device*)self->device; + + try + { + if(device->device->pause(self->handle)) + { + Py_RETURN_TRUE; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } + + Py_RETURN_FALSE; +} + +PyDoc_STRVAR(M_aud_Handle_resume_doc, + "resume()\n\n" + "Resumes playback.\n\n" + ":return: Whether the action succeeded.\n" + ":rtype: bool"); + +static PyObject * +Handle_resume(Handle *self) +{ + Device* device = (Device*)self->device; + + try + { + if(device->device->resume(self->handle)) + { + Py_RETURN_TRUE; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } + + Py_RETURN_FALSE; +} + +PyDoc_STRVAR(M_aud_Handle_stop_doc, + "stop()\n\n" + "Stops playback.\n\n" + ":return: Whether the action succeeded.\n" + ":rtype: bool\n\n" + ".. note:: This makes the handle invalid."); + +static PyObject * +Handle_stop(Handle *self) +{ + Device* device = (Device*)self->device; + + try + { + if(device->device->stop(self->handle)) + { + Py_RETURN_TRUE; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } + + Py_RETURN_FALSE; +} + +static PyMethodDef Handle_methods[] = { + {"pause", (PyCFunction)Handle_pause, METH_NOARGS, + M_aud_Handle_pause_doc + }, + {"resume", (PyCFunction)Handle_resume, METH_NOARGS, + M_aud_Handle_resume_doc + }, + {"stop", (PyCFunction)Handle_stop, METH_NOARGS, + M_aud_Handle_stop_doc + }, + {NULL} /* Sentinel */ +}; + +PyDoc_STRVAR(M_aud_Handle_position_doc, + "The playback position of the sound in seconds."); + +static PyObject * +Handle_get_position(Handle *self, void* nothing) +{ + Device* device = (Device*)self->device; + + try + { + return Py_BuildValue("f", device->device->getPosition(self->handle)); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Handle_set_position(Handle *self, PyObject* args, void* nothing) +{ + float position; + + if(!PyArg_Parse(args, "f:position", &position)) + return -1; + + Device* device = (Device*)self->device; + + try + { + if(device->device->seek(self->handle, position)) + return 0; + PyErr_SetString(AUDError, "Couldn't seek the sound!"); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_keep_doc, + "Whether the sound should be kept paused in the device when its " + "end is reached.\n" + "This can be used to seek the sound to some position and start " + "playback again.\n\n" + ".. warning:: If this is set to true and you forget stopping this " + "equals a memory leak as the handle exists until the device is " + "destroyed."); + +static PyObject * +Handle_get_keep(Handle *self, void* nothing) +{ + Device* device = (Device*)self->device; + + try + { + if(device->device->getKeep(self->handle)) + { + Py_RETURN_TRUE; + } + else + { + Py_RETURN_FALSE; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Handle_set_keep(Handle *self, PyObject* args, void* nothing) +{ + if(!PyBool_Check(args)) + { + PyErr_SetString(PyExc_TypeError, "keep is not a boolean!"); + return -1; + } + + bool keep = args == Py_True; + Device* device = (Device*)self->device; + + try + { + if(device->device->setKeep(self->handle, keep)) + return 0; + PyErr_SetString(AUDError, "Couldn't set keep of the sound!"); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_status_doc, + "Whether the sound is playing, paused or stopped (=invalid)."); + +static PyObject * +Handle_get_status(Handle *self, void* nothing) +{ + Device* device = (Device*)self->device; + + try + { + return Py_BuildValue("i", device->device->getStatus(self->handle)); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +PyDoc_STRVAR(M_aud_Handle_volume_doc, + "The volume of the sound."); + +static PyObject * +Handle_get_volume(Handle *self, void* nothing) +{ + Device* device = (Device*)self->device; + + try + { + return Py_BuildValue("f", device->device->getVolume(self->handle)); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Handle_set_volume(Handle *self, PyObject* args, void* nothing) +{ + float volume; + + if(!PyArg_Parse(args, "f:volume", &volume)) + return -1; + + Device* device = (Device*)self->device; + + try + { + if(device->device->setVolume(self->handle, volume)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the sound volume!"); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_pitch_doc, + "The pitch of the sound."); + +static PyObject * +Handle_get_pitch(Handle *self, void* nothing) +{ + Device* device = (Device*)self->device; + + try + { + return Py_BuildValue("f", device->device->getPitch(self->handle)); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Handle_set_pitch(Handle *self, PyObject* args, void* nothing) +{ + float pitch; + + if(!PyArg_Parse(args, "f:pitch", &pitch)) + return -1; + + Device* device = (Device*)self->device; + + try + { + if(device->device->setPitch(self->handle, pitch)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the sound pitch!"); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_loop_count_doc, + "The (remaining) loop count of the sound. A negative value indicates infinity."); + +static PyObject * +Handle_get_loop_count(Handle *self, void* nothing) +{ + Device* device = (Device*)self->device; + + try + { + return Py_BuildValue("i", device->device->getLoopCount(self->handle)); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Handle_set_loop_count(Handle *self, PyObject* args, void* nothing) +{ + int loops; + + if(!PyArg_Parse(args, "i:loop_count", &loops)) + return -1; + + Device* device = (Device*)self->device; + + try + { + if(device->device->setLoopCount(self->handle, loops)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the loop count!"); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_location_doc, + "The source's location in 3D space, a 3D tuple of floats."); + +static PyObject * +Handle_get_location(Handle *self, void* nothing) +{ + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + AUD_Vector3 v = device->getSourceLocation(self->handle); + return Py_BuildValue("(fff)", v.x(), v.y(), v.z()); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return NULL; +} + +static int +Handle_set_location(Handle *self, PyObject* args, void* nothing) +{ + float x, y, z; + + if(!PyArg_Parse(args, "(fff):location", &x, &y, &z)) + return -1; + + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + AUD_Vector3 location(x, y, z); + if(device->setSourceLocation(self->handle, location)) + return 0; + PyErr_SetString(AUDError, "Location couldn't be set!"); + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_velocity_doc, + "The source's velocity in 3D space, a 3D tuple of floats."); + +static PyObject * +Handle_get_velocity(Handle *self, void* nothing) +{ + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + AUD_Vector3 v = device->getSourceVelocity(self->handle); + return Py_BuildValue("(fff)", v.x(), v.y(), v.z()); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return NULL; +} + +static int +Handle_set_velocity(Handle *self, PyObject* args, void* nothing) +{ + float x, y, z; + + if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z)) + return -1; + + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + AUD_Vector3 velocity(x, y, z); + if(device->setSourceVelocity(self->handle, velocity)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the velocity!"); + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_orientation_doc, + "The source's orientation in 3D space as quaternion, a 4 float tuple."); + +static PyObject * +Handle_get_orientation(Handle *self, void* nothing) +{ + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + AUD_Quaternion o = device->getSourceOrientation(self->handle); + return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z()); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return NULL; +} + +static int +Handle_set_orientation(Handle *self, PyObject* args, void* nothing) +{ + float w, x, y, z; + + if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z)) + return -1; + + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + AUD_Quaternion orientation(w, x, y, z); + if(device->setSourceOrientation(self->handle, orientation)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the orientation!"); + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_relative_doc, + "Whether the source's location, velocity and orientation is relative or absolute to the listener."); + +static PyObject * +Handle_get_relative(Handle *self, void* nothing) +{ + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + if(device->isRelative(self->handle)) + { + Py_RETURN_TRUE; + } + else + { + Py_RETURN_FALSE; + } + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return NULL; +} + +static int +Handle_set_relative(Handle *self, PyObject* args, void* nothing) +{ + if(!PyBool_Check(args)) + { + PyErr_SetString(PyExc_TypeError, "Value is not a boolean!"); + return -1; + } + + bool relative = (args == Py_True); + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + if(device->setRelative(self->handle, relative)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the relativeness!"); + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc, + "The minimum volume of the source.\n\n" + ".. seealso:: :attr:`Device.distance_model`"); + +static PyObject * +Handle_get_volume_minimum(Handle *self, void* nothing) +{ + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + return Py_BuildValue("f", device->getVolumeMinimum(self->handle)); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + return NULL; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing) +{ + float volume; + + if(!PyArg_Parse(args, "f:volume_minimum", &volume)) + return -1; + + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + if(device->setVolumeMinimum(self->handle, volume)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the minimum volume!"); + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc, + "The maximum volume of the source.\n\n" + ".. seealso:: :attr:`Device.distance_model`"); + +static PyObject * +Handle_get_volume_maximum(Handle *self, void* nothing) +{ + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + return Py_BuildValue("f", device->getVolumeMaximum(self->handle)); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + return NULL; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing) +{ + float volume; + + if(!PyArg_Parse(args, "f:volume_maximum", &volume)) + return -1; + + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + if(device->setVolumeMaximum(self->handle, volume)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the maximum volume!"); + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_distance_reference_doc, + "The reference distance of the source.\n" + "At this distance the volume will be exactly :attr:`volume`.\n\n" + ".. seealso:: :attr:`Device.distance_model`"); + +static PyObject * +Handle_get_distance_reference(Handle *self, void* nothing) +{ + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + return Py_BuildValue("f", device->getDistanceReference(self->handle)); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + return NULL; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing) +{ + float distance; + + if(!PyArg_Parse(args, "f:distance_reference", &distance)) + return -1; + + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + if(device->setDistanceReference(self->handle, distance)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the reference distance!"); + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc, + "The maximum distance of the source.\n" + "If the listener is further away the source volume will be 0.\n\n" + ".. seealso:: :attr:`Device.distance_model`"); + +static PyObject * +Handle_get_distance_maximum(Handle *self, void* nothing) +{ + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + return Py_BuildValue("f", device->getDistanceMaximum(self->handle)); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + return NULL; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing) +{ + float distance; + + if(!PyArg_Parse(args, "f:distance_maximum", &distance)) + return -1; + + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + if(device->setDistanceMaximum(self->handle, distance)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the maximum distance!"); + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_attenuation_doc, + "This factor is used for distance based attenuation of the " + "source.\n\n" + ".. seealso:: :attr:`Device.distance_model`"); + +static PyObject * +Handle_get_attenuation(Handle *self, void* nothing) +{ + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + return Py_BuildValue("f", device->getAttenuation(self->handle)); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + return NULL; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Handle_set_attenuation(Handle *self, PyObject* args, void* nothing) +{ + float factor; + + if(!PyArg_Parse(args, "f:attenuation", &factor)) + return -1; + + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + if(device->setAttenuation(self->handle, factor)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the attenuation!"); + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc, + "The opening angle of the inner cone of the source. If the cone " + "values of a source are set there are two (audible) cones with " + "the apex at the :attr:`location` of the source and with infinite " + "height, heading in the direction of the source's " + ":attr:`orientation`.\n" + "In the inner cone the volume is normal. Outside the outer cone " + "the volume will be :attr:`cone_volume_outer` and in the area " + "between the volume will be interpolated linearly."); + +static PyObject * +Handle_get_cone_angle_inner(Handle *self, void* nothing) +{ + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + return Py_BuildValue("f", device->getConeAngleInner(self->handle)); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + return NULL; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing) +{ + float angle; + + if(!PyArg_Parse(args, "f:cone_angle_inner", &angle)) + return -1; + + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + if(device->setConeAngleInner(self->handle, angle)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the cone inner angle!"); + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc, + "The opening angle of the outer cone of the source.\n\n" + ".. seealso:: :attr:`cone_angle_inner`"); + +static PyObject * +Handle_get_cone_angle_outer(Handle *self, void* nothing) +{ + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + return Py_BuildValue("f", device->getConeAngleOuter(self->handle)); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + return NULL; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing) +{ + float angle; + + if(!PyArg_Parse(args, "f:cone_angle_outer", &angle)) + return -1; + + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + if(device->setConeAngleOuter(self->handle, angle)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the cone outer angle!"); + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc, + "The volume outside the outer cone of the source.\n\n" + ".. seealso:: :attr:`cone_angle_inner`"); + +static PyObject * +Handle_get_cone_volume_outer(Handle *self, void* nothing) +{ + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + return Py_BuildValue("f", device->getConeVolumeOuter(self->handle)); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + return NULL; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing) +{ + float volume; + + if(!PyArg_Parse(args, "f:cone_volume_outer", &volume)) + return -1; + + Device* dev = (Device*)self->device; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); + if(device) + { + if(device->setConeVolumeOuter(self->handle, volume)) + return 0; + PyErr_SetString(AUDError, "Couldn't set the cone outer volume!"); + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +static PyGetSetDef Handle_properties[] = { + {(char*)"position", (getter)Handle_get_position, (setter)Handle_set_position, + M_aud_Handle_position_doc, NULL }, + {(char*)"keep", (getter)Handle_get_keep, (setter)Handle_set_keep, + M_aud_Handle_keep_doc, NULL }, + {(char*)"status", (getter)Handle_get_status, NULL, + M_aud_Handle_status_doc, NULL }, + {(char*)"volume", (getter)Handle_get_volume, (setter)Handle_set_volume, + M_aud_Handle_volume_doc, NULL }, + {(char*)"pitch", (getter)Handle_get_pitch, (setter)Handle_set_pitch, + M_aud_Handle_pitch_doc, NULL }, + {(char*)"loop_count", (getter)Handle_get_loop_count, (setter)Handle_set_loop_count, + M_aud_Handle_loop_count_doc, NULL }, + {(char*)"location", (getter)Handle_get_location, (setter)Handle_set_location, + M_aud_Handle_location_doc, NULL }, + {(char*)"velocity", (getter)Handle_get_velocity, (setter)Handle_set_velocity, + M_aud_Handle_velocity_doc, NULL }, + {(char*)"orientation", (getter)Handle_get_orientation, (setter)Handle_set_orientation, + M_aud_Handle_orientation_doc, NULL }, + {(char*)"relative", (getter)Handle_get_relative, (setter)Handle_set_relative, + M_aud_Handle_relative_doc, NULL }, + {(char*)"volume_minimum", (getter)Handle_get_volume_minimum, (setter)Handle_set_volume_minimum, + M_aud_Handle_volume_minimum_doc, NULL }, + {(char*)"volume_maximum", (getter)Handle_get_volume_maximum, (setter)Handle_set_volume_maximum, + M_aud_Handle_volume_maximum_doc, NULL }, + {(char*)"distance_reference", (getter)Handle_get_distance_reference, (setter)Handle_set_distance_reference, + M_aud_Handle_distance_reference_doc, NULL }, + {(char*)"distance_maximum", (getter)Handle_get_distance_maximum, (setter)Handle_set_distance_maximum, + M_aud_Handle_distance_maximum_doc, NULL }, + {(char*)"attenuation", (getter)Handle_get_attenuation, (setter)Handle_set_attenuation, + M_aud_Handle_attenuation_doc, NULL }, + {(char*)"cone_angle_inner", (getter)Handle_get_cone_angle_inner, (setter)Handle_set_cone_angle_inner, + M_aud_Handle_cone_angle_inner_doc, NULL }, + {(char*)"cone_angle_outer", (getter)Handle_get_cone_angle_outer, (setter)Handle_set_cone_angle_outer, + M_aud_Handle_cone_angle_outer_doc, NULL }, + {(char*)"cone_volume_outer", (getter)Handle_get_cone_volume_outer, (setter)Handle_set_cone_volume_outer, + M_aud_Handle_cone_volume_outer_doc, NULL }, + {NULL} /* Sentinel */ +}; + +PyDoc_STRVAR(M_aud_Handle_doc, + "Handle objects are playback handles that can be used to control " + "playback of a sound. If a sound is played back multiple times " + "then there are as many handles."); + +static PyTypeObject HandleType = { + PyVarObject_HEAD_INIT(NULL, 0) + "aud.Handle", /* tp_name */ + sizeof(Handle), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)Handle_dealloc,/* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + M_aud_Handle_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + Handle_methods, /* tp_methods */ + 0, /* tp_members */ + Handle_properties, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + +// ========== Device ================================================== + +static void +Device_dealloc(Device* self) +{ + if(self->device) + delete self->device; + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * +Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + Device *self; + + static const char *kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", NULL}; + int device; + int rate = AUD_RATE_44100; + int channels = AUD_CHANNELS_STEREO; + int format = AUD_FORMAT_FLOAT32; + int buffersize = AUD_DEFAULT_BUFFER_SIZE; + const char* name = "Audaspace"; + + if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|iiiis:Device", const_cast<char**>(kwlist), + &device, &rate, &channels, &format, &buffersize, &name)) + return NULL; + + if(buffersize < 128) + { + PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than 127!"); + return NULL; + } + + self = (Device*)type->tp_alloc(type, 0); + if(self != NULL) + { + AUD_DeviceSpecs specs; + specs.channels = (AUD_Channels)channels; + specs.format = (AUD_SampleFormat)format; + specs.rate = (AUD_SampleRate)rate; + + self->device = NULL; + + try + { + switch(device) + { + case AUD_DEVICE_NULL: + self->device = new AUD_NULLDevice(); + break; + case AUD_DEVICE_OPENAL: +#ifdef WITH_OPENAL + self->device = new AUD_OpenALDevice(specs, buffersize); +#endif + break; + case AUD_DEVICE_SDL: +#ifdef WITH_SDL + self->device = new AUD_SDLDevice(specs, buffersize); +#endif + break; + case AUD_DEVICE_JACK: +#ifdef WITH_JACK + self->device = new AUD_JackDevice(name, specs, buffersize); +#endif + break; + case AUD_DEVICE_READ: + break; + } + + } + catch(AUD_Exception& e) + { + Py_DECREF(self); + PyErr_SetString(AUDError, e.str); + return NULL; + } + + if(!self->device) + { + Py_DECREF(self); + PyErr_SetString(AUDError, "Unsupported device type!"); + return NULL; + } + } + + return (PyObject *)self; +} + +PyDoc_STRVAR(M_aud_Device_play_doc, + "play(factory, keep=False)\n\n" + "Plays a factory.\n\n" + ":arg factory: The factory to play.\n" + ":type factory: :class:`Factory`\n" + ":arg keep: See :attr:`Handle.keep`.\n" + ":type keep: bool\n" + ":return: The playback handle with which playback can be " + "controlled with.\n" + ":rtype: :class:`Handle`"); + +static PyObject * +Device_play(Device *self, PyObject *args, PyObject *kwds) +{ + PyObject* object; + PyObject* keepo = NULL; + + bool keep = false; + + static const char *kwlist[] = {"factory", "keep", NULL}; + + if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:play", const_cast<char**>(kwlist), &object, &keepo)) + return NULL; + + if(!PyObject_TypeCheck(object, &FactoryType)) + { + PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!"); + return NULL; + } + + if(keepo != NULL) + { + if(!PyBool_Check(keepo)) + { + PyErr_SetString(PyExc_TypeError, "keep is not a boolean!"); + return NULL; + } + + keep = keepo == Py_True; + } + + Factory* sound = (Factory*)object; + Handle *handle; + + handle = (Handle*)HandleType.tp_alloc(&HandleType, 0); + if(handle != NULL) + { + handle->device = (PyObject*)self; + Py_INCREF(self); + + try + { + handle->handle = self->device->play(sound->factory, keep); + } + catch(AUD_Exception& e) + { + Py_DECREF(handle); + PyErr_SetString(AUDError, e.str); + return NULL; + } + } + + return (PyObject *)handle; +} + +PyDoc_STRVAR(M_aud_Device_lock_doc, + "lock()\n\n" + "Locks the device so that it's guaranteed, that no samples are " + "read from the streams until :meth:`unlock` is called.\n" + "This is useful if you want to do start/stop/pause/resume some " + "sounds at the same time.\n\n" + ".. note:: The device has to be unlocked as often as locked to be " + "able to continue playback.\n\n" + ".. warning:: Make sure the time between locking and unlocking is " + "as short as possible to avoid clicks."); + +static PyObject * +Device_lock(Device *self) +{ + try + { + self->device->lock(); + Py_RETURN_NONE; + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +PyDoc_STRVAR(M_aud_Device_unlock_doc, + "unlock()\n\n" + "Unlocks the device after a lock call, see :meth:`lock` for " + "details."); + +static PyObject * +Device_unlock(Device *self) +{ + try + { + self->device->unlock(); + Py_RETURN_NONE; + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static PyMethodDef Device_methods[] = { + {"play", (PyCFunction)Device_play, METH_VARARGS | METH_KEYWORDS, + M_aud_Device_play_doc + }, + {"lock", (PyCFunction)Device_lock, METH_NOARGS, + M_aud_Device_lock_doc + }, + {"unlock", (PyCFunction)Device_unlock, METH_NOARGS, + M_aud_Device_unlock_doc + }, + {NULL} /* Sentinel */ +}; + +PyDoc_STRVAR(M_aud_Device_rate_doc, + "The sampling rate of the device in Hz."); + +static PyObject * +Device_get_rate(Device *self, void* nothing) +{ + try + { + AUD_DeviceSpecs specs = self->device->getSpecs(); + return Py_BuildValue("i", specs.rate); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +PyDoc_STRVAR(M_aud_Device_format_doc, + "The native sample format of the device."); + +static PyObject * +Device_get_format(Device *self, void* nothing) +{ + try + { + AUD_DeviceSpecs specs = self->device->getSpecs(); + return Py_BuildValue("i", specs.format); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +PyDoc_STRVAR(M_aud_Device_channels_doc, + "The channel count of the device."); + +static PyObject * +Device_get_channels(Device *self, void* nothing) +{ + try + { + AUD_DeviceSpecs specs = self->device->getSpecs(); + return Py_BuildValue("i", specs.channels); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +PyDoc_STRVAR(M_aud_Device_volume_doc, + "The overall volume of the device."); + +static PyObject * +Device_get_volume(Device *self, void* nothing) +{ + try + { + return Py_BuildValue("f", self->device->getVolume()); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Device_set_volume(Device *self, PyObject* args, void* nothing) +{ + float volume; + + if(!PyArg_Parse(args, "f:volume", &volume)) + return -1; + + try + { + self->device->setVolume(volume); + return 0; + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return -1; + } +} + +PyDoc_STRVAR(M_aud_Device_listener_location_doc, + "The listeners's location in 3D space, a 3D tuple of floats."); + +static PyObject * +Device_get_listener_location(Device *self, void* nothing) +{ + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + if(device) + { + AUD_Vector3 v = device->getListenerLocation(); + return Py_BuildValue("(fff)", v.x(), v.y(), v.z()); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return NULL; +} + +static int +Device_set_listener_location(Device *self, PyObject* args, void* nothing) +{ + float x, y, z; + + if(!PyArg_Parse(args, "(fff):listener_location", &x, &y, &z)) + return -1; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + if(device) + { + AUD_Vector3 location(x, y, z); + device->setListenerLocation(location); + return 0; + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Device_listener_velocity_doc, + "The listener's velocity in 3D space, a 3D tuple of floats."); + +static PyObject * +Device_get_listener_velocity(Device *self, void* nothing) +{ + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + if(device) + { + AUD_Vector3 v = device->getListenerVelocity(); + return Py_BuildValue("(fff)", v.x(), v.y(), v.z()); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return NULL; +} + +static int +Device_set_listener_velocity(Device *self, PyObject* args, void* nothing) +{ + float x, y, z; + + if(!PyArg_Parse(args, "(fff):listener_velocity", &x, &y, &z)) + return -1; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + if(device) + { + AUD_Vector3 velocity(x, y, z); + device->setListenerVelocity(velocity); + return 0; + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Device_listener_orientation_doc, + "The listener's orientation in 3D space as quaternion, a 4 float tuple."); + +static PyObject * +Device_get_listener_orientation(Device *self, void* nothing) +{ + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + if(device) + { + AUD_Quaternion o = device->getListenerOrientation(); + return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z()); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return NULL; +} + +static int +Device_set_listener_orientation(Device *self, PyObject* args, void* nothing) +{ + float w, x, y, z; + + if(!PyArg_Parse(args, "(ffff):listener_orientation", &w, &x, &y, &z)) + return -1; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + if(device) + { + AUD_Quaternion orientation(w, x, y, z); + device->setListenerOrientation(orientation); + return 0; + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Device_speed_of_sound_doc, + "The speed of sound of the device.\n" + "The speed of sound in air is typically 343 m/s."); + +static PyObject * +Device_get_speed_of_sound(Device *self, void* nothing) +{ + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + if(device) + { + return Py_BuildValue("f", device->getSpeedOfSound()); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + return NULL; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Device_set_speed_of_sound(Device *self, PyObject* args, void* nothing) +{ + float speed; + + if(!PyArg_Parse(args, "f:speed_of_sound", &speed)) + return -1; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + if(device) + { + device->setSpeedOfSound(speed); + return 0; + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Device_doppler_factor_doc, + "The doppler factor of the device.\n" + "This factor is a scaling factor for the velocity vectors in " + "doppler calculation. So a value bigger than 1 will exaggerate " + "the effect as it raises the velocity."); + +static PyObject * +Device_get_doppler_factor(Device *self, void* nothing) +{ + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + if(device) + { + return Py_BuildValue("f", device->getDopplerFactor()); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + return NULL; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Device_set_doppler_factor(Device *self, PyObject* args, void* nothing) +{ + float factor; + + if(!PyArg_Parse(args, "f:doppler_factor", &factor)) + return -1; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + if(device) + { + device->setDopplerFactor(factor); + return 0; + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +PyDoc_STRVAR(M_aud_Device_distance_model_doc, + "The distance model of the device.\n\n" + ".. seealso:: http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm#_Toc199835864"); + +static PyObject * +Device_get_distance_model(Device *self, void* nothing) +{ + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + if(device) + { + return Py_BuildValue("i", int(device->getDistanceModel())); + } + else + { + PyErr_SetString(AUDError, device_not_3d_error); + return NULL; + } + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + return NULL; + } +} + +static int +Device_set_distance_model(Device *self, PyObject* args, void* nothing) +{ + int model; + + if(!PyArg_Parse(args, "i:distance_model", &model)) + return -1; + + try + { + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + if(device) + { + device->setDistanceModel(AUD_DistanceModel(model)); + return 0; + } + else + PyErr_SetString(AUDError, device_not_3d_error); + } + catch(AUD_Exception& e) + { + PyErr_SetString(AUDError, e.str); + } + + return -1; +} + +static PyGetSetDef Device_properties[] = { + {(char*)"rate", (getter)Device_get_rate, NULL, + M_aud_Device_rate_doc, NULL }, + {(char*)"format", (getter)Device_get_format, NULL, + M_aud_Device_format_doc, NULL }, + {(char*)"channels", (getter)Device_get_channels, NULL, + M_aud_Device_channels_doc, NULL }, + {(char*)"volume", (getter)Device_get_volume, (setter)Device_set_volume, + M_aud_Device_volume_doc, NULL }, + {(char*)"listener_location", (getter)Device_get_listener_location, (setter)Device_set_listener_location, + M_aud_Device_listener_location_doc, NULL }, + {(char*)"listener_velocity", (getter)Device_get_listener_velocity, (setter)Device_set_listener_velocity, + M_aud_Device_listener_velocity_doc, NULL }, + {(char*)"listener_orientation", (getter)Device_get_listener_orientation, (setter)Device_set_listener_orientation, + M_aud_Device_listener_orientation_doc, NULL }, + {(char*)"speed_of_sound", (getter)Device_get_speed_of_sound, (setter)Device_set_speed_of_sound, + M_aud_Device_speed_of_sound_doc, NULL }, + {(char*)"doppler_factor", (getter)Device_get_doppler_factor, (setter)Device_set_doppler_factor, + M_aud_Device_doppler_factor_doc, NULL }, + {(char*)"distance_model", (getter)Device_get_distance_model, (setter)Device_set_distance_model, + M_aud_Device_distance_model_doc, NULL }, + {NULL} /* Sentinel */ +}; + +PyDoc_STRVAR(M_aud_Device_doc, + "Device objects represent an audio output backend like OpenAL or " + "SDL, but might also represent a file output or RAM buffer " + "output."); + +static PyTypeObject DeviceType = { + PyVarObject_HEAD_INIT(NULL, 0) + "aud.Device", /* tp_name */ + sizeof(Device), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)Device_dealloc,/* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_reserved */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + M_aud_Device_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + Device_methods, /* tp_methods */ + 0, /* tp_members */ + Device_properties, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + Device_new, /* tp_new */ +}; + +PyObject * +Device_empty() +{ + return DeviceType.tp_alloc(&DeviceType, 0); +} + +// ==================================================================== + +PyDoc_STRVAR(M_aud_doc, + "This module provides access to the audaspace audio library."); + +static struct PyModuleDef audmodule = { + PyModuleDef_HEAD_INIT, + "aud", /* name of module */ + M_aud_doc, /* module documentation */ + -1, /* size of per-interpreter state of the module, + or -1 if the module keeps state in global variables. */ + NULL, NULL, NULL, NULL, NULL +}; + +PyMODINIT_FUNC +PyInit_aud(void) +{ + PyObject* m; + + if(PyType_Ready(&FactoryType) < 0) + return NULL; + + if(PyType_Ready(&DeviceType) < 0) + return NULL; + + if(PyType_Ready(&HandleType) < 0) + return NULL; + + m = PyModule_Create(&audmodule); + if(m == NULL) + return NULL; + + Py_INCREF(&FactoryType); + PyModule_AddObject(m, "Factory", (PyObject*)&FactoryType); + + Py_INCREF(&DeviceType); + PyModule_AddObject(m, "Device", (PyObject*)&DeviceType); + + Py_INCREF(&HandleType); + PyModule_AddObject(m, "Handle", (PyObject*)&HandleType); + + AUDError = PyErr_NewException("aud.error", NULL, NULL); + Py_INCREF(AUDError); + PyModule_AddObject(m, "error", AUDError); + + // device constants + PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_NULL); + PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_OPENAL); + PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_SDL); + PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_JACK); + //PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_READ); + // format constants + PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT32); + PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT64); + PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_INVALID); + PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S16); + PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S24); + PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S32); + PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_U8); + // status constants + PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_INVALID); + PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PAUSED); + PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PLAYING); + // distance model constants + PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT); + PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT_CLAMPED); + PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE); + PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE_CLAMPED); + PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR); + PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR_CLAMPED); + PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVALID); + + return m; +} diff --git a/intern/audaspace/Python/AUD_PyAPI.h b/intern/audaspace/Python/AUD_PyAPI.h new file mode 100644 index 00000000000..aeeaf94af9d --- /dev/null +++ b/intern/audaspace/Python/AUD_PyAPI.h @@ -0,0 +1,67 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_PYAPI +#define AUD_PYAPI + +#include "Python.h" + +#ifdef __cplusplus +extern "C" { +#include "AUD_IDevice.h" +#else +typedef void AUD_IFactory; +typedef void AUD_IDevice; +typedef void AUD_Handle; +#endif + +typedef struct { + PyObject_HEAD + PyObject* child_list; + AUD_IFactory* factory; +} Factory; + +typedef struct { + PyObject_HEAD + AUD_Handle* handle; + PyObject* device; +} Handle; + +typedef struct { + PyObject_HEAD + AUD_IDevice* device; +} Device; + +PyMODINIT_FUNC +PyInit_aud(void); + +extern PyObject * +Device_empty(); + +#ifdef __cplusplus +} +#endif + +#endif //AUD_PYAPI diff --git a/intern/audaspace/SConscript b/intern/audaspace/SConscript index bbd2442c480..35c457aad4e 100644 --- a/intern/audaspace/SConscript +++ b/intern/audaspace/SConscript @@ -36,6 +36,11 @@ if env['WITH_BF_FFTW3']: incs += ' fftw ' + env['BF_FFTW3_INC'] defs.append('WITH_FFTW3') +if env['WITH_BF_PYTHON']: + sources += env.Glob('Python/*.cpp') + incs += ' Python ' + env['BF_PYTHON_INC'] + defs.append('WITH_PYTHON') + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'): incs += ' ' + env['BF_PTHREADS_INC'] diff --git a/intern/audaspace/SDL/AUD_SDLDevice.cpp b/intern/audaspace/SDL/AUD_SDLDevice.cpp index 1a385af8a0c..c1eb7bdf61e 100644 --- a/intern/audaspace/SDL/AUD_SDLDevice.cpp +++ b/intern/audaspace/SDL/AUD_SDLDevice.cpp @@ -33,6 +33,10 @@ void AUD_SDLDevice::SDL_mix(void *data, Uint8* buffer, int length) device->mix((data_t*)buffer,length/AUD_DEVICE_SAMPLE_SIZE(device->m_specs)); } +static const char* open_error = "AUD_SDLDevice: Device couldn't be opened."; +static const char* format_error = "AUD_SDLDevice: Obtained unsupported sample " + "format."; + AUD_SDLDevice::AUD_SDLDevice(AUD_DeviceSpecs specs, int buffersize) { if(specs.channels == AUD_CHANNELS_INVALID) @@ -57,7 +61,7 @@ AUD_SDLDevice::AUD_SDLDevice(AUD_DeviceSpecs specs, int buffersize) format.userdata = this; if(SDL_OpenAudio(&format, &obtained) != 0) - AUD_THROW(AUD_ERROR_SDL); + AUD_THROW(AUD_ERROR_SDL, open_error); m_specs.rate = (AUD_SampleRate)obtained.freq; m_specs.channels = (AUD_Channels)obtained.channels; @@ -66,7 +70,10 @@ AUD_SDLDevice::AUD_SDLDevice(AUD_DeviceSpecs specs, int buffersize) else if(obtained.format == AUDIO_S16LSB || obtained.format == AUDIO_S16MSB) m_specs.format = AUD_FORMAT_S16; else - AUD_THROW(AUD_ERROR_SDL); + { + SDL_CloseAudio(); + AUD_THROW(AUD_ERROR_SDL, format_error); + } create(); } diff --git a/intern/audaspace/SDL/AUD_SDLDevice.h b/intern/audaspace/SDL/AUD_SDLDevice.h index 4b7de1996e8..af713b27480 100644 --- a/intern/audaspace/SDL/AUD_SDLDevice.h +++ b/intern/audaspace/SDL/AUD_SDLDevice.h @@ -44,6 +44,10 @@ private: */ static void SDL_mix(void *data, Uint8* buffer, int length); + // hide copy constructor and operator= + AUD_SDLDevice(const AUD_SDLDevice&); + AUD_SDLDevice& operator=(const AUD_SDLDevice&); + protected: virtual void playing(bool playing); diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp index caafbd14327..b421bb777e1 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp +++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp @@ -26,28 +26,18 @@ #include "AUD_SRCResampleFactory.h" #include "AUD_SRCResampleReader.h" -AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IReader* reader, - AUD_DeviceSpecs specs) : - AUD_ResampleFactory(reader, specs) {} - AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs) : - AUD_ResampleFactory(factory, specs) {} - -AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_DeviceSpecs specs) : - AUD_ResampleFactory(specs) {} + AUD_ResampleFactory(factory, specs) +{ +} -AUD_IReader* AUD_SRCResampleFactory::createReader() +AUD_IReader* AUD_SRCResampleFactory::createReader() const { AUD_IReader* reader = getReader(); - if(reader != 0) - { - if(reader->getSpecs().rate != m_specs.rate) - { - reader = new AUD_SRCResampleReader(reader, m_specs.specs); - AUD_NEW("reader") - } - } + if(reader->getSpecs().rate != m_specs.rate) + reader = new AUD_SRCResampleReader(reader, m_specs.specs); + return reader; } diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.h b/intern/audaspace/SRC/AUD_SRCResampleFactory.h index 4b16c70169c..4edb0e76181 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleFactory.h +++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.h @@ -34,12 +34,15 @@ */ class AUD_SRCResampleFactory : public AUD_ResampleFactory { +private: + // hide copy constructor and operator= + AUD_SRCResampleFactory(const AUD_SRCResampleFactory&); + AUD_SRCResampleFactory& operator=(const AUD_SRCResampleFactory&); + public: - AUD_SRCResampleFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); - AUD_SRCResampleFactory(AUD_DeviceSpecs specs); - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_SRCRESAMPLEFACTORY diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp index e89857635de..91bf7002a49 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp +++ b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp @@ -24,7 +24,6 @@ */ #include "AUD_SRCResampleReader.h" -#include "AUD_Buffer.h" #include <cmath> #include <cstring> @@ -35,16 +34,18 @@ static long src_callback(void *cb_data, float **data) return ((AUD_SRCResampleReader*)cb_data)->doCallback(data); } +static const char* state_error = "AUD_SRCResampleReader: SRC State couldn't be " + "created."; + AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader, AUD_Specs specs) : - AUD_EffectReader(reader) + AUD_EffectReader(reader), + m_sspecs(reader->getSpecs()), + m_factor(double(specs.rate) / double(m_sspecs.rate)), + m_tspecs(specs), + m_position(0) { - m_sspecs = reader->getSpecs(); - - m_tspecs = specs; m_tspecs.channels = m_sspecs.channels; - m_factor = (double)m_tspecs.rate / (double)m_sspecs.rate; - m_position = 0; int error; m_src = src_callback_new(src_callback, @@ -56,23 +57,18 @@ AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader, if(!m_src) { // XXX printf("%s\n", src_strerror(error)); - delete m_reader; AUD_DELETE("reader") - AUD_THROW(AUD_ERROR_READER); + AUD_THROW(AUD_ERROR_SRC, state_error); } - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } AUD_SRCResampleReader::~AUD_SRCResampleReader() { src_delete(m_src); - - delete m_buffer; AUD_DELETE("buffer") } long AUD_SRCResampleReader::doCallback(float** data) { - int length = m_buffer->getSize() / AUD_SAMPLE_SIZE(m_tspecs); + int length = m_buffer.getSize() / AUD_SAMPLE_SIZE(m_tspecs); sample_t* buffer; m_reader->read(length, buffer); @@ -88,17 +84,17 @@ void AUD_SRCResampleReader::seek(int position) m_position = position; } -int AUD_SRCResampleReader::getLength() +int AUD_SRCResampleReader::getLength() const { return m_reader->getLength() * m_factor; } -int AUD_SRCResampleReader::getPosition() +int AUD_SRCResampleReader::getPosition() const { return m_position; } -AUD_Specs AUD_SRCResampleReader::getSpecs() +AUD_Specs AUD_SRCResampleReader::getSpecs() const { return m_tspecs; } @@ -107,10 +103,10 @@ void AUD_SRCResampleReader::read(int & length, sample_t* & buffer) { int size = length * AUD_SAMPLE_SIZE(m_tspecs); - if(m_buffer->getSize() < size) - m_buffer->resize(size); + if(m_buffer.getSize() < size) + m_buffer.resize(size); - buffer = m_buffer->getBuffer(); + buffer = m_buffer.getBuffer(); length = src_callback_read(m_src, m_factor, length, buffer); diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.h b/intern/audaspace/SRC/AUD_SRCResampleReader.h index e09d1b66f13..5e3dafb359b 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleReader.h +++ b/intern/audaspace/SRC/AUD_SRCResampleReader.h @@ -27,7 +27,7 @@ #define AUD_SRCRESAMPLEREADER #include "AUD_EffectReader.h" -class AUD_Buffer; +#include "AUD_Buffer.h" #include <samplerate.h> @@ -38,14 +38,19 @@ class AUD_SRCResampleReader : public AUD_EffectReader { private: /** + * The sample specification of the source. + */ + const AUD_Specs m_sspecs; + + /** * The resampling factor. */ - double m_factor; + const double m_factor; /** * The sound output buffer. */ - AUD_Buffer *m_buffer; + AUD_Buffer m_buffer; /** * The target specification. @@ -53,11 +58,6 @@ private: AUD_Specs m_tspecs; /** - * The sample specification of the source. - */ - AUD_Specs m_sspecs; - - /** * The src state structure. */ SRC_STATE* m_src; @@ -67,14 +67,17 @@ private: */ int m_position; + // hide copy constructor and operator= + AUD_SRCResampleReader(const AUD_SRCResampleReader&); + AUD_SRCResampleReader& operator=(const AUD_SRCResampleReader&); + public: /** * Creates a resampling reader. * \param reader The reader to mix. * \param specs The target specification. * \exception AUD_Exception Thrown if the source specification cannot be - * mixed to the target specification or if the reader is - * NULL. + * resampled to the target specification. */ AUD_SRCResampleReader(AUD_IReader* reader, AUD_Specs specs); @@ -92,9 +95,9 @@ public: long doCallback(float** data); virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); - virtual AUD_Specs getSpecs(); + virtual int getLength() const; + virtual int getPosition() const; + virtual AUD_Specs getSpecs() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp index 8e71c97baec..cad64d70790 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp @@ -24,45 +24,29 @@ */ // needed for INT64_C +#ifndef __STDC_CONSTANT_MACROS #define __STDC_CONSTANT_MACROS +#endif #include "AUD_FFMPEGFactory.h" #include "AUD_FFMPEGReader.h" #include "AUD_Buffer.h" -AUD_FFMPEGFactory::AUD_FFMPEGFactory(const char* filename) +AUD_FFMPEGFactory::AUD_FFMPEGFactory(std::string filename) : + m_filename(filename) { - if(filename != NULL) - { - m_filename = new char[strlen(filename)+1]; AUD_NEW("string") - strcpy(m_filename, filename); - } - else - m_filename = NULL; } -AUD_FFMPEGFactory::AUD_FFMPEGFactory(unsigned char* buffer, int size) +AUD_FFMPEGFactory::AUD_FFMPEGFactory(const data_t* buffer, int size) : + m_buffer(new AUD_Buffer(size)) { - m_filename = NULL; - m_buffer = AUD_Reference<AUD_Buffer>(new AUD_Buffer(size)); memcpy(m_buffer.get()->getBuffer(), buffer, size); } -AUD_FFMPEGFactory::~AUD_FFMPEGFactory() -{ - if(m_filename) - { - delete[] m_filename; AUD_DELETE("string") - } -} - -AUD_IReader* AUD_FFMPEGFactory::createReader() +AUD_IReader* AUD_FFMPEGFactory::createReader() const { - AUD_IReader* reader; - if(m_filename) - reader = new AUD_FFMPEGReader(m_filename); + if(m_buffer.get()) + return new AUD_FFMPEGReader(m_buffer); else - reader = new AUD_FFMPEGReader(m_buffer); - AUD_NEW("reader") - return reader; + return new AUD_FFMPEGReader(m_filename); } diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h index 22560303a73..43a6ce68ca7 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h @@ -30,6 +30,8 @@ #include "AUD_Reference.h" class AUD_Buffer; +#include <string> + /** * This factory reads a sound file via ffmpeg. * \warning Notice that the needed formats and codecs have to be registered @@ -41,33 +43,32 @@ private: /** * The filename of the sound source file. */ - char* m_filename; + const std::string m_filename; /** * The buffer to read from. */ AUD_Reference<AUD_Buffer> m_buffer; + // hide copy constructor and operator= + AUD_FFMPEGFactory(const AUD_FFMPEGFactory&); + AUD_FFMPEGFactory& operator=(const AUD_FFMPEGFactory&); + public: /** * Creates a new factory. * \param filename The sound file path. */ - AUD_FFMPEGFactory(const char* filename); + AUD_FFMPEGFactory(std::string filename); /** * Creates a new factory. * \param buffer The buffer to read from. * \param size The size of the buffer. */ - AUD_FFMPEGFactory(unsigned char* buffer, int size); - - /** - * Destroys the factory. - */ - ~AUD_FFMPEGFactory(); + AUD_FFMPEGFactory(const data_t* buffer, int size); - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_FFMPEGFACTORY diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp index 313ea52e892..b9d5d304368 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp @@ -24,23 +24,24 @@ */ // needed for INT64_C +#ifndef __STDC_CONSTANT_MACROS #define __STDC_CONSTANT_MACROS +#endif #include "AUD_FFMPEGReader.h" -#include "AUD_Buffer.h" extern "C" { #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> } -int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer) +int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer& buffer) { // save packet parameters uint8_t *audio_pkg_data = packet->data; int audio_pkg_size = packet->size; - int buf_size = buffer->getSize(); + int buf_size = buffer.getSize(); int buf_pos = 0; int read_length, data_size; @@ -51,21 +52,16 @@ int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer) // resize buffer if needed if(buf_size - buf_pos < AVCODEC_MAX_AUDIO_FRAME_SIZE) { - buffer->resize(buf_size + AVCODEC_MAX_AUDIO_FRAME_SIZE, true); + buffer.resize(buf_size + AVCODEC_MAX_AUDIO_FRAME_SIZE, true); buf_size += AVCODEC_MAX_AUDIO_FRAME_SIZE; } // read samples from the packet data_size = buf_size - buf_pos; - /*read_length = avcodec_decode_audio3(m_codecCtx, - (int16_t*)(((data_t*)buffer->getBuffer())+buf_pos), + read_length = avcodec_decode_audio3(m_codecCtx, + (int16_t*)(((data_t*)buffer.getBuffer())+buf_pos), &data_size, - packet);*/ - read_length = avcodec_decode_audio2(m_codecCtx, - (int16_t*)(((data_t*)buffer->getBuffer())+buf_pos), - &data_size, - audio_pkg_data, - audio_pkg_size); + packet); // read error, next packet! if(read_length < 0) @@ -81,36 +77,50 @@ int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer) return buf_pos; } +static const char* streaminfo_error = "AUD_FFMPEGReader: Stream info couldn't " + "be found."; +static const char* noaudio_error = "AUD_FFMPEGReader: File doesn't include an " + "audio stream."; +static const char* nodecoder_error = "AUD_FFMPEGReader: No decoder found for " + "the audio stream."; +static const char* codecopen_error = "AUD_FFMPEGReader: Codec couldn't be " + "opened."; +static const char* format_error = "AUD_FFMPEGReader: Unsupported sample " + "format."; + void AUD_FFMPEGReader::init() { m_position = 0; m_pkgbuf_left = 0; if(av_find_stream_info(m_formatCtx)<0) - AUD_THROW(AUD_ERROR_FFMPEG); + AUD_THROW(AUD_ERROR_FFMPEG, streaminfo_error); // find audio stream and codec m_stream = -1; for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++) + { if((m_formatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) && (m_stream < 0)) { m_stream=i; break; } + } + if(m_stream == -1) - AUD_THROW(AUD_ERROR_FFMPEG); + AUD_THROW(AUD_ERROR_FFMPEG, noaudio_error); m_codecCtx = m_formatCtx->streams[m_stream]->codec; // get a decoder and open it AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id); if(!aCodec) - AUD_THROW(AUD_ERROR_FFMPEG); + AUD_THROW(AUD_ERROR_FFMPEG, nodecoder_error); if(avcodec_open(m_codecCtx, aCodec)<0) - AUD_THROW(AUD_ERROR_FFMPEG); + AUD_THROW(AUD_ERROR_FFMPEG, codecopen_error); // XXX this prints file information to stdout: //dump_format(m_formatCtx, 0, NULL, 0); @@ -140,45 +150,49 @@ void AUD_FFMPEGReader::init() m_specs.format = AUD_FORMAT_FLOAT64; break; default: - AUD_THROW(AUD_ERROR_FILE); + AUD_THROW(AUD_ERROR_FFMPEG, format_error); } m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate; - - // last but not least if there hasn't been any error, create the buffers - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - m_pkgbuf = new AUD_Buffer(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1); - AUD_NEW("buffer") } -AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename) -{ - m_byteiocontext = NULL; +static const char* fileopen_error = "AUD_FFMPEGReader: File couldn't be " + "opened."; +AUD_FFMPEGReader::AUD_FFMPEGReader(std::string filename) : + m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1), + m_byteiocontext(NULL) +{ // open file - if(av_open_input_file(&m_formatCtx, filename, NULL, 0, NULL)!=0) - AUD_THROW(AUD_ERROR_FILE); + if(av_open_input_file(&m_formatCtx, filename.c_str(), NULL, 0, NULL)!=0) + AUD_THROW(AUD_ERROR_FILE, fileopen_error); try { init(); } - catch(AUD_Exception) + catch(AUD_Exception&) { av_close_input_file(m_formatCtx); throw; } } -AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) +static const char* streamopen_error = "AUD_FFMPEGReader: Stream couldn't be " + "opened."; + +AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) : + m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1), + m_membuffer(buffer) { m_byteiocontext = (ByteIOContext*)av_mallocz(sizeof(ByteIOContext)); - AUD_NEW("byteiocontext") - m_membuffer = buffer; if(init_put_byte(m_byteiocontext, (data_t*)buffer.get()->getBuffer(), buffer.get()->getSize(), 0, NULL, NULL, NULL, NULL) != 0) - AUD_THROW(AUD_ERROR_FILE); + { + av_free(m_byteiocontext); + AUD_THROW(AUD_ERROR_FILE, fileopen_error); + } AVProbeData probe_data; probe_data.filename = ""; @@ -188,16 +202,19 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) // open stream if(av_open_input_stream(&m_formatCtx, m_byteiocontext, "", fmt, NULL)!=0) - AUD_THROW(AUD_ERROR_FILE); + { + av_free(m_byteiocontext); + AUD_THROW(AUD_ERROR_FILE, streamopen_error); + } try { init(); } - catch(AUD_Exception) + catch(AUD_Exception&) { av_close_input_stream(m_formatCtx); - av_free(m_byteiocontext); AUD_DELETE("byteiocontext") + av_free(m_byteiocontext); throw; } } @@ -209,16 +226,13 @@ AUD_FFMPEGReader::~AUD_FFMPEGReader() if(m_byteiocontext) { av_close_input_stream(m_formatCtx); - av_free(m_byteiocontext); AUD_DELETE("byteiocontext") + av_free(m_byteiocontext); } else av_close_input_file(m_formatCtx); - - delete m_buffer; AUD_DELETE("buffer") - delete m_pkgbuf; AUD_DELETE("buffer") } -bool AUD_FFMPEGReader::isSeekable() +bool AUD_FFMPEGReader::isSeekable() const { return true; } @@ -260,9 +274,17 @@ void AUD_FFMPEGReader::seek(int position) if(m_position < position) { - sample_t* buf; - int length = position - m_position; - read(length, buf); + // read until we're at the right position + int length = AUD_DEFAULT_BUFFER_SIZE; + sample_t* buffer; + for(int len = position - m_position; + length == AUD_DEFAULT_BUFFER_SIZE; + len -= AUD_DEFAULT_BUFFER_SIZE) + { + if(len < AUD_DEFAULT_BUFFER_SIZE) + length = len; + read(length, buffer); + } } } } @@ -276,33 +298,23 @@ void AUD_FFMPEGReader::seek(int position) } } -int AUD_FFMPEGReader::getLength() +int AUD_FFMPEGReader::getLength() const { // return approximated remaning size return (int)((m_formatCtx->duration * m_codecCtx->sample_rate) / AV_TIME_BASE)-m_position; } -int AUD_FFMPEGReader::getPosition() +int AUD_FFMPEGReader::getPosition() const { return m_position; } -AUD_Specs AUD_FFMPEGReader::getSpecs() +AUD_Specs AUD_FFMPEGReader::getSpecs() const { return m_specs.specs; } -AUD_ReaderType AUD_FFMPEGReader::getType() -{ - return AUD_TYPE_STREAM; -} - -bool AUD_FFMPEGReader::notify(AUD_Message &message) -{ - return false; -} - void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) { // read packages and decode them @@ -313,10 +325,10 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs); // resize output buffer if necessary - if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(m_specs)) - m_buffer->resize(length * AUD_SAMPLE_SIZE(m_specs)); + if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(m_specs)) + m_buffer.resize(length * AUD_SAMPLE_SIZE(m_specs)); - buffer = m_buffer->getBuffer(); + buffer = m_buffer.getBuffer(); pkgbuf_pos = m_pkgbuf_left; m_pkgbuf_left = 0; @@ -324,7 +336,7 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) if(pkgbuf_pos > 0) { data_size = AUD_MIN(pkgbuf_pos, left * sample_size); - m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(), + m_convert((data_t*) buffer, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format)); buffer += data_size / AUD_FORMAT_SIZE(m_specs.format); left -= data_size/sample_size; @@ -341,7 +353,7 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) // copy to output buffer data_size = AUD_MIN(pkgbuf_pos, left * sample_size); - m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(), + m_convert((data_t*) buffer, (data_t*) m_pkgbuf.getBuffer(), data_size / AUD_FORMAT_SIZE(m_specs.format)); buffer += data_size / AUD_FORMAT_SIZE(m_specs.format); left -= data_size/sample_size; @@ -352,12 +364,12 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer) if(pkgbuf_pos > data_size) { m_pkgbuf_left = pkgbuf_pos-data_size; - memmove(m_pkgbuf->getBuffer(), - ((data_t*)m_pkgbuf->getBuffer())+data_size, + memmove(m_pkgbuf.getBuffer(), + ((data_t*)m_pkgbuf.getBuffer())+data_size, pkgbuf_pos-data_size); } - buffer = m_buffer->getBuffer(); + buffer = m_buffer.getBuffer(); if(left > 0) length -= left; diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h index f992fdf7a34..8ebf5b45cdc 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h @@ -29,7 +29,9 @@ #include "AUD_ConverterFunctions.h" #include "AUD_IReader.h" #include "AUD_Reference.h" -class AUD_Buffer; +#include "AUD_Buffer.h" + +#include <string> struct AVCodecContext; extern "C" { @@ -55,7 +57,7 @@ private: /** * The playback buffer. */ - AUD_Buffer *m_buffer; + AUD_Buffer m_buffer; /** * The specification of the audio data. @@ -65,7 +67,7 @@ private: /** * The buffer for package reading. */ - AUD_Buffer *m_pkgbuf; + AUD_Buffer m_pkgbuf; /** * The count of samples still available from the last read package. @@ -108,13 +110,17 @@ private: * \param buffer The target buffer. * \return The count of read bytes. */ - int decode(AVPacket* packet, AUD_Buffer* buffer); + int decode(AVPacket* packet, AUD_Buffer& buffer); /** * Initializes the object. */ void init(); + // hide copy constructor and operator= + AUD_FFMPEGReader(const AUD_FFMPEGReader&); + AUD_FFMPEGReader& operator=(const AUD_FFMPEGReader&); + public: /** * Creates a new reader. @@ -122,7 +128,7 @@ public: * \exception AUD_Exception Thrown if the file specified does not exist or * cannot be read with ffmpeg. */ - AUD_FFMPEGReader(const char* filename); + AUD_FFMPEGReader(std::string filename); /** * Creates a new reader. @@ -137,13 +143,11 @@ public: */ virtual ~AUD_FFMPEGReader(); - virtual bool isSeekable(); + virtual bool isSeekable() const; virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); - virtual AUD_Specs getSpecs(); - virtual AUD_ReaderType getType(); - virtual bool notify(AUD_Message &message); + virtual int getLength() const; + virtual int getPosition() const; + virtual AUD_Specs getSpecs() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/fftw/AUD_BandPassReader.h b/intern/audaspace/fftw/AUD_BandPassReader.h index 7a8fd3b94d5..bb63a3ec818 100644 --- a/intern/audaspace/fftw/AUD_BandPassReader.h +++ b/intern/audaspace/fftw/AUD_BandPassReader.h @@ -83,7 +83,6 @@ public: * \param reader The reader to read from. * \param low The lowest passed frequency. * \param high The highest passed frequency. - * \exception AUD_Exception Thrown if the reader specified is NULL. */ AUD_BandPassReader(AUD_IReader* reader, float low, float high); diff --git a/intern/audaspace/intern/AUD_3DMath.h b/intern/audaspace/intern/AUD_3DMath.h new file mode 100644 index 00000000000..a3405bf4d31 --- /dev/null +++ b/intern/audaspace/intern/AUD_3DMath.h @@ -0,0 +1,189 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#ifndef AUD_3DMATH +#define AUD_3DMATH + +class AUD_Quaternion +{ +private: + union + { + float m_v[4]; + struct + { + const float m_w; + const float m_x; + const float m_y; + const float m_z; + }; + }; + +public: + /** + * Creates a new quaternion. + * \param w The w component. + * \param x The x component. + * \param y The y component. + * \param z The z component. + */ + inline AUD_Quaternion(float w, float x, float y, float z) : + m_w(w), m_x(x), m_y(y), m_z(z) + { + } + + /** + * Retrieves the w component of the quarternion. + * \return The w component. + */ + inline const float& w() const + { + return m_w; + } + + /** + * Retrieves the x component of the quarternion. + * \return The x component. + */ + inline const float& x() const + { + return m_x; + } + + /** + * Retrieves the y component of the quarternion. + * \return The y component. + */ + inline const float& y() const + { + return m_y; + } + + /** + * Retrieves the z component of the quarternion. + * \return The z component. + */ + inline const float& z() const + { + return m_z; + } + + /** + * Retrieves the components of the vector. + * \param destination Where the 4 float values should be saved to. + */ + inline void get(float* destination) const + { + destination[0] = m_w; + destination[1] = m_x; + destination[2] = m_y; + destination[3] = m_z; + } + + /** + * Retrieves the components of the vector. + * \return The components as float[4]. + */ + inline const float* get() const + { + return m_v; + } +}; + +class AUD_Vector3 +{ +private: + union + { + float m_v[3]; + struct + { + const float m_x; + const float m_y; + const float m_z; + }; + }; + +public: + /** + * Creates a new 3 dimensional vector. + * \param x The x component. + * \param y The y component. + * \param z The z component. + */ + inline AUD_Vector3(float x, float y, float z) : + m_x(x), m_y(y), m_z(z) + { + } + + /** + * Retrieves the x component of the vector. + * \return The x component. + */ + inline const float& x() const + { + return m_x; + } + + /** + * Retrieves the y component of the vector. + * \return The y component. + */ + inline const float& y() const + { + return m_y; + } + + /** + * Retrieves the z component of the vector. + * \return The z component. + */ + inline const float& z() const + { + return m_z; + } + + /** + * Retrieves the components of the vector. + * \param destination Where the 3 float values should be saved to. + */ + inline void get(float* destination) const + { + destination[0] = m_x; + destination[1] = m_y; + destination[2] = m_z; + } + + /** + * Retrieves the components of the vector. + * \return The components as float[3]. + */ + inline const float* get() const + { + return m_v; + } +}; + +#endif //AUD_3DMATH diff --git a/intern/audaspace/intern/AUD_Buffer.cpp b/intern/audaspace/intern/AUD_Buffer.cpp index a8e74a023bf..11eed399ca5 100644 --- a/intern/audaspace/intern/AUD_Buffer.cpp +++ b/intern/audaspace/intern/AUD_Buffer.cpp @@ -34,34 +34,37 @@ AUD_Buffer::AUD_Buffer(int size) { m_size = size; - m_buffer = (data_t*) malloc(size+16); AUD_NEW("buffer") + m_buffer = (data_t*) malloc(size+16); } AUD_Buffer::~AUD_Buffer() { - free(m_buffer); AUD_DELETE("buffer") + free(m_buffer); } -sample_t* AUD_Buffer::getBuffer() +sample_t* AUD_Buffer::getBuffer() const { return (sample_t*) AUD_ALIGN(m_buffer); } -int AUD_Buffer::getSize() +int AUD_Buffer::getSize() const { return m_size; } void AUD_Buffer::resize(int size, bool keep) { - data_t* buffer = (data_t*) malloc(size+16); AUD_NEW("buffer") - - // copy old data over if wanted if(keep) + { + data_t* buffer = (data_t*) malloc(size + 16); + memcpy(AUD_ALIGN(buffer), AUD_ALIGN(m_buffer), AUD_MIN(size, m_size)); - free(m_buffer); AUD_DELETE("buffer") + free(m_buffer); + m_buffer = buffer; + } + else + m_buffer = (data_t*) realloc(m_buffer, size + 16); - m_buffer = buffer; m_size = size; } diff --git a/intern/audaspace/intern/AUD_Buffer.h b/intern/audaspace/intern/AUD_Buffer.h index f745ee6154b..b3889b35ffe 100644 --- a/intern/audaspace/intern/AUD_Buffer.h +++ b/intern/audaspace/intern/AUD_Buffer.h @@ -41,6 +41,10 @@ private: /// The pointer to the buffer memory. data_t* m_buffer; + // hide copy constructor and operator= + AUD_Buffer(const AUD_Buffer&); + AUD_Buffer& operator=(const AUD_Buffer&); + public: /** * Creates a new buffer. @@ -56,12 +60,12 @@ public: /** * Returns the pointer to the buffer in memory. */ - sample_t* getBuffer(); + sample_t* getBuffer() const; /** * Returns the size of the buffer in bytes. */ - int getSize(); + int getSize() const; /** * Resizes the buffer. diff --git a/intern/audaspace/intern/AUD_BufferReader.cpp b/intern/audaspace/intern/AUD_BufferReader.cpp index 0101de338bd..d3af549a868 100644 --- a/intern/audaspace/intern/AUD_BufferReader.cpp +++ b/intern/audaspace/intern/AUD_BufferReader.cpp @@ -28,53 +28,36 @@ #include "AUD_Space.h" AUD_BufferReader::AUD_BufferReader(AUD_Reference<AUD_Buffer> buffer, - AUD_Specs specs) + AUD_Specs specs) : + m_position(0), m_buffer(buffer), m_specs(specs) { - m_position = 0; - m_buffer = buffer; - m_specs = specs; } -bool AUD_BufferReader::isSeekable() +bool AUD_BufferReader::isSeekable() const { return true; } void AUD_BufferReader::seek(int position) { - if(position < 0) - m_position = 0; - else if(position > m_buffer.get()->getSize() / AUD_SAMPLE_SIZE(m_specs)) - m_position = m_buffer.get()->getSize() / AUD_SAMPLE_SIZE(m_specs); - else - m_position = position; + m_position = position; } -int AUD_BufferReader::getLength() +int AUD_BufferReader::getLength() const { - return m_buffer.get()->getSize()/AUD_SAMPLE_SIZE(m_specs); + return m_buffer.get()->getSize() / AUD_SAMPLE_SIZE(m_specs); } -int AUD_BufferReader::getPosition() +int AUD_BufferReader::getPosition() const { return m_position; } -AUD_Specs AUD_BufferReader::getSpecs() +AUD_Specs AUD_BufferReader::getSpecs() const { return m_specs; } -AUD_ReaderType AUD_BufferReader::getType() -{ - return AUD_TYPE_BUFFER; -} - -bool AUD_BufferReader::notify(AUD_Message &message) -{ - return false; -} - void AUD_BufferReader::read(int & length, sample_t* & buffer) { int sample_size = AUD_SAMPLE_SIZE(m_specs); diff --git a/intern/audaspace/intern/AUD_BufferReader.h b/intern/audaspace/intern/AUD_BufferReader.h index f2d8ff6b57d..a8bd89060b0 100644 --- a/intern/audaspace/intern/AUD_BufferReader.h +++ b/intern/audaspace/intern/AUD_BufferReader.h @@ -53,6 +53,10 @@ private: */ AUD_Specs m_specs; + // hide copy constructor and operator= + AUD_BufferReader(const AUD_BufferReader&); + AUD_BufferReader& operator=(const AUD_BufferReader&); + public: /** * Creates a new buffer reader. @@ -61,13 +65,11 @@ public: */ AUD_BufferReader(AUD_Reference<AUD_Buffer> buffer, AUD_Specs specs); - virtual bool isSeekable(); + virtual bool isSeekable() const; virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); - virtual AUD_Specs getSpecs(); - virtual AUD_ReaderType getType(); - virtual bool notify(AUD_Message &message); + virtual int getLength() const; + virtual int getPosition() const; + virtual AUD_Specs getSpecs() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp index 8740f62c9a7..40cbbd92d93 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -23,11 +23,18 @@ * ***** END LGPL LICENSE BLOCK ***** */ +#ifdef WITH_PYTHON +#include "AUD_PyAPI.h" + +Device* g_device; +bool g_pyinitialized = false; +#endif + #include <cstdlib> #include <cstring> #include <cmath> -#ifdef WITH_FFMPEG +#ifndef __STDC_CONSTANT_MACROS // needed for INT64_C #define __STDC_CONSTANT_MACROS #endif @@ -51,9 +58,9 @@ #include "AUD_ChannelMapperFactory.h" #include "AUD_Buffer.h" #include "AUD_ReadDevice.h" -#include "AUD_SourceCaps.h" #include "AUD_IReader.h" #include "AUD_SequencerFactory.h" +#include "AUD_SilenceFactory.h" #ifdef WITH_SDL #include "AUD_SDLDevice.h" @@ -78,6 +85,7 @@ extern "C" { typedef AUD_IFactory AUD_Sound; typedef AUD_ReadDevice AUD_Device; +typedef AUD_Handle AUD_Channel; #define AUD_CAPI_IMPLEMENTATION #include "AUD_C-API.h" @@ -123,7 +131,7 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) #endif #ifdef WITH_JACK case AUD_JACK_DEVICE: - dev = new AUD_JackDevice(specs, buffersize); + dev = new AUD_JackDevice("Blender", specs, buffersize); break; #endif default: @@ -131,12 +139,22 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) } AUD_device = dev; - if(AUD_device->checkCapability(AUD_CAPS_3D_DEVICE)) - AUD_3ddevice = dynamic_cast<AUD_I3DDevice*>(AUD_device); + AUD_3ddevice = dynamic_cast<AUD_I3DDevice*>(AUD_device); + +#ifdef WITH_PYTHON + if(g_pyinitialized) + { + g_device = (Device*)Device_empty(); + if(g_device != NULL) + { + g_device->device = dev; + } + } +#endif return true; } - catch(AUD_Exception) + catch(AUD_Exception&) { return false; } @@ -160,13 +178,55 @@ int* AUD_enumDevices() void AUD_exit() { - if(AUD_device) +#ifdef WITH_PYTHON + if(g_device) { + Py_XDECREF(g_device); + g_device = NULL; + } + else +#endif + if(AUD_device) delete AUD_device; - AUD_device = NULL; - AUD_3ddevice = NULL; + AUD_device = NULL; + AUD_3ddevice = NULL; +} + +#ifdef WITH_PYTHON +static PyObject* AUD_getCDevice(PyObject* self) +{ + if(g_device) + { + Py_INCREF(g_device); + return (PyObject*)g_device; + } + Py_RETURN_NONE; +} + +static PyMethodDef meth_getcdevice[] = {{ "device", (PyCFunction)AUD_getCDevice, METH_NOARGS, + "device()\n\n" + "Returns the application's :class:`Device`.\n\n" + ":return: The application's :class:`Device`.\n" + ":rtype: :class:`Device`"}}; + +PyObject* AUD_initPython() +{ + PyObject* module = PyInit_aud(); + PyModule_AddObject(module, "device", (PyObject *)PyCFunction_New(meth_getcdevice, NULL)); + PyDict_SetItemString(PySys_GetObject("modules"), "aud", module); + if(AUD_device) + { + g_device = (Device*)Device_empty(); + if(g_device != NULL) + { + g_device->device = AUD_device; + } } + g_pyinitialized = true; + + return module; } +#endif void AUD_lock() { @@ -223,7 +283,7 @@ AUD_Sound* AUD_bufferSound(AUD_Sound* sound) { return new AUD_StreamBufferFactory(sound); } - catch(AUD_Exception) + catch(AUD_Exception&) { return NULL; } @@ -237,7 +297,7 @@ AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay) { return new AUD_DelayFactory(sound, delay); } - catch(AUD_Exception) + catch(AUD_Exception&) { return NULL; } @@ -251,7 +311,7 @@ AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end) { return new AUD_LimiterFactory(sound, start, end); } - catch(AUD_Exception) + catch(AUD_Exception&) { return NULL; } @@ -265,7 +325,7 @@ AUD_Sound* AUD_pingpongSound(AUD_Sound* sound) { return new AUD_PingPongFactory(sound); } - catch(AUD_Exception) + catch(AUD_Exception&) { return NULL; } @@ -279,26 +339,21 @@ AUD_Sound* AUD_loopSound(AUD_Sound* sound) { return new AUD_LoopFactory(sound); } - catch(AUD_Exception) + catch(AUD_Exception&) { return NULL; } } -int AUD_setLoop(AUD_Handle* handle, int loops, float time) +int AUD_setLoop(AUD_Channel* handle, int loops) { if(handle) { - AUD_Message message; - message.type = AUD_MSG_LOOP; - message.loopcount = loops; - message.time = time; - try { - return AUD_device->sendMessage(handle, message); + return AUD_device->setLoopCount(handle, loops); } - catch(AUD_Exception) + catch(AUD_Exception&) { } } @@ -313,7 +368,7 @@ AUD_Sound* AUD_rectifySound(AUD_Sound* sound) { return new AUD_RectifyFactory(sound); } - catch(AUD_Exception) + catch(AUD_Exception&) { return NULL; } @@ -325,7 +380,7 @@ void AUD_unload(AUD_Sound* sound) delete sound; } -AUD_Handle* AUD_play(AUD_Sound* sound, int keep) +AUD_Channel* AUD_play(AUD_Sound* sound, int keep) { assert(AUD_device); assert(sound); @@ -333,207 +388,321 @@ AUD_Handle* AUD_play(AUD_Sound* sound, int keep) { return AUD_device->play(sound, keep); } - catch(AUD_Exception) + catch(AUD_Exception&) { return NULL; } } -int AUD_pause(AUD_Handle* handle) +int AUD_pause(AUD_Channel* handle) { assert(AUD_device); return AUD_device->pause(handle); } -int AUD_resume(AUD_Handle* handle) +int AUD_resume(AUD_Channel* handle) { assert(AUD_device); return AUD_device->resume(handle); } -int AUD_stop(AUD_Handle* handle) +int AUD_stop(AUD_Channel* handle) { if(AUD_device) return AUD_device->stop(handle); return false; } -int AUD_setKeep(AUD_Handle* handle, int keep) +int AUD_setKeep(AUD_Channel* handle, int keep) { assert(AUD_device); return AUD_device->setKeep(handle, keep); } -int AUD_seek(AUD_Handle* handle, float seekTo) +int AUD_seek(AUD_Channel* handle, float seekTo) { assert(AUD_device); return AUD_device->seek(handle, seekTo); } -float AUD_getPosition(AUD_Handle* handle) +float AUD_getPosition(AUD_Channel* handle) { assert(AUD_device); return AUD_device->getPosition(handle); } -AUD_Status AUD_getStatus(AUD_Handle* handle) +AUD_Status AUD_getStatus(AUD_Channel* handle) { assert(AUD_device); return AUD_device->getStatus(handle); } -AUD_Handle* AUD_play3D(AUD_Sound* sound, int keep) +int AUD_setListenerLocation(const float* location) { assert(AUD_device); - assert(sound); - try + if(AUD_3ddevice) { - if(AUD_3ddevice) - return AUD_3ddevice->play3D(sound, keep); - else - return AUD_device->play(sound, keep); + AUD_Vector3 v(location[0], location[1], location[2]); + AUD_3ddevice->setListenerLocation(v); + return true; } - catch(AUD_Exception) + + return false; +} + +int AUD_setListenerVelocity(const float* velocity) +{ + assert(AUD_device); + + if(AUD_3ddevice) { - return NULL; + AUD_Vector3 v(velocity[0], velocity[1], velocity[2]); + AUD_3ddevice->setListenerVelocity(v); + return true; } + + return false; } -int AUD_updateListener(AUD_3DData* data) +int AUD_setListenerOrientation(const float* orientation) { assert(AUD_device); - assert(data); - try + if(AUD_3ddevice) { - if(AUD_3ddevice) - return AUD_3ddevice->updateListener(*data); + AUD_Quaternion q(orientation[0], orientation[1], orientation[2], orientation[3]); + AUD_3ddevice->setListenerOrientation(q); + return true; } - catch(AUD_Exception) + + return false; +} + +int AUD_setSpeedOfSound(float speed) +{ + assert(AUD_device); + + if(AUD_3ddevice) { + AUD_3ddevice->setSpeedOfSound(speed); + return true; } + return false; } -int AUD_set3DSetting(AUD_3DSetting setting, float value) +int AUD_setDopplerFactor(float factor) { assert(AUD_device); - try + if(AUD_3ddevice) { - if(AUD_3ddevice) - return AUD_3ddevice->setSetting(setting, value); + AUD_3ddevice->setDopplerFactor(factor); + return true; } - catch(AUD_Exception) + + return false; +} + +int AUD_setDistanceModel(AUD_DistanceModel model) +{ + assert(AUD_device); + + if(AUD_3ddevice) { + AUD_3ddevice->setDistanceModel(model); + return true; } + return false; } -float AUD_get3DSetting(AUD_3DSetting setting) +int AUD_setSourceLocation(AUD_Channel* handle, const float* location) { assert(AUD_device); + assert(handle); - try + if(AUD_3ddevice) { - if(AUD_3ddevice) - return AUD_3ddevice->getSetting(setting); + AUD_Vector3 v(location[0], location[1], location[2]); + return AUD_3ddevice->setSourceLocation(handle, v); } - catch(AUD_Exception) + + return false; +} + +int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity) +{ + assert(AUD_device); + assert(handle); + + if(AUD_3ddevice) { + AUD_Vector3 v(velocity[0], velocity[1], velocity[2]); + return AUD_3ddevice->setSourceVelocity(handle, v); } - return 0.0f; + + return false; } -int AUD_update3DSource(AUD_Handle* handle, AUD_3DData* data) +int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation) { - if(handle) + assert(AUD_device); + assert(handle); + + if(AUD_3ddevice) { - assert(AUD_device); - assert(data); + AUD_Quaternion q(orientation[0], orientation[1], orientation[2], orientation[3]); + return AUD_3ddevice->setSourceOrientation(handle, q); + } - try - { - if(AUD_3ddevice) - return AUD_3ddevice->updateSource(handle, *data); - } - catch(AUD_Exception) - { - } + return false; +} + +int AUD_setRelative(AUD_Channel* handle, int relative) +{ + assert(AUD_device); + assert(handle); + + if(AUD_3ddevice) + { + return AUD_3ddevice->setRelative(handle, relative); } + return false; } -int AUD_set3DSourceSetting(AUD_Handle* handle, - AUD_3DSourceSetting setting, float value) +int AUD_setVolumeMaximum(AUD_Channel* handle, float volume) { - if(handle) + assert(AUD_device); + assert(handle); + + if(AUD_3ddevice) { - assert(AUD_device); + return AUD_3ddevice->setVolumeMaximum(handle, volume); + } - try - { - if(AUD_3ddevice) - return AUD_3ddevice->setSourceSetting(handle, setting, value); - } - catch(AUD_Exception) - { - } + return false; +} + +int AUD_setVolumeMinimum(AUD_Channel* handle, float volume) +{ + assert(AUD_device); + assert(handle); + + if(AUD_3ddevice) + { + return AUD_3ddevice->setVolumeMinimum(handle, volume); } + return false; } -float AUD_get3DSourceSetting(AUD_Handle* handle, AUD_3DSourceSetting setting) +int AUD_setDistanceMaximum(AUD_Channel* handle, float distance) { - if(handle) + assert(AUD_device); + assert(handle); + + if(AUD_3ddevice) { - assert(AUD_device); + return AUD_3ddevice->setDistanceMaximum(handle, distance); + } - try - { - if(AUD_3ddevice) - return AUD_3ddevice->getSourceSetting(handle, setting); - } - catch(AUD_Exception) - { - } + return false; +} + +int AUD_setDistanceReference(AUD_Channel* handle, float distance) +{ + assert(AUD_device); + assert(handle); + + if(AUD_3ddevice) + { + return AUD_3ddevice->setDistanceReference(handle, distance); + } + + return false; +} + +int AUD_setAttenuation(AUD_Channel* handle, float factor) +{ + assert(AUD_device); + assert(handle); + + if(AUD_3ddevice) + { + return AUD_3ddevice->setAttenuation(handle, factor); + } + + return false; +} + +int AUD_setConeAngleOuter(AUD_Channel* handle, float angle) +{ + assert(AUD_device); + assert(handle); + + if(AUD_3ddevice) + { + return AUD_3ddevice->setConeAngleOuter(handle, angle); + } + + return false; +} + +int AUD_setConeAngleInner(AUD_Channel* handle, float angle) +{ + assert(AUD_device); + assert(handle); + + if(AUD_3ddevice) + { + return AUD_3ddevice->setConeAngleInner(handle, angle); + } + + return false; +} + +int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume) +{ + assert(AUD_device); + assert(handle); + + if(AUD_3ddevice) + { + return AUD_3ddevice->setConeVolumeOuter(handle, volume); } - return 0.0f; + + return false; } -int AUD_setSoundVolume(AUD_Handle* handle, float volume) +int AUD_setSoundVolume(AUD_Channel* handle, float volume) { if(handle) { assert(AUD_device); - AUD_SourceCaps caps; - caps.handle = handle; - caps.value = volume; try { - return AUD_device->setCapability(AUD_CAPS_SOURCE_VOLUME, &caps); + return AUD_device->setVolume(handle, volume); } - catch(AUD_Exception) {} + catch(AUD_Exception&) {} } return false; } -int AUD_setSoundPitch(AUD_Handle* handle, float pitch) +int AUD_setSoundPitch(AUD_Channel* handle, float pitch) { if(handle) { assert(AUD_device); - AUD_SourceCaps caps; - caps.handle = handle; - caps.value = pitch; try { - return AUD_device->setCapability(AUD_CAPS_SOURCE_PITCH, &caps); + return AUD_device->setPitch(handle, pitch); } - catch(AUD_Exception) {} + catch(AUD_Exception&) {} } return false; } @@ -544,24 +713,24 @@ AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs) { return new AUD_ReadDevice(specs); } - catch(AUD_Exception) + catch(AUD_Exception&) { return NULL; } } -AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek) +AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek) { assert(device); assert(sound); try { - AUD_Handle* handle = device->play(sound); + AUD_Channel* handle = device->play(sound); device->seek(handle, seek); return handle; } - catch(AUD_Exception) + catch(AUD_Exception&) { return NULL; } @@ -573,28 +742,26 @@ int AUD_setDeviceVolume(AUD_Device* device, float volume) try { - return device->setCapability(AUD_CAPS_VOLUME, &volume); + device->setVolume(volume); + return true; } - catch(AUD_Exception) {} + catch(AUD_Exception&) {} return false; } -int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Handle* handle, +int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Channel* handle, float volume) { if(handle) { assert(device); - AUD_SourceCaps caps; - caps.handle = handle; - caps.value = volume; try { - return device->setCapability(AUD_CAPS_SOURCE_VOLUME, &caps); + return device->setVolume(handle, volume); } - catch(AUD_Exception) {} + catch(AUD_Exception&) {} } return false; } @@ -608,7 +775,7 @@ int AUD_readDevice(AUD_Device* device, data_t* buffer, int length) { return device->read(buffer, length); } - catch(AUD_Exception) + catch(AUD_Exception&) { return false; } @@ -622,7 +789,7 @@ void AUD_closeReadDevice(AUD_Device* device) { delete device; } - catch(AUD_Exception) + catch(AUD_Exception&) { } } @@ -679,6 +846,32 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high, return result; } +static void pauseSound(AUD_Channel* handle) +{ + assert(AUD_device); + + AUD_device->pause(handle); +} + +AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds) +{ + assert(AUD_device); + + AUD_SilenceFactory silence; + AUD_LimiterFactory limiter(&silence, 0, seconds); + + try + { + AUD_Channel* channel = AUD_device->play(&limiter); + AUD_device->setStopCallback(channel, (stopCallback)pauseSound, handle); + return channel; + } + catch(AUD_Exception&) + { + return NULL; + } +} + AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume) { /* AUD_XXX should be this: but AUD_createSequencer is called before the device @@ -721,23 +914,16 @@ void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, char mut int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length) { - AUD_IReader* reader = sound->createReader(); AUD_DeviceSpecs specs; sample_t* buf; - specs.specs = reader->getSpecs(); + specs.rate = AUD_RATE_INVALID; specs.channels = AUD_CHANNELS_MONO; - specs.format = AUD_FORMAT_FLOAT32; - - AUD_ChannelMapperFactory mapper(reader, specs); + specs.format = AUD_FORMAT_INVALID; - if(!reader || reader->getType() != AUD_TYPE_BUFFER) - return -1; + AUD_ChannelMapperFactory mapper(sound, specs); - reader = mapper.createReader(); - - if(!reader) - return -1; + AUD_IReader* reader = mapper.createReader(); int len = reader->getLength(); float samplejump = (float)len / (float)length; @@ -766,7 +952,7 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length) } } - delete reader; AUD_DELETE("reader") + delete reader; return length; } @@ -789,7 +975,7 @@ void AUD_stopPlayback() #endif } -void AUD_seekSequencer(AUD_Handle* handle, float time) +void AUD_seekSequencer(AUD_Channel* handle, float time) { #ifdef WITH_JACK AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); @@ -802,7 +988,7 @@ void AUD_seekSequencer(AUD_Handle* handle, float time) } } -float AUD_getSequencerPosition(AUD_Handle* handle) +float AUD_getSequencerPosition(AUD_Channel* handle) { #ifdef WITH_JACK AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); @@ -833,16 +1019,3 @@ int AUD_doesPlayback() #endif return -1; } - -#ifdef AUD_DEBUG_MEMORY -int AUD_References(int count, const char* text) -{ - static int m_count = 0; - m_count += count; - if(count > 0) - printf("+%s\n", text); - if(count < 0) - printf("-%s\n", text); - return m_count; -} -#endif diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h index 55aed02153f..de2d8465d18 100644 --- a/intern/audaspace/intern/AUD_C-API.h +++ b/intern/audaspace/intern/AUD_C-API.h @@ -26,6 +26,10 @@ #ifndef AUD_CAPI #define AUD_CAPI +#ifdef WITH_PYTHON +#include "Python.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -48,7 +52,7 @@ typedef struct #ifndef AUD_CAPI_IMPLEMENTATION typedef void AUD_Sound; - typedef void AUD_Handle; + typedef void AUD_Channel; typedef void AUD_Device; typedef void AUD_SequencerEntry; typedef float (*AUD_volumeFunction)(void*, void*, float); @@ -80,6 +84,13 @@ extern int* AUD_enumDevices(); */ extern void AUD_exit(); +#ifdef WITH_PYTHON +/** + * Initalizes the Python module. + */ +extern PyObject* AUD_initPython(); +#endif + /** * Locks the playback device. */ @@ -154,10 +165,9 @@ extern AUD_Sound* AUD_loopSound(AUD_Sound* sound); * Sets a remaining loop count of a looping sound that currently plays. * \param handle The playback handle. * \param loops The count of remaining loops, -1 for infinity. - * \param time The time after which playback should stop, -1 for infinity. * \return Whether the handle is valid. */ -extern int AUD_setLoop(AUD_Handle* handle, int loops, float time); +extern int AUD_setLoop(AUD_Channel* handle, int loops); /** * Rectifies a sound. @@ -179,28 +189,28 @@ extern void AUD_unload(AUD_Sound* sound); * paused when its end has been reached. * \return A handle to the played back sound. */ -extern AUD_Handle* AUD_play(AUD_Sound* sound, int keep); +extern AUD_Channel* AUD_play(AUD_Sound* sound, int keep); /** * Pauses a played back sound. * \param handle The handle to the sound. * \return Whether the handle has been playing or not. */ -extern int AUD_pause(AUD_Handle* handle); +extern int AUD_pause(AUD_Channel* handle); /** * Resumes a paused sound. * \param handle The handle to the sound. * \return Whether the handle has been paused or not. */ -extern int AUD_resume(AUD_Handle* handle); +extern int AUD_resume(AUD_Channel* handle); /** * Stops a playing or paused sound. * \param handle The handle to the sound. * \return Whether the handle has been valid or not. */ -extern int AUD_stop(AUD_Handle* handle); +extern int AUD_stop(AUD_Channel* handle); /** * Sets the end behaviour of a playing or paused sound. @@ -209,7 +219,7 @@ extern int AUD_stop(AUD_Handle* handle); * paused when its end has been reached. * \return Whether the handle has been valid or not. */ -extern int AUD_setKeep(AUD_Handle* handle, int keep); +extern int AUD_setKeep(AUD_Channel* handle, int keep); /** * Seeks a playing or paused sound. @@ -217,7 +227,7 @@ extern int AUD_setKeep(AUD_Handle* handle, int keep); * \param seekTo From where the sound file should be played back in seconds. * \return Whether the handle has been valid or not. */ -extern int AUD_seek(AUD_Handle* handle, float seekTo); +extern int AUD_seek(AUD_Channel* handle, float seekTo); /** * Retrieves the playback position of a handle. @@ -225,74 +235,155 @@ extern int AUD_seek(AUD_Handle* handle, float seekTo); * \return The current playback position in seconds or 0.0 if the handle is * invalid. */ -extern float AUD_getPosition(AUD_Handle* handle); +extern float AUD_getPosition(AUD_Channel* handle); /** * Returns the status of a playing, paused or stopped sound. * \param handle The handle to the sound. * \return The status of the sound behind the handle. */ -extern AUD_Status AUD_getStatus(AUD_Handle* handle); +extern AUD_Status AUD_getStatus(AUD_Channel* handle); /** - * Plays a 3D sound. - * \param sound The handle of the sound file. - * \param keep When keep is true the sound source will not be deleted but set to - * paused when its end has been reached. - * \return A handle to the played back sound. - * \note The factory must provide a mono (single channel) source and the device - * must support 3D audio, otherwise the sound is played back normally. + * Sets the listener location. + * \param location The new location. + */ +extern int AUD_setListenerLocation(const float* location); + +/** + * Sets the listener velocity. + * \param velocity The new velocity. + */ +extern int AUD_setListenerVelocity(const float* velocity); + +/** + * Sets the listener orientation. + * \param orientation The new orientation as quaternion. + */ +extern int AUD_setListenerOrientation(const float* orientation); + +/** + * Sets the speed of sound. + * This value is needed for doppler effect calculation. + * \param speed The new speed of sound. + */ +extern int AUD_setSpeedOfSound(float speed); + +/** + * Sets the doppler factor. + * This value is a scaling factor for the velocity vectors of sources and + * listener which is used while calculating the doppler effect. + * \param factor The new doppler factor. + */ +extern int AUD_setDopplerFactor(float factor); + +/** + * Sets the distance model. + * \param model distance model. */ -extern AUD_Handle* AUD_play3D(AUD_Sound* sound, int keep); +extern int AUD_setDistanceModel(AUD_DistanceModel model); /** - * Updates the listener 3D data. - * \param data The 3D data. + * Sets the location of a source. + * \param handle The handle of the source. + * \param location The new location. * \return Whether the action succeeded. */ -extern int AUD_updateListener(AUD_3DData* data); +extern int AUD_setSourceLocation(AUD_Channel* handle, const float* location); /** - * Sets a 3D device setting. - * \param setting The setting type. - * \param value The new setting value. + * Sets the velocity of a source. + * \param handle The handle of the source. + * \param velocity The new velocity. * \return Whether the action succeeded. */ -extern int AUD_set3DSetting(AUD_3DSetting setting, float value); +extern int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity); /** - * Retrieves a 3D device setting. - * \param setting The setting type. - * \return The setting value. + * Sets the orientation of a source. + * \param handle The handle of the source. + * \param orientation The new orientation as quaternion. + * \return Whether the action succeeded. */ -extern float AUD_get3DSetting(AUD_3DSetting setting); +extern int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation); /** - * Updates a listeners 3D data. - * \param handle The source handle. - * \param data The 3D data. + * Sets whether the source location, velocity and orientation are relative + * to the listener. + * \param handle The handle of the source. + * \param relative Whether the source is relative. * \return Whether the action succeeded. */ -extern int AUD_update3DSource(AUD_Handle* handle, AUD_3DData* data); +extern int AUD_setRelative(AUD_Channel* handle, int relative); /** - * Sets a 3D source setting. - * \param handle The source handle. - * \param setting The setting type. - * \param value The new setting value. + * Sets the maximum volume of a source. + * \param handle The handle of the source. + * \param volume The new maximum volume. * \return Whether the action succeeded. */ -extern int AUD_set3DSourceSetting(AUD_Handle* handle, - AUD_3DSourceSetting setting, float value); +extern int AUD_setVolumeMaximum(AUD_Channel* handle, float volume); /** - * Retrieves a 3D source setting. - * \param handle The source handle. - * \param setting The setting type. - * \return The setting value. + * Sets the minimum volume of a source. + * \param handle The handle of the source. + * \param volume The new minimum volume. + * \return Whether the action succeeded. */ -extern float AUD_get3DSourceSetting(AUD_Handle* handle, - AUD_3DSourceSetting setting); +extern int AUD_setVolumeMinimum(AUD_Channel* handle, float volume); + +/** + * Sets the maximum distance of a source. + * If a source is further away from the reader than this distance, the + * volume will automatically be set to 0. + * \param handle The handle of the source. + * \param distance The new maximum distance. + * \return Whether the action succeeded. + */ +extern int AUD_setDistanceMaximum(AUD_Channel* handle, float distance); + +/** + * Sets the reference distance of a source. + * \param handle The handle of the source. + * \param distance The new reference distance. + * \return Whether the action succeeded. + */ +extern int AUD_setDistanceReference(AUD_Channel* handle, float distance); + +/** + * Sets the attenuation of a source. + * This value is used for distance calculation. + * \param handle The handle of the source. + * \param factor The new attenuation. + * \return Whether the action succeeded. + */ +extern int AUD_setAttenuation(AUD_Channel* handle, float factor); + +/** + * Sets the outer angle of the cone of a source. + * \param handle The handle of the source. + * \param angle The new outer angle of the cone. + * \return Whether the action succeeded. + */ +extern int AUD_setConeAngleOuter(AUD_Channel* handle, float angle); + +/** + * Sets the inner angle of the cone of a source. + * \param handle The handle of the source. + * \param angle The new inner angle of the cone. + * \return Whether the action succeeded. + */ +extern int AUD_setConeAngleInner(AUD_Channel* handle, float angle); + +/** + * Sets the outer volume of the cone of a source. + * The volume between inner and outer angle is interpolated between inner + * volume and this value. + * \param handle The handle of the source. + * \param volume The new outer volume of the cone. + * \return Whether the action succeeded. + */ +extern int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume); /** * Sets the volume of a played back sound. @@ -300,7 +391,7 @@ extern float AUD_get3DSourceSetting(AUD_Handle* handle, * \param volume The new volume, must be between 0.0 and 1.0. * \return Whether the action succeeded. */ -extern int AUD_setSoundVolume(AUD_Handle* handle, float volume); +extern int AUD_setSoundVolume(AUD_Channel* handle, float volume); /** * Sets the pitch of a played back sound. @@ -308,7 +399,7 @@ extern int AUD_setSoundVolume(AUD_Handle* handle, float volume); * \param pitch The new pitch. * \return Whether the action succeeded. */ -extern int AUD_setSoundPitch(AUD_Handle* handle, float pitch); +extern int AUD_setSoundPitch(AUD_Channel* handle, float pitch); /** * Opens a read device, with which audio data can be read. @@ -332,7 +423,7 @@ extern int AUD_setDeviceVolume(AUD_Device* device, float volume); * \param seek The position where the sound should be seeked to. * \return A handle to the played back sound. */ -extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek); +extern AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek); /** * Sets the volume of a played back sound of a read device. @@ -342,7 +433,7 @@ extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float se * \return Whether the action succeeded. */ extern int AUD_setDeviceSoundVolume(AUD_Device* device, - AUD_Handle* handle, + AUD_Channel* handle, float volume); /** @@ -372,6 +463,14 @@ extern float* AUD_readSoundBuffer(const char* filename, float low, float high, float sthreshold, int samplerate, int* length); +/** + * Pauses a playing sound after a specific amount of time. + * \param handle The handle to the sound. + * \param time The time in seconds. + * \return The silence handle. + */ +extern AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds); + extern AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume); extern void AUD_destroySequencer(AUD_Sound* sequencer); @@ -393,9 +492,9 @@ extern void AUD_startPlayback(); extern void AUD_stopPlayback(); -extern void AUD_seekSequencer(AUD_Handle* handle, float time); +extern void AUD_seekSequencer(AUD_Channel* handle, float time); -extern float AUD_getSequencerPosition(AUD_Handle* handle); +extern float AUD_getSequencerPosition(AUD_Channel* handle); #ifdef WITH_JACK extern void AUD_setSyncCallback(AUD_syncFunction function, void* data); diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp index 3420ed16649..b3d5434b1e3 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp @@ -28,13 +28,6 @@ #include <cstring> -AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IReader* reader, - AUD_DeviceSpecs specs) : - AUD_MixerFactory(reader, specs) -{ - memset(m_mapping, 0, sizeof(m_mapping)); -} - AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs) : AUD_MixerFactory(factory, specs) @@ -42,12 +35,6 @@ AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IFactory* factory, memset(m_mapping, 0, sizeof(m_mapping)); } -AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_DeviceSpecs specs) : - AUD_MixerFactory(specs) -{ - memset(m_mapping, 0, sizeof(m_mapping)); -} - AUD_ChannelMapperFactory::~AUD_ChannelMapperFactory() { for(int i = 1; i < 10; i++) @@ -72,12 +59,12 @@ float** AUD_ChannelMapperFactory::getMapping(int ic) { int channels = m_specs.channels; - m_mapping[ic] = new float*[channels+1]; AUD_NEW("mapping") + m_mapping[ic] = new float*[channels+1]; m_mapping[ic][channels] = 0; for(int i = 0; i < channels; i++) { - m_mapping[ic][i] = new float[ic+1]; AUD_NEW("mapping") + m_mapping[ic][i] = new float[ic+1]; for(int j = 0; j <= ic; j++) m_mapping[ic][i][j] = ((i == j) || (channels == 1) || (ic == 0)) ? 1.0f : 0.0f; @@ -99,27 +86,21 @@ void AUD_ChannelMapperFactory::deleteMapping(int ic) { if(m_mapping[ic][i] != 0) { - delete[] m_mapping[ic][i]; AUD_DELETE("mapping") + delete[] m_mapping[ic][i]; } else break; } - delete[] m_mapping[ic]; AUD_DELETE("mapping") + delete[] m_mapping[ic]; m_mapping[ic] = 0; } } -AUD_IReader* AUD_ChannelMapperFactory::createReader() +AUD_IReader* AUD_ChannelMapperFactory::createReader() const { AUD_IReader* reader = getReader(); + int ic = reader->getSpecs().channels; - if(reader != 0) - { - int ic = reader->getSpecs().channels; - - reader = new AUD_ChannelMapperReader(reader, getMapping(ic)); - AUD_NEW("reader") - } - - return reader; + return new AUD_ChannelMapperReader(reader, + const_cast<AUD_ChannelMapperFactory*>(this)->getMapping(ic)); } diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.h b/intern/audaspace/intern/AUD_ChannelMapperFactory.h index a67bfa12123..2f315874421 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.h +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.h @@ -40,10 +40,12 @@ private: */ float **m_mapping[9]; + // hide copy constructor and operator= + AUD_ChannelMapperFactory(const AUD_ChannelMapperFactory&); + AUD_ChannelMapperFactory& operator=(const AUD_ChannelMapperFactory&); + public: - AUD_ChannelMapperFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); AUD_ChannelMapperFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); - AUD_ChannelMapperFactory(AUD_DeviceSpecs specs); virtual ~AUD_ChannelMapperFactory(); @@ -59,7 +61,7 @@ public: */ void deleteMapping(int ic); - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_CHANNELMAPPERFACTORY diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp index d78278219e8..71b9f35b3a4 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp @@ -24,7 +24,6 @@ */ #include "AUD_ChannelMapperReader.h" -#include "AUD_Buffer.h" AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader, float **mapping) : @@ -36,7 +35,7 @@ AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader, m_rch = m_specs.channels; while(mapping[++channels] != 0); - m_mapping = new float*[channels]; AUD_NEW("mapping") + m_mapping = new float*[channels]; m_specs.channels = (AUD_Channels)channels; float sum; @@ -44,7 +43,7 @@ AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader, while(channels--) { - m_mapping[channels] = new float[m_rch]; AUD_NEW("mapping") + m_mapping[channels] = new float[m_rch]; sum = 0.0f; for(i=0; i < m_rch; i++) sum += mapping[channels][i]; @@ -52,8 +51,6 @@ AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader, m_mapping[channels][i] = sum > 0.0f ? mapping[channels][i]/sum : 0.0f; } - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } AUD_ChannelMapperReader::~AUD_ChannelMapperReader() @@ -62,42 +59,37 @@ AUD_ChannelMapperReader::~AUD_ChannelMapperReader() while(channels--) { - delete[] m_mapping[channels]; AUD_DELETE("mapping") + delete[] m_mapping[channels]; } - delete[] m_mapping; AUD_DELETE("mapping") - - delete m_buffer; AUD_DELETE("buffer") + delete[] m_mapping; } -AUD_Specs AUD_ChannelMapperReader::getSpecs() +AUD_Specs AUD_ChannelMapperReader::getSpecs() const { return m_specs; } void AUD_ChannelMapperReader::read(int & length, sample_t* & buffer) { - m_reader->read(length, buffer); + sample_t* in = buffer; - int channels = m_specs.channels; + m_reader->read(length, in); - if(m_buffer->getSize() < length * 4 * channels) - m_buffer->resize(length * 4 * channels); + if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(m_specs)) + m_buffer.resize(length * AUD_SAMPLE_SIZE(m_specs)); - sample_t* in = buffer; - sample_t* out = m_buffer->getBuffer(); + buffer = m_buffer.getBuffer(); sample_t sum; for(int i = 0; i < length; i++) { - for(int j = 0; j < channels; j++) + for(int j = 0; j < m_specs.channels; j++) { sum = 0; for(int k = 0; k < m_rch; k++) sum += m_mapping[j][k] * in[i * m_rch + k]; - out[i * channels + j] = sum; + buffer[i * m_specs.channels + j] = sum; } } - - buffer = m_buffer->getBuffer(); } diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.h b/intern/audaspace/intern/AUD_ChannelMapperReader.h index fe79ab6edd6..398e14da55d 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperReader.h +++ b/intern/audaspace/intern/AUD_ChannelMapperReader.h @@ -27,7 +27,7 @@ #define AUD_CHANNELMAPPERREADER #include "AUD_EffectReader.h" -class AUD_Buffer; +#include "AUD_Buffer.h" /** * This class maps a sound source's channels to a specific output channel count. @@ -39,7 +39,7 @@ private: /** * The sound output buffer. */ - AUD_Buffer *m_buffer; + AUD_Buffer m_buffer; /** * The output specification. @@ -56,20 +56,24 @@ private: */ float **m_mapping; + // hide copy constructor and operator= + AUD_ChannelMapperReader(const AUD_ChannelMapperReader&); + AUD_ChannelMapperReader& operator=(const AUD_ChannelMapperReader&); + public: /** * Creates a channel mapper reader. * \param reader The reader to map. * \param mapping The mapping specification as two dimensional float array. - * \exception AUD_Exception Thrown if the reader is NULL. */ AUD_ChannelMapperReader(AUD_IReader* reader, float **mapping); + /** * Destroys the reader. */ ~AUD_ChannelMapperReader(); - virtual AUD_Specs getSpecs(); + virtual AUD_Specs getSpecs() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/intern/AUD_ConverterFactory.cpp b/intern/audaspace/intern/AUD_ConverterFactory.cpp index 1c6d5468251..057d97fe794 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.cpp +++ b/intern/audaspace/intern/AUD_ConverterFactory.cpp @@ -26,29 +26,18 @@ #include "AUD_ConverterFactory.h" #include "AUD_ConverterReader.h" -AUD_ConverterFactory::AUD_ConverterFactory(AUD_IReader* reader, - AUD_DeviceSpecs specs) : - AUD_MixerFactory(reader, specs) {} - AUD_ConverterFactory::AUD_ConverterFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs) : - AUD_MixerFactory(factory, specs) {} - -AUD_ConverterFactory::AUD_ConverterFactory(AUD_DeviceSpecs specs) : - AUD_MixerFactory(specs) {} + AUD_MixerFactory(factory, specs) +{ +} -AUD_IReader* AUD_ConverterFactory::createReader() +AUD_IReader* AUD_ConverterFactory::createReader() const { AUD_IReader* reader = getReader(); - if(reader != 0) - { - if(m_specs.format != AUD_FORMAT_FLOAT32) - { - reader = new AUD_ConverterReader(reader, m_specs); - AUD_NEW("reader") - } - } + if(m_specs.format != AUD_FORMAT_FLOAT32) + reader = new AUD_ConverterReader(reader, m_specs); return reader; } diff --git a/intern/audaspace/intern/AUD_ConverterFactory.h b/intern/audaspace/intern/AUD_ConverterFactory.h index 11ca6c9f0a8..3535616a4a6 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.h +++ b/intern/audaspace/intern/AUD_ConverterFactory.h @@ -34,12 +34,15 @@ */ class AUD_ConverterFactory : public AUD_MixerFactory { +private: + // hide copy constructor and operator= + AUD_ConverterFactory(const AUD_ConverterFactory&); + AUD_ConverterFactory& operator=(const AUD_ConverterFactory&); + public: - AUD_ConverterFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); AUD_ConverterFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); - AUD_ConverterFactory(AUD_DeviceSpecs specs); - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_CONVERTERFACTORY diff --git a/intern/audaspace/intern/AUD_ConverterReader.cpp b/intern/audaspace/intern/AUD_ConverterReader.cpp index 808144085bb..379a7c85851 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.cpp +++ b/intern/audaspace/intern/AUD_ConverterReader.cpp @@ -24,7 +24,6 @@ */ #include "AUD_ConverterReader.h" -#include "AUD_Buffer.h" AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader, AUD_DeviceSpecs specs) : @@ -63,16 +62,9 @@ AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader, } m_specs.format = specs.format; - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") -} - -AUD_ConverterReader::~AUD_ConverterReader() -{ - delete m_buffer; AUD_DELETE("buffer") } -AUD_Specs AUD_ConverterReader::getSpecs() +AUD_Specs AUD_ConverterReader::getSpecs() const { return m_specs.specs; } @@ -83,11 +75,11 @@ void AUD_ConverterReader::read(int & length, sample_t* & buffer) int samplesize = AUD_SAMPLE_SIZE(m_specs); - if(m_buffer->getSize() < length*samplesize) - m_buffer->resize(length*samplesize); + if(m_buffer.getSize() < length * samplesize) + m_buffer.resize(length * samplesize); - m_convert((data_t*)m_buffer->getBuffer(), (data_t*)buffer, + m_convert((data_t*)m_buffer.getBuffer(), (data_t*)buffer, length * m_specs.channels); - buffer = m_buffer->getBuffer(); + buffer = m_buffer.getBuffer(); } diff --git a/intern/audaspace/intern/AUD_ConverterReader.h b/intern/audaspace/intern/AUD_ConverterReader.h index ba49bbfd9ba..64a46fd63e6 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.h +++ b/intern/audaspace/intern/AUD_ConverterReader.h @@ -28,7 +28,7 @@ #include "AUD_EffectReader.h" #include "AUD_ConverterFunctions.h" -class AUD_Buffer; +#include "AUD_Buffer.h" /** * This class converts a sound source from one to another format. @@ -39,7 +39,7 @@ private: /** * The sound output buffer. */ - AUD_Buffer *m_buffer; + AUD_Buffer m_buffer; /** * The target specification. @@ -51,20 +51,19 @@ private: */ AUD_convert_f m_convert; + // hide copy constructor and operator= + AUD_ConverterReader(const AUD_ConverterReader&); + AUD_ConverterReader& operator=(const AUD_ConverterReader&); + public: /** * Creates a converter reader. * \param reader The reader to convert. * \param specs The target specification. - * \exception AUD_Exception Thrown if the reader is NULL. */ AUD_ConverterReader(AUD_IReader* reader, AUD_DeviceSpecs specs); - /** - * Destroys the reader. - */ - ~AUD_ConverterReader(); - virtual AUD_Specs getSpecs(); + virtual AUD_Specs getSpecs() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/intern/AUD_DefaultMixer.cpp b/intern/audaspace/intern/AUD_DefaultMixer.cpp new file mode 100644 index 00000000000..12faa10d866 --- /dev/null +++ b/intern/audaspace/intern/AUD_DefaultMixer.cpp @@ -0,0 +1,63 @@ +/* + * $Id$ + * + * ***** BEGIN LGPL LICENSE BLOCK ***** + * + * Copyright 2009 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 Lesser General Public License as published by + * the Free Software Foundation, either version 3 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>. + * + * ***** END LGPL LICENSE BLOCK ***** + */ + +#include "AUD_DefaultMixer.h" +#include "AUD_SRCResampleReader.h" +#include "AUD_ChannelMapperReader.h" +#include "AUD_ChannelMapperFactory.h" + +#include <cstring> + +AUD_DefaultMixer::AUD_DefaultMixer(AUD_DeviceSpecs specs) : + AUD_Mixer(specs) +{ +} + +AUD_IReader* AUD_DefaultMixer::prepare(AUD_IReader* reader) +{ + // hacky for now, until a better channel mapper reader is available + AUD_ChannelMapperFactory cmf(NULL, m_specs); + + AUD_Specs specs = reader->getSpecs(); + + // if channel count is lower in output, rechannel before resampling + if(specs.channels < m_specs.channels) + { + reader = new AUD_ChannelMapperReader(reader, + cmf.getMapping(specs.channels)); + specs.channels = m_specs.channels; + } + + // resample + if(specs.rate != m_specs.rate) + reader = new AUD_SRCResampleReader(reader, m_specs.specs); + + // rechannel + if(specs.channels != m_specs.channels) + reader = new AUD_ChannelMapperReader(reader, + cmf.getMapping(specs.channels)); + + return reader; +} diff --git a/intern/audaspace/FX/AUD_SumReader.h b/intern/audaspace/intern/AUD_DefaultMixer.h index 76ccf2f863a..c2f69629c88 100644 --- a/intern/audaspace/FX/AUD_SumReader.h +++ b/intern/audaspace/intern/AUD_DefaultMixer.h @@ -23,42 +23,31 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#ifndef AUD_SUMREADER -#define AUD_SUMREADER +#ifndef AUD_DEFAULTMIXER +#define AUD_DEFAULTMIXER -#include "AUD_EffectReader.h" -class AUD_Buffer; +#include "AUD_Mixer.h" /** - * This class represents an summer. + * This class is able to mix audiosignals of different channel count and sample + * rate and convert it to a specific output format. + * It uses a default ChannelMapperFactory and a SRCResampleFactory for + * the perparation. */ -class AUD_SumReader : public AUD_EffectReader +class AUD_DefaultMixer : public AUD_Mixer { -private: - /** - * The playback buffer. - */ - AUD_Buffer *m_buffer; - - /** - * The sums of the specific channels. - */ - AUD_Buffer *m_sums; - public: /** - * Creates a new sum reader. - * \param reader The reader to read from. - * \exception AUD_Exception Thrown if the reader specified is NULL. + * Creates the mixer. */ - AUD_SumReader(AUD_IReader* reader); + AUD_DefaultMixer(AUD_DeviceSpecs specs); /** - * Destroys the reader. + * This funuction prepares a reader for playback. + * \param reader The reader to prepare. + * \return The reader that should be used for playback. */ - virtual ~AUD_SumReader(); - - virtual void read(int & length, sample_t* & buffer); + virtual AUD_IReader* prepare(AUD_IReader* reader); }; -#endif //AUD_SUMREADER +#endif //AUD_DEFAULTMIXER diff --git a/intern/audaspace/intern/AUD_FileFactory.cpp b/intern/audaspace/intern/AUD_FileFactory.cpp index 5888479a0ba..7ee34b2dc5a 100644 --- a/intern/audaspace/intern/AUD_FileFactory.cpp +++ b/intern/audaspace/intern/AUD_FileFactory.cpp @@ -30,7 +30,9 @@ #ifdef WITH_FFMPEG // needed for INT64_C +#ifndef __STDC_CONSTANT_MACROS #define __STDC_CONSTANT_MACROS +#endif #include "AUD_FFMPEGReader.h" #endif @@ -38,61 +40,42 @@ #include "AUD_SndFileReader.h" #endif -AUD_FileFactory::AUD_FileFactory(const char* filename) +AUD_FileFactory::AUD_FileFactory(std::string filename) : + m_filename(filename) { - if(filename != NULL) - { - m_filename = new char[strlen(filename)+1]; AUD_NEW("string") - strcpy(m_filename, filename); - } - else - m_filename = NULL; } -AUD_FileFactory::AUD_FileFactory(unsigned char* buffer, int size) +AUD_FileFactory::AUD_FileFactory(const data_t* buffer, int size) : + m_buffer(new AUD_Buffer(size)) { - m_filename = NULL; - m_buffer = AUD_Reference<AUD_Buffer>(new AUD_Buffer(size)); memcpy(m_buffer.get()->getBuffer(), buffer, size); } -AUD_FileFactory::~AUD_FileFactory() -{ - if(m_filename) - { - delete[] m_filename; AUD_DELETE("string") - } -} +static const char* read_error = "AUD_FileFactory: File couldn't be read."; -AUD_IReader* AUD_FileFactory::createReader() +AUD_IReader* AUD_FileFactory::createReader() const { - AUD_IReader* reader = 0; - #ifdef WITH_SNDFILE try { - if(m_filename) - reader = new AUD_SndFileReader(m_filename); + if(m_buffer.get()) + return new AUD_SndFileReader(m_buffer); else - reader = new AUD_SndFileReader(m_buffer); - AUD_NEW("reader") - return reader; + return new AUD_SndFileReader(m_filename); } - catch(AUD_Exception e) {} + catch(AUD_Exception&) {} #endif #ifdef WITH_FFMPEG try { - if(m_filename) - reader = new AUD_FFMPEGReader(m_filename); + if(m_buffer.get()) + return new AUD_FFMPEGReader(m_buffer); else - reader = new AUD_FFMPEGReader(m_buffer); - AUD_NEW("reader") - return reader; + return new AUD_FFMPEGReader(m_filename); } - catch(AUD_Exception e) {} + catch(AUD_Exception&) {} #endif - return reader; + AUD_THROW(AUD_ERROR_FILE, read_error); } diff --git a/intern/audaspace/intern/AUD_FileFactory.h b/intern/audaspace/intern/AUD_FileFactory.h index 6ab8f280534..9182667d72e 100644 --- a/intern/audaspace/intern/AUD_FileFactory.h +++ b/intern/audaspace/intern/AUD_FileFactory.h @@ -30,6 +30,8 @@ #include "AUD_Reference.h" class AUD_Buffer; +#include <string> + /** * This factory tries to read a sound file via all available file readers. */ @@ -39,33 +41,32 @@ private: /** * The filename of the sound source file. */ - char* m_filename; + std::string m_filename; /** * The buffer to read from. */ AUD_Reference<AUD_Buffer> m_buffer; + // hide copy constructor and operator= + AUD_FileFactory(const AUD_FileFactory&); + AUD_FileFactory& operator=(const AUD_FileFactory&); + public: /** * Creates a new factory. * \param filename The sound file path. */ - AUD_FileFactory(const char* filename); + AUD_FileFactory(std::string filename); /** * Creates a new factory. * \param buffer The buffer to read from. * \param size The size of the buffer. */ - AUD_FileFactory(unsigned char* buffer, int size); - - /** - * Destroys the factory. - */ - ~AUD_FileFactory(); + AUD_FileFactory(const data_t* buffer, int size); - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_FILEFACTORY diff --git a/intern/audaspace/intern/AUD_I3DDevice.h b/intern/audaspace/intern/AUD_I3DDevice.h index c36924160de..629b0997d4d 100644 --- a/intern/audaspace/intern/AUD_I3DDevice.h +++ b/intern/audaspace/intern/AUD_I3DDevice.h @@ -27,77 +27,288 @@ #define AUD_I3DDEVICE #include "AUD_Space.h" +#include "AUD_3DMath.h" + +struct AUD_Handle; /** * This class represents an output device for 3D sound. - * Whether a normal device supports this or not can be checked with the - * AUD_CAPS_3D_DEVICE capability. */ class AUD_I3DDevice { public: /** - * Plays a 3D sound source. - * \param factory The factory to create the reader for the sound source. - * \param keep When keep is true the sound source will not be deleted but - * set to paused when its end has been reached. - * \return Returns a handle with which the playback can be controlled. - * This is NULL if the sound couldn't be played back. - * \exception AUD_Exception Thrown if there's an unexpected (from the - * device side) error during creation of the reader. - * \note The factory must provide a mono (single channel) source otherwise - * the sound is played back normally. + * Retrieves the listener location. + * \return The listener location. + */ + virtual AUD_Vector3 getListenerLocation() const=0; + + /** + * Sets the listener location. + * \param location The new location. + */ + virtual void setListenerLocation(const AUD_Vector3& location)=0; + + /** + * Retrieves the listener velocity. + * \return The listener velocity. + */ + virtual AUD_Vector3 getListenerVelocity() const=0; + + /** + * Sets the listener velocity. + * \param velocity The new velocity. + */ + virtual void setListenerVelocity(const AUD_Vector3& velocity)=0; + + /** + * Retrieves the listener orientation. + * \return The listener orientation as quaternion. + */ + virtual AUD_Quaternion getListenerOrientation() const=0; + + /** + * Sets the listener orientation. + * \param orientation The new orientation as quaternion. + */ + virtual void setListenerOrientation(const AUD_Quaternion& orientation)=0; + + + /** + * Retrieves the speed of sound. + * This value is needed for doppler effect calculation. + * \return The speed of sound. + */ + virtual float getSpeedOfSound() const=0; + + /** + * Sets the speed of sound. + * This value is needed for doppler effect calculation. + * \param speed The new speed of sound. + */ + virtual void setSpeedOfSound(float speed)=0; + + /** + * Retrieves the doppler factor. + * This value is a scaling factor for the velocity vectors of sources and + * listener which is used while calculating the doppler effect. + * \return The doppler factor. + */ + virtual float getDopplerFactor() const=0; + + /** + * Sets the doppler factor. + * This value is a scaling factor for the velocity vectors of sources and + * listener which is used while calculating the doppler effect. + * \param factor The new doppler factor. + */ + virtual void setDopplerFactor(float factor)=0; + + /** + * Retrieves the distance model. + * \return The distance model. + */ + virtual AUD_DistanceModel getDistanceModel() const=0; + + /** + * Sets the distance model. + * \param model distance model. + */ + virtual void setDistanceModel(AUD_DistanceModel model)=0; + + + + /** + * Retrieves the location of a source. + * \param handle The handle of the source. + * \return The location. + */ + virtual AUD_Vector3 getSourceLocation(AUD_Handle* handle)=0; + + /** + * Sets the location of a source. + * \param handle The handle of the source. + * \param location The new location. + * \return Whether the action succeeded. + */ + virtual bool setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location)=0; + + /** + * Retrieves the velocity of a source. + * \param handle The handle of the source. + * \return The velocity. + */ + virtual AUD_Vector3 getSourceVelocity(AUD_Handle* handle)=0; + + /** + * Sets the velocity of a source. + * \param handle The handle of the source. + * \param velocity The new velocity. + * \return Whether the action succeeded. + */ + virtual bool setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity)=0; + + /** + * Retrieves the orientation of a source. + * \param handle The handle of the source. + * \return The orientation as quaternion. + */ + virtual AUD_Quaternion getSourceOrientation(AUD_Handle* handle)=0; + + /** + * Sets the orientation of a source. + * \param handle The handle of the source. + * \param orientation The new orientation as quaternion. + * \return Whether the action succeeded. + */ + virtual bool setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation)=0; + + + /** + * Checks whether the source location, velocity and orientation are relative + * to the listener. + * \param handle The handle of the source. + * \return Whether the source is relative. + */ + virtual bool isRelative(AUD_Handle* handle)=0; + + /** + * Sets whether the source location, velocity and orientation are relative + * to the listener. + * \param handle The handle of the source. + * \param relative Whether the source is relative. + * \return Whether the action succeeded. + */ + virtual bool setRelative(AUD_Handle* handle, bool relative)=0; + + /** + * Retrieves the maximum volume of a source. + * \param handle The handle of the source. + * \return The maximum volume. + */ + virtual float getVolumeMaximum(AUD_Handle* handle)=0; + + /** + * Sets the maximum volume of a source. + * \param handle The handle of the source. + * \param volume The new maximum volume. + * \return Whether the action succeeded. + */ + virtual bool setVolumeMaximum(AUD_Handle* handle, float volume)=0; + + /** + * Retrieves the minimum volume of a source. + * \param handle The handle of the source. + * \return The minimum volume. */ - virtual AUD_Handle* play3D(AUD_IFactory* factory, bool keep = false)=0; + virtual float getVolumeMinimum(AUD_Handle* handle)=0; /** - * Updates a listeners 3D data. - * \param data The 3D data. + * Sets the minimum volume of a source. + * \param handle The handle of the source. + * \param volume The new minimum volume. * \return Whether the action succeeded. */ - virtual bool updateListener(AUD_3DData &data)=0; + virtual bool setVolumeMinimum(AUD_Handle* handle, float volume)=0; + + /** + * Retrieves the maximum distance of a source. + * If a source is further away from the reader than this distance, the + * volume will automatically be set to 0. + * \param handle The handle of the source. + * \return The maximum distance. + */ + virtual float getDistanceMaximum(AUD_Handle* handle)=0; /** - * Sets a 3D device setting. - * \param setting The setting type. - * \param value The new setting value. + * Sets the maximum distance of a source. + * If a source is further away from the reader than this distance, the + * volume will automatically be set to 0. + * \param handle The handle of the source. + * \param distance The new maximum distance. * \return Whether the action succeeded. */ - virtual bool setSetting(AUD_3DSetting setting, float value)=0; + virtual bool setDistanceMaximum(AUD_Handle* handle, float distance)=0; /** - * Retrieves a 3D device setting. - * \param setting The setting type. - * \return The setting value. + * Retrieves the reference distance of a source. + * \param handle The handle of the source. + * \return The reference distance. */ - virtual float getSetting(AUD_3DSetting setting)=0; + virtual float getDistanceReference(AUD_Handle* handle)=0; /** - * Updates a listeners 3D data. - * \param handle The source handle. - * \param data The 3D data. + * Sets the reference distance of a source. + * \param handle The handle of the source. + * \param distance The new reference distance. * \return Whether the action succeeded. */ - virtual bool updateSource(AUD_Handle* handle, AUD_3DData &data)=0; + virtual bool setDistanceReference(AUD_Handle* handle, float distance)=0; + + /** + * Retrieves the attenuation of a source. + * \param handle The handle of the source. + * \return The attenuation. + */ + virtual float getAttenuation(AUD_Handle* handle)=0; /** - * Sets a 3D source setting. - * \param handle The source handle. - * \param setting The setting type. - * \param value The new setting value. + * Sets the attenuation of a source. + * This value is used for distance calculation. + * \param handle The handle of the source. + * \param factor The new attenuation. * \return Whether the action succeeded. */ - virtual bool setSourceSetting(AUD_Handle* handle, - AUD_3DSourceSetting setting, float value)=0; + virtual bool setAttenuation(AUD_Handle* handle, float factor)=0; /** - * Retrieves a 3D source setting. - * \param handle The source handle. - * \param setting The setting type. - * \return The setting value. + * Retrieves the outer angle of the cone of a source. + * \param handle The handle of the source. + * \return The outer angle of the cone. + */ + virtual float getConeAngleOuter(AUD_Handle* handle)=0; + + /** + * Sets the outer angle of the cone of a source. + * \param handle The handle of the source. + * \param angle The new outer angle of the cone. + * \return Whether the action succeeded. + */ + virtual bool setConeAngleOuter(AUD_Handle* handle, float angle)=0; + + /** + * Retrieves the inner angle of the cone of a source. + * \param handle The handle of the source. + * \return The inner angle of the cone. + */ + virtual float getConeAngleInner(AUD_Handle* handle)=0; + + /** + * Sets the inner angle of the cone of a source. + * \param handle The handle of the source. + * \param angle The new inner angle of the cone. + * \return Whether the action succeeded. + */ + virtual bool setConeAngleInner(AUD_Handle* handle, float angle)=0; + + /** + * Retrieves the outer volume of the cone of a source. + * The volume between inner and outer angle is interpolated between inner + * volume and this value. + * \param handle The handle of the source. + * \return The outer volume of the cone. + */ + virtual float getConeVolumeOuter(AUD_Handle* handle)=0; + + /** + * Sets the outer volume of the cone of a source. + * The volume between inner and outer angle is interpolated between inner + * volume and this value. + * \param handle The handle of the source. + * \param volume The new outer volume of the cone. + * \return Whether the action succeeded. */ - virtual float getSourceSetting(AUD_Handle* handle, - AUD_3DSourceSetting setting)=0; + virtual bool setConeVolumeOuter(AUD_Handle* handle, float volume)=0; }; #endif //AUD_I3DDEVICE diff --git a/intern/audaspace/intern/AUD_IDevice.h b/intern/audaspace/intern/AUD_IDevice.h index e924f57cefc..d0925f6f647 100644 --- a/intern/audaspace/intern/AUD_IDevice.h +++ b/intern/audaspace/intern/AUD_IDevice.h @@ -30,9 +30,11 @@ class AUD_IFactory; /// Handle structure, for inherition. -typedef struct +struct AUD_Handle { -} AUD_Handle; +}; + +typedef void (*stopCallback)(void*); /** * This class represents an output device for sound sources. @@ -53,7 +55,7 @@ public: /** * Returns the specification of the device. */ - virtual AUD_DeviceSpecs getSpecs()=0; + virtual AUD_DeviceSpecs getSpecs() const=0; /** * Plays a sound source. @@ -96,6 +98,16 @@ public: virtual bool stop(AUD_Handle* handle)=0; /** + * Gets the behaviour of the device for a played back sound when the sound + * doesn't return any more samples. + * \param handle The handle returned by the play function. + * \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(AUD_Handle* handle)=0; + + /** * Sets the behaviour of the device for a played back sound when the sound * doesn't return any more samples. * \param handle The handle returned by the play function. @@ -107,16 +119,6 @@ public: virtual bool setKeep(AUD_Handle* handle, bool keep)=0; /** - * Sends a message to a sound or all sounds that are currently played or - * paused. - * \param handle The sound that should receive the message or NULL if all - * sounds should receive it. - * \param message The message. - * \return True if the message has been read by at least one sound. - */ - virtual bool sendMessage(AUD_Handle* handle, AUD_Message &message)=0; - - /** * Seeks in a played back sound. * \param handle The handle returned by the play function. * \param position The new position from where to play back, in seconds. @@ -163,29 +165,80 @@ public: virtual void unlock()=0; /** - * Checks if a specific capability as available on a device. - * \param capability The capability. - * \return Whether it is available or not. + * Retrieves the overall device volume. + * \return The overall device volume. */ - virtual bool checkCapability(int capability)=0; + virtual float getVolume() const=0; /** - * Set a value of a capability. The data behind the pointer depends on the - * capability. - * \param capability The capability. - * \param value The value. - * \return Whether the action succeeded or not. + * Sets the overall device volume. + * \param handle The sound handle. + * \param volume The overall device volume. */ - virtual bool setCapability(int capability, void *value)=0; + virtual void setVolume(float volume)=0; /** - * Retrieves a value of a capability. The data behind the pointer depends on - * the capability. - * \param capability The capability. - * \param value The value. - * \return Whether the action succeeded or not. + * Retrieves the volume of a playing sound. + * \param handle The sound handle. + * \return The volume. + */ + virtual float getVolume(AUD_Handle* handle)=0; + + /** + * Sets the volume of a playing sound. + * \param handle The sound handle. + * \param volume The volume. + * \return + * - true if the handle is valid. + * - false if the handle is invalid. + */ + virtual bool setVolume(AUD_Handle* handle, float volume)=0; + + /** + * Retrieves the pitch of a playing sound. + * \return The pitch. + */ + virtual float getPitch(AUD_Handle* handle)=0; + + /** + * Sets the pitch of a playing sound. + * \param handle The sound handle. + * \param pitch The pitch. + * \return + * - true if the handle is valid. + * - false if the handle is invalid. + */ + virtual bool setPitch(AUD_Handle* handle, float pitch)=0; + + /** + * Retrieves the loop count of a playing sound. + * A negative value indicates infinity. + * \return The remaining loop count. + */ + virtual int getLoopCount(AUD_Handle* handle)=0; + + /** + * Sets the loop count of a playing sound. + * A negative value indicates infinity. + * \param handle The sound handle. + * \param count The new loop count. + * \return + * - true if the handle is valid. + * - false if the handle is invalid. + */ + virtual bool setLoopCount(AUD_Handle* handle, int count)=0; + + /** + * Sets the callback function that's called when the end of a playing sound + * is reached. + * \param handle The sound handle. + * \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 getCapability(int capability, void *value)=0; + virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = 0, void* data = 0)=0; }; #endif //AUD_IDevice diff --git a/intern/audaspace/intern/AUD_IFactory.h b/intern/audaspace/intern/AUD_IFactory.h index f7f29c9e842..aed53cef749 100644 --- a/intern/audaspace/intern/AUD_IFactory.h +++ b/intern/audaspace/intern/AUD_IFactory.h @@ -49,7 +49,7 @@ public: * \exception AUD_Exception An exception may be thrown if there has been * a more unexpected error during reader creation. */ - virtual AUD_IReader* createReader()=0; + virtual AUD_IReader* createReader() const=0; }; #endif //AUD_IFACTORY diff --git a/intern/audaspace/intern/AUD_IReader.h b/intern/audaspace/intern/AUD_IReader.h index 02a46098d32..816abfea7f3 100644 --- a/intern/audaspace/intern/AUD_IReader.h +++ b/intern/audaspace/intern/AUD_IReader.h @@ -46,7 +46,7 @@ public: * \return Always returns true for readers of the buffer type. * \see getType */ - virtual bool isSeekable()=0; + virtual bool isSeekable() const=0; /** * Seeks to a specific position in the source. @@ -65,7 +65,7 @@ public: * \return The length as sample count. May be negative if unknown. * \see getType */ - virtual int getLength()=0; + virtual int getLength() const=0; /** * Returns the position of the source as a sample count value. @@ -76,30 +76,13 @@ public: * the buffer ones. * \see getType */ - virtual int getPosition()=0; + virtual int getPosition() const=0; /** * Returns the specification of the reader. * \return The AUD_Specs structure. */ - virtual AUD_Specs getSpecs()=0; - - /** - * Returns the type of the reader. There are special conditions for the - * readers of the buffer type. Those have to return correct position and - * length values as well as they must be seekable. - * \return AUD_TYPE_BUFFER or AUD_TYPE_STREAM. - */ - virtual AUD_ReaderType getType()=0; - - /** - * Sends a message to this reader and if it has subreaders it broadcasts - * the message to them. - * \param message The message. - * \return Whether the message has been read by the reader or one of his - * subreaders. - */ - virtual bool notify(AUD_Message &message)=0; + virtual AUD_Specs getSpecs() const=0; /** * Request to read the next length samples out of the source. diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.cpp b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp index e738fc17693..91414c6a392 100644 --- a/intern/audaspace/intern/AUD_LinearResampleFactory.cpp +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp @@ -26,28 +26,18 @@ #include "AUD_LinearResampleFactory.h" #include "AUD_LinearResampleReader.h" -AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_IReader* reader, - AUD_DeviceSpecs specs) : - AUD_ResampleFactory(reader, specs) {} - AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs) : - AUD_ResampleFactory(factory, specs) {} - -AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_DeviceSpecs specs) : - AUD_ResampleFactory(specs) {} + AUD_ResampleFactory(factory, specs) +{ +} -AUD_IReader* AUD_LinearResampleFactory::createReader() +AUD_IReader* AUD_LinearResampleFactory::createReader() const { AUD_IReader* reader = getReader(); - if(reader != 0) - { - if(reader->getSpecs().rate != m_specs.rate) - { - reader = new AUD_LinearResampleReader(reader, m_specs.specs); - AUD_NEW("reader") - } - } + if(reader->getSpecs().rate != m_specs.rate) + reader = new AUD_LinearResampleReader(reader, m_specs.specs); + return reader; } diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.h b/intern/audaspace/intern/AUD_LinearResampleFactory.h index 81a9d623815..426641f6099 100644 --- a/intern/audaspace/intern/AUD_LinearResampleFactory.h +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.h @@ -33,12 +33,15 @@ */ class AUD_LinearResampleFactory : public AUD_ResampleFactory { +private: + // hide copy constructor and operator= + AUD_LinearResampleFactory(const AUD_LinearResampleFactory&); + AUD_LinearResampleFactory& operator=(const AUD_LinearResampleFactory&); + public: - AUD_LinearResampleFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); AUD_LinearResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); - AUD_LinearResampleFactory(AUD_DeviceSpecs specs); - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_LINEARRESAMPLEFACTORY diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.cpp b/intern/audaspace/intern/AUD_LinearResampleReader.cpp index dcd5310575d..cfe7561d336 100644 --- a/intern/audaspace/intern/AUD_LinearResampleReader.cpp +++ b/intern/audaspace/intern/AUD_LinearResampleReader.cpp @@ -24,7 +24,6 @@ */ #include "AUD_LinearResampleReader.h" -#include "AUD_Buffer.h" #include <cmath> #include <cstring> @@ -33,25 +32,15 @@ AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_IReader* reader, AUD_Specs specs) : - AUD_EffectReader(reader) + AUD_EffectReader(reader), + m_sspecs(reader->getSpecs()), + m_factor(float(specs.rate) / float(m_sspecs.rate)), + m_tspecs(specs), + m_position(0), + m_sposition(0) { - m_sspecs = reader->getSpecs(); - - m_tspecs = specs; m_tspecs.channels = m_sspecs.channels; - m_factor = (float)m_tspecs.rate / (float)m_sspecs.rate; - - m_position = 0; - m_sposition = 0; - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - m_cache = new AUD_Buffer(2 * AUD_SAMPLE_SIZE(specs)); AUD_NEW("buffer") -} - -AUD_LinearResampleReader::~AUD_LinearResampleReader() -{ - delete m_buffer; AUD_DELETE("buffer") - delete m_cache; AUD_DELETE("buffer") + m_cache.resize(2 * AUD_SAMPLE_SIZE(m_tspecs)); } void AUD_LinearResampleReader::seek(int position) @@ -61,17 +50,17 @@ void AUD_LinearResampleReader::seek(int position) m_reader->seek(m_sposition); } -int AUD_LinearResampleReader::getLength() +int AUD_LinearResampleReader::getLength() const { return m_reader->getLength() * m_factor; } -int AUD_LinearResampleReader::getPosition() +int AUD_LinearResampleReader::getPosition() const { return m_position; } -AUD_Specs AUD_LinearResampleReader::getSpecs() +AUD_Specs AUD_LinearResampleReader::getSpecs() const { return m_tspecs; } @@ -81,13 +70,13 @@ void AUD_LinearResampleReader::read(int & length, sample_t* & buffer) int samplesize = AUD_SAMPLE_SIZE(m_tspecs); int size = length * samplesize; - if(m_buffer->getSize() < size) - m_buffer->resize(size); + if(m_buffer.getSize() < size) + m_buffer.resize(size); int need = ceil((m_position + length) / m_factor) + 1 - m_sposition; int len = need; sample_t* buf; - buffer = m_buffer->getBuffer(); + buffer = m_buffer.getBuffer(); m_reader->read(len, buf); @@ -106,9 +95,9 @@ void AUD_LinearResampleReader::read(int & length, sample_t* & buffer) if(floor(spos) < 0) { - low = m_cache->getBuffer()[(int)(floor(spos) + 2) * CC]; + low = m_cache.getBuffer()[(int)(floor(spos) + 2) * CC]; if(ceil(spos) < 0) - high = m_cache->getBuffer()[(int)(ceil(spos) + 2) * CC]; + high = m_cache.getBuffer()[(int)(ceil(spos) + 2) * CC]; else high = buf[(int)ceil(spos) * CC]; } @@ -122,11 +111,11 @@ void AUD_LinearResampleReader::read(int & length, sample_t* & buffer) } if(len > 1) - memcpy(m_cache->getBuffer(), + memcpy(m_cache.getBuffer(), buf + (len - 2) * channels, 2 * samplesize); else if(len == 1) - memcpy(m_cache->getBuffer() + 1 * channels, buf, samplesize); + memcpy(m_cache.getBuffer() + 1 * channels, buf, samplesize); m_sposition += len; m_position += length; diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.h b/intern/audaspace/intern/AUD_LinearResampleReader.h index c86b8b76c59..fbf56286857 100644 --- a/intern/audaspace/intern/AUD_LinearResampleReader.h +++ b/intern/audaspace/intern/AUD_LinearResampleReader.h @@ -27,7 +27,7 @@ #define AUD_LINEARRESAMPLEREADER #include "AUD_EffectReader.h" -class AUD_Buffer; +#include "AUD_Buffer.h" /** * This resampling reader uses libsamplerate for resampling. @@ -36,9 +36,19 @@ class AUD_LinearResampleReader : public AUD_EffectReader { private: /** + * The sample specification of the source. + */ + const AUD_Specs m_sspecs; + + /** * The resampling factor. */ - float m_factor; + const float m_factor; + + /** + * The target specification. + */ + AUD_Specs m_tspecs; /** * The current position. @@ -53,41 +63,29 @@ private: /** * The sound output buffer. */ - AUD_Buffer *m_buffer; + AUD_Buffer m_buffer; /** * The input caching buffer. */ - AUD_Buffer *m_cache; - - /** - * The target specification. - */ - AUD_Specs m_tspecs; + AUD_Buffer m_cache; - /** - * The sample specification of the source. - */ - AUD_Specs m_sspecs; + // hide copy constructor and operator= + AUD_LinearResampleReader(const AUD_LinearResampleReader&); + AUD_LinearResampleReader& operator=(const AUD_LinearResampleReader&); public: /** * Creates a resampling reader. * \param reader The reader to mix. * \param specs The target specification. - * \exception AUD_Exception Thrown if the reader is NULL. */ AUD_LinearResampleReader(AUD_IReader* reader, AUD_Specs specs); - /** - * Destroys the reader. - */ - ~AUD_LinearResampleReader(); - virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); - virtual AUD_Specs getSpecs(); + virtual int getLength() const; + virtual int getPosition() const; + virtual AUD_Specs getSpecs() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/intern/AUD_Mixer.cpp b/intern/audaspace/intern/AUD_Mixer.cpp index e77d40fdbca..419ac3af6ac 100644 --- a/intern/audaspace/intern/AUD_Mixer.cpp +++ b/intern/audaspace/intern/AUD_Mixer.cpp @@ -24,72 +24,13 @@ */ #include "AUD_Mixer.h" -#include "AUD_SRCResampleFactory.h" -#include "AUD_LinearResampleFactory.h" -#include "AUD_ChannelMapperFactory.h" #include "AUD_IReader.h" -#include "AUD_Buffer.h" #include <cstring> -AUD_Mixer::AUD_Mixer() +AUD_Mixer::AUD_Mixer(AUD_DeviceSpecs specs) : + m_specs(specs) { - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - - m_resampler = NULL; - m_mapper = NULL; -} - -AUD_Mixer::~AUD_Mixer() -{ - delete m_buffer; AUD_DELETE("buffer") - - - if(m_resampler) - { - delete m_resampler; AUD_DELETE("factory") - } - if(m_mapper) - { - delete m_mapper; AUD_DELETE("factory") - } -} - -AUD_IReader* AUD_Mixer::prepare(AUD_IReader* reader) -{ - m_resampler->setReader(reader); - reader = m_resampler->createReader(); - - if(reader != NULL && reader->getSpecs().channels != m_specs.channels) - { - m_mapper->setReader(reader); - reader = m_mapper->createReader(); - } - - return reader; -} - -AUD_DeviceSpecs AUD_Mixer::getSpecs() -{ - return m_specs; -} - -void AUD_Mixer::setSpecs(AUD_DeviceSpecs specs) -{ - m_specs = specs; - - if(m_resampler) - { - delete m_resampler; AUD_DELETE("factory") - } - if(m_mapper) - { - delete m_mapper; AUD_DELETE("factory") - } - - m_resampler = new AUD_MIXER_RESAMPLER(specs); AUD_NEW("factory") - m_mapper = new AUD_ChannelMapperFactory(specs); AUD_NEW("factory") - int bigendian = 1; bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian @@ -121,6 +62,11 @@ void AUD_Mixer::setSpecs(AUD_DeviceSpecs specs) } } +AUD_DeviceSpecs AUD_Mixer::getSpecs() const +{ + return m_specs; +} + void AUD_Mixer::add(sample_t* buffer, int start, int length, float volume) { AUD_MixerBuffer buf; @@ -137,10 +83,10 @@ void AUD_Mixer::superpose(data_t* buffer, int length, float volume) int channels = m_specs.channels; - if(m_buffer->getSize() < length * channels * 4) - m_buffer->resize(length * channels * 4); + if(m_buffer.getSize() < length * channels * 4) + m_buffer.resize(length * channels * 4); - sample_t* out = m_buffer->getBuffer(); + sample_t* out = m_buffer.getBuffer(); sample_t* in; memset(out, 0, length * channels * 4); diff --git a/intern/audaspace/intern/AUD_Mixer.h b/intern/audaspace/intern/AUD_Mixer.h index 2e7ba743541..a7f5fb274f0 100644 --- a/intern/audaspace/intern/AUD_Mixer.h +++ b/intern/audaspace/intern/AUD_Mixer.h @@ -26,13 +26,8 @@ #ifndef AUD_MIXER #define AUD_MIXER -#define AUD_MIXER_RESAMPLER AUD_SRCResampleFactory - #include "AUD_ConverterFunctions.h" -class AUD_ConverterFactory; -class AUD_MIXER_RESAMPLER; -class AUD_ChannelMapperFactory; -class AUD_Buffer; +#include "AUD_Buffer.h" class AUD_IReader; #include <list> @@ -45,24 +40,12 @@ struct AUD_MixerBuffer }; /** - * This class is able to mix audiosignals of different channel count and sample - * rate and convert it to a specific output format. - * It uses a default ChannelMapperFactory and a SRCResampleFactory for - * the perparation. + * This abstract class is able to mix audiosignals of different channel count + * and sample rate and convert it to a specific output format. */ class AUD_Mixer { -private: - /** - * The resampling factory that resamples all readers for superposition. - */ - AUD_MIXER_RESAMPLER* m_resampler; - - /** - * The channel mapper factory that maps all readers for superposition. - */ - AUD_ChannelMapperFactory* m_mapper; - +protected: /** * The list of buffers to superpose. */ @@ -71,12 +54,12 @@ private: /** * The output specification. */ - AUD_DeviceSpecs m_specs; + const AUD_DeviceSpecs m_specs; /** * The temporary mixing buffer. */ - AUD_Buffer* m_buffer; + AUD_Buffer m_buffer; /** * Converter function. @@ -87,31 +70,25 @@ public: /** * Creates the mixer. */ - AUD_Mixer(); + AUD_Mixer(AUD_DeviceSpecs specs); /** * Destroys the mixer. */ - ~AUD_Mixer(); - - /** - * This funuction prepares a reader for playback. - * \param reader The reader to prepare. - * \return The reader that should be used for playback. - */ - AUD_IReader* prepare(AUD_IReader* reader); + virtual ~AUD_Mixer() {} /** * Returns the target specification for superposing. * \return The target specification. */ - AUD_DeviceSpecs getSpecs(); + AUD_DeviceSpecs getSpecs() const; /** - * Sets the target specification for superposing. - * \param specs The target specification. + * This funuction prepares a reader for playback. + * \param reader The reader to prepare. + * \return The reader that should be used for playback. */ - void setSpecs(AUD_DeviceSpecs specs); + virtual AUD_IReader* prepare(AUD_IReader* reader)=0; /** * Adds a buffer for superposition. @@ -120,7 +97,7 @@ public: * \param length The length of the buffer in samples. * \param volume The mixing volume. Must be a value between 0.0 and 1.0. */ - void add(sample_t* buffer, int start, int length, float volume); + virtual void add(sample_t* buffer, int start, int length, float volume); /** * Superposes all added buffers into an output buffer. @@ -128,7 +105,7 @@ public: * \param length The length of the buffer in samples. * \param volume The mixing volume. Must be a value between 0.0 and 1.0. */ - void superpose(data_t* buffer, int length, float volume); + virtual void superpose(data_t* buffer, int length, float volume); }; #endif //AUD_MIXER diff --git a/intern/audaspace/intern/AUD_MixerFactory.cpp b/intern/audaspace/intern/AUD_MixerFactory.cpp index e78818301fa..4370bed6ca6 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.cpp +++ b/intern/audaspace/intern/AUD_MixerFactory.cpp @@ -26,84 +26,23 @@ #include "AUD_MixerFactory.h" #include "AUD_IReader.h" -AUD_IReader* AUD_MixerFactory::getReader() +AUD_IReader* AUD_MixerFactory::getReader() const { - AUD_IReader* reader; - - // first check for an existing reader - if(m_reader != 0) - { - reader = m_reader; - m_reader = 0; - return reader; - } - - // otherwise create a reader if there is a factory - if(m_factory != 0) - { - reader = m_factory->createReader(); - return reader; - } - - return 0; -} - -AUD_MixerFactory::AUD_MixerFactory(AUD_IReader* reader, - AUD_DeviceSpecs specs) -{ - m_specs = specs; - m_reader = reader; - m_factory = 0; + return m_factory->createReader(); } AUD_MixerFactory::AUD_MixerFactory(AUD_IFactory* factory, - AUD_DeviceSpecs specs) + AUD_DeviceSpecs specs) : + m_specs(specs), m_factory(factory) { - m_specs = specs; - m_reader = 0; - m_factory = factory; } -AUD_MixerFactory::AUD_MixerFactory(AUD_DeviceSpecs specs) -{ - m_specs = specs; - m_reader = 0; - m_factory = 0; -} - -AUD_MixerFactory::~AUD_MixerFactory() -{ - if(m_reader != 0) - { - delete m_reader; AUD_DELETE("reader") - } -} - -AUD_DeviceSpecs AUD_MixerFactory::getSpecs() +AUD_DeviceSpecs AUD_MixerFactory::getSpecs() const { return m_specs; } -void AUD_MixerFactory::setSpecs(AUD_DeviceSpecs specs) -{ - m_specs = specs; -} - -void AUD_MixerFactory::setReader(AUD_IReader* reader) -{ - if(m_reader != 0) - { - delete m_reader; AUD_DELETE("reader") - } - m_reader = reader; -} - -void AUD_MixerFactory::setFactory(AUD_IFactory* factory) -{ - m_factory = factory; -} - -AUD_IFactory* AUD_MixerFactory::getFactory() +AUD_IFactory* AUD_MixerFactory::getFactory() const { return m_factory; } diff --git a/intern/audaspace/intern/AUD_MixerFactory.h b/intern/audaspace/intern/AUD_MixerFactory.h index a2f4aa78d76..909eca8c148 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.h +++ b/intern/audaspace/intern/AUD_MixerFactory.h @@ -35,9 +35,9 @@ class AUD_MixerFactory : public AUD_IFactory { protected: /** - * The reader that should be mixed later. + * The target specification for resampling. */ - AUD_IReader* m_reader; + const AUD_DeviceSpecs m_specs; /** * If there is no reader it is created out of this factory. @@ -45,73 +45,31 @@ protected: AUD_IFactory* m_factory; /** - * The target specification for resampling. - */ - AUD_DeviceSpecs m_specs; - - /** - * Returns the reader created out of the factory or taken from m_reader. + * Returns the reader created out of the factory. * This method can be used for the createReader function of the implementing * classes. - * \return The reader to mix, or NULL if there is no reader or factory. + * \return The reader to mix. */ - AUD_IReader* getReader(); + AUD_IReader* getReader() const; public: /** * Creates a new factory. - * \param reader The reader to mix. - * \param specs The target specification. - */ - AUD_MixerFactory(AUD_IReader* reader, AUD_DeviceSpecs specs); - - /** - * Creates a new factory. * \param factory The factory to create the readers to mix out of. * \param specs The target specification. */ AUD_MixerFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); /** - * Creates a new factory. - * \param specs The target specification. - */ - AUD_MixerFactory(AUD_DeviceSpecs specs); - - /** - * Destroys the resampling factory. - */ - virtual ~AUD_MixerFactory(); - - /** * Returns the target specification for resampling. */ - AUD_DeviceSpecs getSpecs(); - - /** - * Sets the target specification for resampling. - * \param specs The specification. - */ - void setSpecs(AUD_DeviceSpecs specs); - - /** - * Sets the reader for resampling. - * If there has already been a reader, it will be deleted. - * \param reader The reader that should be used as source for resampling. - */ - void setReader(AUD_IReader* reader); - - /** - * Sets the factory for resampling. - * \param factory The factory that should be used as source for resampling. - */ - void setFactory(AUD_IFactory* factory); + AUD_DeviceSpecs getSpecs() const; /** * Returns the saved factory. - * \return The factory or NULL if there has no factory been saved. + * \return The factory. */ - AUD_IFactory* getFactory(); + AUD_IFactory* getFactory() const; }; #endif //AUD_MIXERFACTORY diff --git a/intern/audaspace/intern/AUD_NULLDevice.cpp b/intern/audaspace/intern/AUD_NULLDevice.cpp index c9dfadd1839..272e1e4b5b2 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.cpp +++ b/intern/audaspace/intern/AUD_NULLDevice.cpp @@ -31,14 +31,15 @@ AUD_NULLDevice::AUD_NULLDevice() { - m_specs.channels = AUD_CHANNELS_INVALID; - m_specs.format = AUD_FORMAT_INVALID; - m_specs.rate = AUD_RATE_INVALID; } -AUD_DeviceSpecs AUD_NULLDevice::getSpecs() +AUD_DeviceSpecs AUD_NULLDevice::getSpecs() const { - return m_specs; + AUD_DeviceSpecs specs; + specs.channels = AUD_CHANNELS_INVALID; + specs.format = AUD_FORMAT_INVALID; + specs.rate = AUD_RATE_INVALID; + return specs; } AUD_Handle* AUD_NULLDevice::play(AUD_IFactory* factory, bool keep) @@ -61,12 +62,12 @@ bool AUD_NULLDevice::stop(AUD_Handle* handle) return false; } -bool AUD_NULLDevice::setKeep(AUD_Handle* handle, bool keep) +bool AUD_NULLDevice::getKeep(AUD_Handle* handle) { return false; } -bool AUD_NULLDevice::sendMessage(AUD_Handle* handle, AUD_Message &message) +bool AUD_NULLDevice::setKeep(AUD_Handle* handle, bool keep) { return false; } @@ -94,17 +95,46 @@ void AUD_NULLDevice::unlock() { } -bool AUD_NULLDevice::checkCapability(int capability) +float AUD_NULLDevice::getVolume() const +{ + return 0; +} + +void AUD_NULLDevice::setVolume(float volume) +{ +} + +float AUD_NULLDevice::getVolume(AUD_Handle* handle) +{ + return std::numeric_limits<float>::quiet_NaN(); +} + +bool AUD_NULLDevice::setVolume(AUD_Handle* handle, float volume) { return false; } -bool AUD_NULLDevice::setCapability(int capability, void *value) +float AUD_NULLDevice::getPitch(AUD_Handle* handle) +{ + return std::numeric_limits<float>::quiet_NaN(); +} + +bool AUD_NULLDevice::setPitch(AUD_Handle* handle, float pitch) +{ + return false; +} + +int AUD_NULLDevice::getLoopCount(AUD_Handle* handle) +{ + return 0; +} + +bool AUD_NULLDevice::setLoopCount(AUD_Handle* handle, int count) { return false; } -bool AUD_NULLDevice::getCapability(int capability, void *value) +bool AUD_NULLDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data) { return false; } diff --git a/intern/audaspace/intern/AUD_NULLDevice.h b/intern/audaspace/intern/AUD_NULLDevice.h index 91ddd23cf71..a1ffdba201a 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.h +++ b/intern/audaspace/intern/AUD_NULLDevice.h @@ -33,33 +33,33 @@ */ class AUD_NULLDevice : public AUD_IDevice { -private: - /** - * The specs of the device. - */ - AUD_DeviceSpecs m_specs; - public: /** * Creates a new NULL device. */ AUD_NULLDevice(); - virtual AUD_DeviceSpecs getSpecs(); + virtual AUD_DeviceSpecs getSpecs() const; virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false); virtual bool pause(AUD_Handle* handle); virtual bool resume(AUD_Handle* handle); virtual bool stop(AUD_Handle* handle); + virtual bool getKeep(AUD_Handle* handle); virtual bool setKeep(AUD_Handle* handle, bool keep); - virtual bool sendMessage(AUD_Handle* handle, AUD_Message &message); virtual bool seek(AUD_Handle* handle, float position); virtual float getPosition(AUD_Handle* handle); virtual AUD_Status getStatus(AUD_Handle* handle); virtual void lock(); virtual void unlock(); - virtual bool checkCapability(int capability); - virtual bool setCapability(int capability, void *value); - virtual bool getCapability(int capability, void *value); + virtual float getVolume() const; + virtual void setVolume(float volume); + virtual float getVolume(AUD_Handle* handle); + virtual bool setVolume(AUD_Handle* handle, float volume); + virtual float getPitch(AUD_Handle* handle); + virtual bool setPitch(AUD_Handle* handle, float pitch); + virtual int getLoopCount(AUD_Handle* handle); + virtual bool setLoopCount(AUD_Handle* handle, int count); + virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = 0, void* data = 0); }; #endif //AUD_NULLDEVICE diff --git a/intern/audaspace/intern/AUD_ReadDevice.cpp b/intern/audaspace/intern/AUD_ReadDevice.cpp index 37a7d1ae295..cde5694354e 100644 --- a/intern/audaspace/intern/AUD_ReadDevice.cpp +++ b/intern/audaspace/intern/AUD_ReadDevice.cpp @@ -23,21 +23,17 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#include "AUD_Mixer.h" +#include "AUD_DefaultMixer.h" #include "AUD_ReadDevice.h" #include "AUD_IReader.h" #include <cstring> -AUD_ReadDevice::AUD_ReadDevice(AUD_DeviceSpecs specs) +AUD_ReadDevice::AUD_ReadDevice(AUD_DeviceSpecs specs) : + m_playing(false) { m_specs = specs; - m_mixer = new AUD_Mixer(); AUD_NEW("mixer") - m_mixer->setSpecs(m_specs); - - m_playing = false; - create(); } diff --git a/intern/audaspace/intern/AUD_ReadDevice.h b/intern/audaspace/intern/AUD_ReadDevice.h index 3fd90df7755..121bcb8612b 100644 --- a/intern/audaspace/intern/AUD_ReadDevice.h +++ b/intern/audaspace/intern/AUD_ReadDevice.h @@ -33,15 +33,19 @@ */ class AUD_ReadDevice : public AUD_SoftwareDevice { -protected: - virtual void playing(bool playing); - private: /** * Whether the device currently. */ bool m_playing; + // hide copy constructor and operator= + AUD_ReadDevice(const AUD_ReadDevice&); + AUD_ReadDevice& operator=(const AUD_ReadDevice&); + +protected: + virtual void playing(bool playing); + public: /** * Creates a new read device. diff --git a/intern/audaspace/intern/AUD_Reference.h b/intern/audaspace/intern/AUD_Reference.h index 9bb9d7440b3..6b1001e2b01 100644 --- a/intern/audaspace/intern/AUD_Reference.h +++ b/intern/audaspace/intern/AUD_Reference.h @@ -45,12 +45,12 @@ public: AUD_Reference(T* reference = 0) { m_reference = reference; - m_refcount = new int; AUD_NEW("int") + m_refcount = new int; *m_refcount = 1; } /** - * Copies a AUD_Reference object. + * Copies an AUD_Reference object. * \param ref The AUD_Reference object to copy. */ AUD_Reference(const AUD_Reference& ref) @@ -69,17 +69,17 @@ public: (*m_refcount)--; if(*m_refcount == 0) { - if(m_reference != 0) + if(m_reference) { - delete m_reference; AUD_DELETE("buffer") + delete m_reference; } - delete m_refcount; AUD_DELETE("int") + delete m_refcount; } } /** - * Copies a AUD_Reference object. - * \param ref The AUD_Reference object to copy. + * Assigns an AUD_Reference to this object. + * \param ref The AUD_Reference object to assign. */ AUD_Reference& operator=(const AUD_Reference& ref) { @@ -89,11 +89,11 @@ public: (*m_refcount)--; if(*m_refcount == 0) { - if(m_reference != 0) + if(m_reference) { - delete m_reference; AUD_DELETE("buffer") + delete m_reference; } - delete m_refcount; AUD_DELETE("int") + delete m_refcount; } m_reference = ref.m_reference; @@ -106,7 +106,7 @@ public: /** * Returns the reference. */ - T* get() + T* get() const { return m_reference; } diff --git a/intern/audaspace/intern/AUD_SequencerFactory.cpp b/intern/audaspace/intern/AUD_SequencerFactory.cpp index bb5cf27fb5f..05c7fefea4a 100644 --- a/intern/audaspace/intern/AUD_SequencerFactory.cpp +++ b/intern/audaspace/intern/AUD_SequencerFactory.cpp @@ -28,11 +28,12 @@ typedef std::list<AUD_SequencerReader*>::iterator AUD_ReaderIterator; -AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, void* data, AUD_volumeFunction volume) +AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, void* data, + AUD_volumeFunction volume) : + m_specs(specs), + m_data(data), + m_volume(volume) { - m_specs = specs; - m_data = data; - m_volume = volume; } AUD_SequencerFactory::~AUD_SequencerFactory() @@ -51,13 +52,23 @@ AUD_SequencerFactory::~AUD_SequencerFactory() { entry = m_entries.front(); m_entries.pop_front(); - delete entry; AUD_DELETE("seqentry") + delete entry; } } +AUD_IReader* AUD_SequencerFactory::newReader() +{ + AUD_SequencerReader* reader = new AUD_SequencerReader(this, m_entries, + m_specs, m_data, + m_volume); + m_readers.push_front(reader); + + return reader; +} + AUD_SequencerEntry* AUD_SequencerFactory::add(AUD_IFactory** sound, float begin, float end, float skip, void* data) { - AUD_SequencerEntry* entry = new AUD_SequencerEntry; AUD_NEW("seqentry") + AUD_SequencerEntry* entry = new AUD_SequencerEntry; entry->sound = sound; entry->begin = begin; entry->skip = skip; @@ -80,7 +91,7 @@ void AUD_SequencerFactory::remove(AUD_SequencerEntry* entry) m_entries.remove(entry); - delete entry; AUD_DELETE("seqentry") + delete entry; } void AUD_SequencerFactory::move(AUD_SequencerEntry* entry, float begin, float end, float skip) @@ -95,12 +106,9 @@ void AUD_SequencerFactory::mute(AUD_SequencerEntry* entry, bool mute) entry->muted = mute; } -AUD_IReader* AUD_SequencerFactory::createReader() +AUD_IReader* AUD_SequencerFactory::createReader() const { - AUD_SequencerReader* reader = new AUD_SequencerReader(this, m_entries, m_specs, m_data, m_volume); AUD_NEW("reader") - m_readers.push_front(reader); - - return reader; + return const_cast<AUD_SequencerFactory*>(this)->newReader(); } void AUD_SequencerFactory::removeReader(AUD_SequencerReader* reader) diff --git a/intern/audaspace/intern/AUD_SequencerFactory.h b/intern/audaspace/intern/AUD_SequencerFactory.h index b564c888fc6..a2c8f48fa54 100644 --- a/intern/audaspace/intern/AUD_SequencerFactory.h +++ b/intern/audaspace/intern/AUD_SequencerFactory.h @@ -60,6 +60,12 @@ private: void* m_data; AUD_volumeFunction m_volume; + AUD_IReader* newReader(); + + // hide copy constructor and operator= + AUD_SequencerFactory(const AUD_SequencerFactory&); + AUD_SequencerFactory& operator=(const AUD_SequencerFactory&); + public: AUD_SequencerFactory(AUD_Specs specs, void* data, AUD_volumeFunction volume); ~AUD_SequencerFactory(); @@ -69,7 +75,7 @@ public: void move(AUD_SequencerEntry* entry, float begin, float end, float skip); void mute(AUD_SequencerEntry* entry, bool mute); - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; void removeReader(AUD_SequencerReader* reader); }; diff --git a/intern/audaspace/intern/AUD_SequencerReader.cpp b/intern/audaspace/intern/AUD_SequencerReader.cpp index 8869d8d54ca..69293205498 100644 --- a/intern/audaspace/intern/AUD_SequencerReader.cpp +++ b/intern/audaspace/intern/AUD_SequencerReader.cpp @@ -24,20 +24,22 @@ */ #include "AUD_SequencerReader.h" -#include "AUD_Buffer.h" +#include "AUD_DefaultMixer.h" #include <math.h> typedef std::list<AUD_SequencerStrip*>::iterator AUD_StripIterator; typedef std::list<AUD_SequencerEntry*>::iterator AUD_EntryIterator; -AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory, std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs, void* data, AUD_volumeFunction volume) +AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory, + std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs, + void* data, AUD_volumeFunction volume) { AUD_DeviceSpecs dspecs; dspecs.specs = specs; dspecs.format = AUD_FORMAT_FLOAT32; - m_mixer.setSpecs(dspecs); + m_mixer = new AUD_DefaultMixer(dspecs); m_factory = factory; m_data = data; m_volume = volume; @@ -46,12 +48,12 @@ AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory, std::lis for(AUD_EntryIterator i = entries.begin(); i != entries.end(); i++) { - strip = new AUD_SequencerStrip; AUD_NEW("seqstrip") + strip = new AUD_SequencerStrip; strip->entry = *i; strip->old_sound = NULL; if(strip->old_sound) - strip->reader = m_mixer.prepare(strip->old_sound->createReader()); + strip->reader = m_mixer->prepare(strip->old_sound->createReader()); else strip->reader = NULL; @@ -59,7 +61,6 @@ AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory, std::lis } m_position = 0; - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } AUD_SequencerReader::~AUD_SequencerReader() @@ -75,12 +76,12 @@ AUD_SequencerReader::~AUD_SequencerReader() m_strips.pop_front(); if(strip->reader) { - delete strip->reader; AUD_DELETE("reader") + delete strip->reader; } - delete strip; AUD_DELETE("seqstrip") + delete strip; } - delete m_buffer; AUD_DELETE("buffer") + delete m_mixer; } void AUD_SequencerReader::destroy() @@ -92,19 +93,19 @@ void AUD_SequencerReader::destroy() { strip = m_strips.front(); m_strips.pop_front(); - delete strip; AUD_DELETE("seqstrip") + delete strip; } } void AUD_SequencerReader::add(AUD_SequencerEntry* entry) { - AUD_SequencerStrip* strip = new AUD_SequencerStrip; AUD_NEW("seqstrip") + AUD_SequencerStrip* strip = new AUD_SequencerStrip; strip->entry = entry; if(*strip->entry->sound) { strip->old_sound = *strip->entry->sound; - strip->reader = m_mixer.prepare(strip->old_sound->createReader()); + strip->reader = m_mixer->prepare(strip->old_sound->createReader()); } else { @@ -125,16 +126,16 @@ void AUD_SequencerReader::remove(AUD_SequencerEntry* entry) i++; if(strip->reader) { - delete strip->reader; AUD_DELETE("reader") + delete strip->reader; } m_strips.remove(strip); - delete strip; AUD_DELETE("seqstrip") + delete strip; return; } } } -bool AUD_SequencerReader::isSeekable() +bool AUD_SequencerReader::isSeekable() const { return true; } @@ -144,44 +145,24 @@ void AUD_SequencerReader::seek(int position) m_position = position; } -int AUD_SequencerReader::getLength() +int AUD_SequencerReader::getLength() const { return -1; } -int AUD_SequencerReader::getPosition() +int AUD_SequencerReader::getPosition() const { return m_position; } -AUD_Specs AUD_SequencerReader::getSpecs() +AUD_Specs AUD_SequencerReader::getSpecs() const { - return m_mixer.getSpecs().specs; -} - -AUD_ReaderType AUD_SequencerReader::getType() -{ - return AUD_TYPE_STREAM; -} - -bool AUD_SequencerReader::notify(AUD_Message &message) -{ - bool result = false; - AUD_SequencerStrip* strip; - - for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++) - { - strip = *i; - if(strip->reader) - result |= (*i)->reader->notify(message); - } - - return result; + return m_mixer->getSpecs().specs; } void AUD_SequencerReader::read(int & length, sample_t* & buffer) { - AUD_DeviceSpecs specs = m_mixer.getSpecs(); + AUD_DeviceSpecs specs = m_mixer->getSpecs(); int samplesize = AUD_SAMPLE_SIZE(specs); int rate = specs.rate; @@ -191,9 +172,9 @@ void AUD_SequencerReader::read(int & length, sample_t* & buffer) AUD_SequencerStrip* strip; sample_t* buf; - if(m_buffer->getSize() < size) - m_buffer->resize(size); - buffer = m_buffer->getBuffer(); + if(m_buffer.getSize() < size) + m_buffer.resize(size); + buffer = m_buffer.getBuffer(); for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++) { @@ -204,12 +185,10 @@ void AUD_SequencerReader::read(int & length, sample_t* & buffer) { strip->old_sound = *strip->entry->sound; if(strip->reader) - { - delete strip->reader; AUD_DELETE("reader") - } + delete strip->reader; if(strip->old_sound) - strip->reader = m_mixer.prepare(strip->old_sound->createReader()); + strip->reader = m_mixer->prepare(strip->old_sound->createReader()); else strip->reader = NULL; } @@ -236,14 +215,14 @@ void AUD_SequencerReader::read(int & length, sample_t* & buffer) if(strip->reader->getPosition() != current) strip->reader->seek(current); strip->reader->read(len, buf); - m_mixer.add(buf, skip, len, m_volume(m_data, strip->entry->data, (float)m_position / (float)rate)); + m_mixer->add(buf, skip, len, m_volume(m_data, strip->entry->data, (float)m_position / (float)rate)); } } } } } - m_mixer.superpose((data_t*)buffer, length, 1.0f); + m_mixer->superpose((data_t*)buffer, length, 1.0f); m_position += length; } diff --git a/intern/audaspace/intern/AUD_SequencerReader.h b/intern/audaspace/intern/AUD_SequencerReader.h index a50e1642260..fd7d94c7578 100644 --- a/intern/audaspace/intern/AUD_SequencerReader.h +++ b/intern/audaspace/intern/AUD_SequencerReader.h @@ -28,9 +28,8 @@ #include "AUD_IReader.h" #include "AUD_SequencerFactory.h" -#include "AUD_Mixer.h" - -class AUD_Buffer; +#include "AUD_Buffer.h" +class AUD_Mixer; struct AUD_SequencerStrip { @@ -53,12 +52,12 @@ private: /** * The sound output buffer. */ - AUD_Buffer *m_buffer; + AUD_Buffer m_buffer; /** * The target specification. */ - AUD_Mixer m_mixer; + AUD_Mixer* m_mixer; /** * Saves the SequencerFactory the reader belongs to. @@ -70,14 +69,17 @@ private: void* m_data; AUD_volumeFunction m_volume; + // hide copy constructor and operator= + AUD_SequencerReader(const AUD_SequencerReader&); + AUD_SequencerReader& operator=(const AUD_SequencerReader&); + public: /** * Creates a resampling reader. * \param reader The reader to mix. * \param specs The target specification. - * \exception AUD_Exception Thrown if the reader is NULL. */ - AUD_SequencerReader(AUD_SequencerFactory* factory, std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs, void* data, AUD_volumeFunction volume); + AUD_SequencerReader(AUD_SequencerFactory* factory, std::list<AUD_SequencerEntry*> &entries, const AUD_Specs specs, void* data, AUD_volumeFunction volume); /** * Destroys the reader. @@ -89,13 +91,11 @@ public: void add(AUD_SequencerEntry* entry); void remove(AUD_SequencerEntry* entry); - virtual bool isSeekable(); + virtual bool isSeekable() const; virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); - virtual AUD_Specs getSpecs(); - virtual AUD_ReaderType getType(); - virtual bool notify(AUD_Message &message); + virtual int getLength() const; + virtual int getPosition() const; + virtual AUD_Specs getSpecs() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/intern/AUD_SourceCaps.h b/intern/audaspace/intern/AUD_SilenceFactory.cpp index b1edd2b9b4e..4e59d7486d5 100644 --- a/intern/audaspace/intern/AUD_SourceCaps.h +++ b/intern/audaspace/intern/AUD_SilenceFactory.cpp @@ -23,19 +23,15 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#ifndef AUD_SOURCECAPS -#define AUD_SOURCECAPS +#include "AUD_SilenceFactory.h" +#include "AUD_SilenceReader.h" +#include "AUD_Space.h" -#include "AUD_IDevice.h" - -/// The structure for source capabilities. -typedef struct +AUD_SilenceFactory::AUD_SilenceFactory() { - /// The source to apply the capability on. - AUD_Handle* handle; - - /// The value for the capability. - float value; -} AUD_SourceCaps; +} -#endif //AUD_SOURCECAPS +AUD_IReader* AUD_SilenceFactory::createReader() const +{ + return new AUD_SilenceReader(); +} diff --git a/intern/audaspace/FX/AUD_RectifyReader.h b/intern/audaspace/intern/AUD_SilenceFactory.h index afbe2e59cab..bc8a5b92727 100644 --- a/intern/audaspace/FX/AUD_RectifyReader.h +++ b/intern/audaspace/intern/AUD_SilenceFactory.h @@ -23,37 +23,28 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#ifndef AUD_RECTIFYREADER -#define AUD_RECTIFYREADER +#ifndef AUD_SILENCEFACTORY +#define AUD_SILENCEFACTORY -#include "AUD_EffectReader.h" -class AUD_Buffer; +#include "AUD_IFactory.h" /** - * This class reads another reader and rectifies it. + * This factory creates a reader that plays a sine tone. */ -class AUD_RectifyReader : public AUD_EffectReader +class AUD_SilenceFactory : public AUD_IFactory { private: - /** - * The playback buffer. - */ - AUD_Buffer *m_buffer; + // hide copy constructor and operator= + AUD_SilenceFactory(const AUD_SilenceFactory&); + AUD_SilenceFactory& operator=(const AUD_SilenceFactory&); public: /** - * Creates a new rectify reader. - * \param reader The reader to read from. - * \exception AUD_Exception Thrown if the reader specified is NULL. - */ - AUD_RectifyReader(AUD_IReader* reader); - - /** - * Destroys the reader. + * Creates a new silence factory. */ - virtual ~AUD_RectifyReader(); + AUD_SilenceFactory(); - virtual void read(int & length, sample_t* & buffer); + virtual AUD_IReader* createReader() const; }; -#endif //AUD_RECTIFYREADER +#endif //AUD_SILENCEFACTORY diff --git a/intern/audaspace/FX/AUD_SquareReader.cpp b/intern/audaspace/intern/AUD_SilenceReader.cpp index 2d4dc52fe27..5243286c5e4 100644 --- a/intern/audaspace/FX/AUD_SquareReader.cpp +++ b/intern/audaspace/intern/AUD_SilenceReader.cpp @@ -23,41 +23,52 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#include "AUD_SquareReader.h" -#include "AUD_Buffer.h" +#include "AUD_SilenceReader.h" #include <cstring> -AUD_SquareReader::AUD_SquareReader(AUD_IReader* reader, float threshold) : - AUD_EffectReader(reader), - m_threshold(threshold) +AUD_SilenceReader::AUD_SilenceReader() : + m_position(0) { - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } -AUD_SquareReader::~AUD_SquareReader() +bool AUD_SilenceReader::isSeekable() const { - delete m_buffer; AUD_DELETE("buffer") + return true; } -void AUD_SquareReader::read(int & length, sample_t* & buffer) +void AUD_SilenceReader::seek(int position) { - sample_t* buf; - AUD_Specs specs = m_reader->getSpecs(); + m_position = position; +} - m_reader->read(length, buf); - if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs)) - m_buffer->resize(length * AUD_SAMPLE_SIZE(specs)); +int AUD_SilenceReader::getLength() const +{ + return -1; +} + +int AUD_SilenceReader::getPosition() const +{ + return m_position; +} - buffer = m_buffer->getBuffer(); +AUD_Specs AUD_SilenceReader::getSpecs() const +{ + AUD_Specs specs; + specs.rate = AUD_RATE_44100; + specs.channels = AUD_CHANNELS_MONO; + return specs; +} - for(int i = 0; i < length * specs.channels; i++) +void AUD_SilenceReader::read(int & length, sample_t* & buffer) +{ + // resize if necessary + if(m_buffer.getSize() < length * sizeof(sample_t)) { - if(buf[i] >= m_threshold) - buffer[i] = 1.0f; - else if(buf[i] <= -m_threshold) - buffer[i] = -1.0f; - else - buffer[i] = 0.0f; + m_buffer.resize(length * sizeof(sample_t)); + memset(m_buffer.getBuffer(), 0, m_buffer.getSize()); } + + buffer = m_buffer.getBuffer(); + m_position += length; } diff --git a/intern/audaspace/FX/AUD_LowpassReader.h b/intern/audaspace/intern/AUD_SilenceReader.h index a490ba52c1c..a8b959b5309 100644 --- a/intern/audaspace/FX/AUD_LowpassReader.h +++ b/intern/audaspace/intern/AUD_SilenceReader.h @@ -23,61 +23,49 @@ * ***** END LGPL LICENSE BLOCK ***** */ -#ifndef AUD_LOWPASSREADER -#define AUD_LOWPASSREADER +#ifndef AUD_SILENCEREADER +#define AUD_SILENCEREADER -#include "AUD_EffectReader.h" -class AUD_Buffer; - -#define AUD_LOWPASS_ORDER 3 +#include "AUD_IReader.h" +#include "AUD_Buffer.h" /** - * This class represents a lowpass filter. + * This class is used for sine tone playback. + * The output format is in the 16 bit format and stereo, the sample rate can be + * specified. + * As the two channels both play the same the output could also be mono, but + * in most cases this will result in having to resample for output, so stereo + * sound is created directly. */ -class AUD_LowpassReader : public AUD_EffectReader +class AUD_SilenceReader : public AUD_IReader { private: /** - * The playback buffer. - */ - AUD_Buffer *m_buffer; - - /** - * The last out values buffer. - */ - AUD_Buffer *m_outvalues; - - /** - * The last in values buffer. - */ - AUD_Buffer *m_invalues; - - /** - * The position for buffer cycling. + * The current position in samples. */ int m_position; /** - * Filter coefficients. + * The playback buffer. */ - float m_coeff[2][AUD_LOWPASS_ORDER]; + AUD_Buffer m_buffer; -public: - /** - * Creates a new lowpass reader. - * \param reader The reader to read from. - * \param frequency The cutoff frequency. - * \param Q The Q factor. - * \exception AUD_Exception Thrown if the reader specified is NULL. - */ - AUD_LowpassReader(AUD_IReader* reader, float frequency, float Q); + // hide copy constructor and operator= + AUD_SilenceReader(const AUD_SilenceReader&); + AUD_SilenceReader& operator=(const AUD_SilenceReader&); +public: /** - * Destroys the reader. + * Creates a new reader. */ - virtual ~AUD_LowpassReader(); + AUD_SilenceReader(); + virtual bool isSeekable() const; + virtual void seek(int position); + virtual int getLength() const; + virtual int getPosition() const; + virtual AUD_Specs getSpecs() const; virtual void read(int & length, sample_t* & buffer); }; -#endif //AUD_LOWPASSREADER +#endif //AUD_SILENCEREADER diff --git a/intern/audaspace/intern/AUD_SinusFactory.cpp b/intern/audaspace/intern/AUD_SinusFactory.cpp index ae878b9df60..3c8e5ccc567 100644 --- a/intern/audaspace/intern/AUD_SinusFactory.cpp +++ b/intern/audaspace/intern/AUD_SinusFactory.cpp @@ -27,25 +27,18 @@ #include "AUD_SinusReader.h" #include "AUD_Space.h" -AUD_SinusFactory::AUD_SinusFactory(double frequency, AUD_SampleRate sampleRate) +AUD_SinusFactory::AUD_SinusFactory(float frequency, AUD_SampleRate sampleRate) : + m_frequency(frequency), + m_sampleRate(sampleRate) { - m_frequency = frequency; - m_sampleRate = sampleRate; } -AUD_IReader* AUD_SinusFactory::createReader() -{ - AUD_IReader* reader = new AUD_SinusReader(m_frequency, m_sampleRate); - AUD_NEW("reader") - return reader; -} - -double AUD_SinusFactory::getFrequency() +float AUD_SinusFactory::getFrequency() const { return m_frequency; } -void AUD_SinusFactory::setFrequency(double frequency) +AUD_IReader* AUD_SinusFactory::createReader() const { - m_frequency = frequency; + return new AUD_SinusReader(m_frequency, m_sampleRate); } diff --git a/intern/audaspace/intern/AUD_SinusFactory.h b/intern/audaspace/intern/AUD_SinusFactory.h index ffb36e741b9..2c5965e11f0 100644 --- a/intern/audaspace/intern/AUD_SinusFactory.h +++ b/intern/audaspace/intern/AUD_SinusFactory.h @@ -37,12 +37,16 @@ private: /** * The frequence of the sine wave. */ - double m_frequency; + const float m_frequency; /** * The target sample rate for output. */ - AUD_SampleRate m_sampleRate; + const AUD_SampleRate m_sampleRate; + + // hide copy constructor and operator= + AUD_SinusFactory(const AUD_SinusFactory&); + AUD_SinusFactory& operator=(const AUD_SinusFactory&); public: /** @@ -50,21 +54,15 @@ public: * \param frequency The desired frequency. * \param sampleRate The target sample rate for playback. */ - AUD_SinusFactory(double frequency, + AUD_SinusFactory(float frequency, AUD_SampleRate sampleRate = AUD_RATE_44100); /** * Returns the frequency of the sine wave. */ - double getFrequency(); - - /** - * Sets the frequency. - * \param frequency The new frequency. - */ - void setFrequency(double frequency); + float getFrequency() const; - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_SINUSFACTORY diff --git a/intern/audaspace/intern/AUD_SinusReader.cpp b/intern/audaspace/intern/AUD_SinusReader.cpp index c52513d5d2e..e810c576a5c 100644 --- a/intern/audaspace/intern/AUD_SinusReader.cpp +++ b/intern/audaspace/intern/AUD_SinusReader.cpp @@ -24,7 +24,6 @@ */ #include "AUD_SinusReader.h" -#include "AUD_Buffer.h" #include <cmath> @@ -32,20 +31,14 @@ #define M_PI 3.14159265358979323846 #endif -AUD_SinusReader::AUD_SinusReader(double frequency, AUD_SampleRate sampleRate) +AUD_SinusReader::AUD_SinusReader(float frequency, AUD_SampleRate sampleRate) : + m_frequency(frequency), + m_position(0), + m_sampleRate(sampleRate) { - m_frequency = frequency; - m_position = 0; - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") - m_sampleRate = sampleRate; } -AUD_SinusReader::~AUD_SinusReader() -{ - delete m_buffer; AUD_DELETE("buffer") -} - -bool AUD_SinusReader::isSeekable() +bool AUD_SinusReader::isSeekable() const { return true; } @@ -55,17 +48,17 @@ void AUD_SinusReader::seek(int position) m_position = position; } -int AUD_SinusReader::getLength() +int AUD_SinusReader::getLength() const { return -1; } -int AUD_SinusReader::getPosition() +int AUD_SinusReader::getPosition() const { return m_position; } -AUD_Specs AUD_SinusReader::getSpecs() +AUD_Specs AUD_SinusReader::getSpecs() const { AUD_Specs specs; specs.rate = m_sampleRate; @@ -73,27 +66,17 @@ AUD_Specs AUD_SinusReader::getSpecs() return specs; } -AUD_ReaderType AUD_SinusReader::getType() -{ - return AUD_TYPE_STREAM; -} - -bool AUD_SinusReader::notify(AUD_Message &message) -{ - return false; -} - void AUD_SinusReader::read(int & length, sample_t* & buffer) { // resize if necessary - if(m_buffer->getSize() < length * sizeof(sample_t)) - m_buffer->resize(length * sizeof(sample_t)); + if(m_buffer.getSize() < length * sizeof(sample_t)) + m_buffer.resize(length * sizeof(sample_t)); // fill with sine data - buffer = m_buffer->getBuffer(); + buffer = m_buffer.getBuffer(); for(int i = 0; i < length; i++) { - buffer[i] = sin((m_position + i) * 2.0f * M_PI * m_frequency / + buffer[i] = sin((m_position + i) * 2 * M_PI * m_frequency / (float)m_sampleRate); } diff --git a/intern/audaspace/intern/AUD_SinusReader.h b/intern/audaspace/intern/AUD_SinusReader.h index cb060dd8a43..4b88ed15db1 100644 --- a/intern/audaspace/intern/AUD_SinusReader.h +++ b/intern/audaspace/intern/AUD_SinusReader.h @@ -27,7 +27,7 @@ #define AUD_SINUSREADER #include "AUD_IReader.h" -class AUD_Buffer; +#include "AUD_Buffer.h" /** * This class is used for sine tone playback. @@ -43,7 +43,7 @@ private: /** * The frequency of the sine wave. */ - double m_frequency; + const float m_frequency; /** * The current position in samples. @@ -53,12 +53,16 @@ private: /** * The playback buffer. */ - AUD_Buffer* m_buffer; + AUD_Buffer m_buffer; /** * The sample rate for the output. */ - AUD_SampleRate m_sampleRate; + const AUD_SampleRate m_sampleRate; + + // hide copy constructor and operator= + AUD_SinusReader(const AUD_SinusReader&); + AUD_SinusReader& operator=(const AUD_SinusReader&); public: /** @@ -66,20 +70,13 @@ public: * \param frequency The frequency of the sine wave. * \param sampleRate The output sample rate. */ - AUD_SinusReader(double frequency, AUD_SampleRate sampleRate); - - /** - * Destroys the reader. - */ - virtual ~AUD_SinusReader(); + AUD_SinusReader(float frequency, AUD_SampleRate sampleRate); - virtual bool isSeekable(); + virtual bool isSeekable() const; virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); - virtual AUD_Specs getSpecs(); - virtual AUD_ReaderType getType(); - virtual bool notify(AUD_Message &message); + virtual int getLength() const; + virtual int getPosition() const; + virtual AUD_Specs getSpecs() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp index 5a3f25fba07..0c0206608e3 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp +++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp @@ -25,11 +25,11 @@ #include "AUD_SoftwareDevice.h" #include "AUD_IReader.h" -#include "AUD_Mixer.h" +#include "AUD_DefaultMixer.h" #include "AUD_IFactory.h" -#include "AUD_SourceCaps.h" #include <cstring> +#include <limits> /// Saves the data for playback. struct AUD_SoftwareHandle : AUD_Handle @@ -42,18 +42,24 @@ struct AUD_SoftwareHandle : AUD_Handle /// The volume of the source. float volume; + + /// The loop count of the source. + int loopcount; + + /// The stop callback. + stopCallback stop; + + /// Stop callback data. + void* stop_data; }; typedef std::list<AUD_SoftwareHandle*>::iterator AUD_HandleIterator; void AUD_SoftwareDevice::create() { - m_playingSounds = new std::list<AUD_SoftwareHandle*>(); AUD_NEW("list") - m_pausedSounds = new std::list<AUD_SoftwareHandle*>(); AUD_NEW("list") m_playback = false; m_volume = 1.0f; - m_mixer = new AUD_Mixer(); AUD_NEW("mixer") - m_mixer->setSpecs(m_specs); + m_mixer = new AUD_DefaultMixer(m_specs); pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); @@ -69,25 +75,27 @@ void AUD_SoftwareDevice::destroy() if(m_playback) playing(m_playback = false); - delete m_mixer; AUD_DELETE("mixer") + delete m_mixer; + + AUD_SoftwareHandle* handle; // delete all playing sounds - while(m_playingSounds->begin() != m_playingSounds->end()) + while(!m_playingSounds.empty()) { - delete (*(m_playingSounds->begin()))->reader; AUD_DELETE("reader") - delete *(m_playingSounds->begin()); AUD_DELETE("handle") - m_playingSounds->erase(m_playingSounds->begin()); + handle = m_playingSounds.front(); + m_playingSounds.pop_front(); + delete handle->reader; + delete handle; } - delete m_playingSounds; AUD_DELETE("list") // delete all paused sounds - while(m_pausedSounds->begin() != m_pausedSounds->end()) + while(!m_pausedSounds.empty()) { - delete (*(m_pausedSounds->begin()))->reader; AUD_DELETE("reader") - delete *(m_pausedSounds->begin()); AUD_DELETE("handle") - m_pausedSounds->erase(m_pausedSounds->begin()); + handle = m_pausedSounds.front(); + m_pausedSounds.pop_front(); + delete handle->reader; + delete handle; } - delete m_pausedSounds; AUD_DELETE("list") pthread_mutex_destroy(&m_mutex); } @@ -99,12 +107,16 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length) { AUD_SoftwareHandle* sound; int len; + int pos; sample_t* buf; std::list<AUD_SoftwareHandle*> stopSounds; + std::list<AUD_Buffer*> tempBufs; + AUD_Buffer* tempbuf; + int samplesize = AUD_SAMPLE_SIZE(m_specs); // for all sounds - AUD_HandleIterator it = m_playingSounds->begin(); - while(it != m_playingSounds->end()) + AUD_HandleIterator it = m_playingSounds.begin(); + while(it != m_playingSounds.end()) { sound = *it; // increment the iterator to make sure it's valid, @@ -112,14 +124,42 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length) ++it; // get the buffer from the source + pos = 0; len = length; sound->reader->read(len, buf); - m_mixer->add(buf, 0, len, sound->volume); + // in case of looping + while(pos + len < length && sound->loopcount) + { + tempbuf = new AUD_Buffer(len * samplesize); + memcpy(tempbuf->getBuffer(), buf, len * samplesize); + tempBufs.push_back(tempbuf); + m_mixer->add(tempbuf->getBuffer(), pos, len, sound->volume); + + pos += len; + + if(sound->loopcount > 0) + sound->loopcount--; + + sound->reader->seek(0); + + len = length - pos; + sound->reader->read(len, buf); + + // prevent endless loop + if(!len) + break; + } + + m_mixer->add(buf, pos, len, sound->volume); + pos += len; // in case the end of the sound is reached - if(len < length) + if(pos < length) { + if(sound->stop) + sound->stop(sound->stop_data); + if(sound->keep) pause(sound); else @@ -130,12 +170,20 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length) // superpose m_mixer->superpose(buffer, length, m_volume); + // cleanup while(!stopSounds.empty()) { sound = stopSounds.front(); stopSounds.pop_front(); stop(sound); } + + while(!tempBufs.empty()) + { + tempbuf = tempBufs.front(); + tempBufs.pop_front(); + delete tempbuf; + } } unlock(); @@ -143,18 +191,18 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length) bool AUD_SoftwareDevice::isValid(AUD_Handle* handle) { - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) + for(AUD_HandleIterator i = m_playingSounds.begin(); + i != m_playingSounds.end(); i++) if(*i == handle) return true; - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) + for(AUD_HandleIterator i = m_pausedSounds.begin(); + i != m_pausedSounds.end(); i++) if(*i == handle) return true; return false; } -AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() +AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const { return m_specs; } @@ -163,24 +211,22 @@ AUD_Handle* AUD_SoftwareDevice::play(AUD_IFactory* factory, bool keep) { AUD_IReader* reader = factory->createReader(); - if(reader == NULL) - AUD_THROW(AUD_ERROR_READER); - // prepare the reader reader = m_mixer->prepare(reader); if(reader == NULL) return NULL; - AUD_Specs rs = reader->getSpecs(); - // play sound - AUD_SoftwareHandle* sound = new AUD_SoftwareHandle; AUD_NEW("handle") + AUD_SoftwareHandle* sound = new AUD_SoftwareHandle; sound->keep = keep; sound->reader = reader; sound->volume = 1.0f; + sound->loopcount = 0; + sound->stop = NULL; + sound->stop_data = NULL; lock(); - m_playingSounds->push_back(sound); + m_playingSounds.push_back(sound); if(!m_playback) playing(m_playback = true); @@ -196,14 +242,14 @@ bool AUD_SoftwareDevice::pause(AUD_Handle* handle) lock(); // only songs that are played can be paused - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) + for(AUD_HandleIterator i = m_playingSounds.begin(); + i != m_playingSounds.end(); i++) { if(*i == handle) { - m_pausedSounds->push_back(*i); - m_playingSounds->erase(i); - if(m_playingSounds->empty()) + m_pausedSounds.push_back(*i); + m_playingSounds.erase(i); + if(m_playingSounds.empty()) playing(m_playback = false); result = true; break; @@ -222,13 +268,13 @@ bool AUD_SoftwareDevice::resume(AUD_Handle* handle) lock(); // only songs that are paused can be resumed - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) + for(AUD_HandleIterator i = m_pausedSounds.begin(); + i != m_pausedSounds.end(); i++) { if(*i == handle) { - m_playingSounds->push_back(*i); - m_pausedSounds->erase(i); + m_playingSounds.push_back(*i); + m_pausedSounds.erase(i); if(!m_playback) playing(m_playback = true); result = true; @@ -247,15 +293,15 @@ bool AUD_SoftwareDevice::stop(AUD_Handle* handle) lock(); - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) + for(AUD_HandleIterator i = m_playingSounds.begin(); + i != m_playingSounds.end(); i++) { if(*i == handle) { - delete (*i)->reader; AUD_DELETE("reader") - delete *i; AUD_DELETE("handle") - m_playingSounds->erase(i); - if(m_playingSounds->empty()) + delete (*i)->reader; + delete *i; + m_playingSounds.erase(i); + if(m_playingSounds.empty()) playing(m_playback = false); result = true; break; @@ -263,14 +309,14 @@ bool AUD_SoftwareDevice::stop(AUD_Handle* handle) } if(!result) { - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) + for(AUD_HandleIterator i = m_pausedSounds.begin(); + i != m_pausedSounds.end(); i++) { if(*i == handle) { - delete (*i)->reader; AUD_DELETE("reader") - delete *i; AUD_DELETE("handle") - m_pausedSounds->erase(i); + delete (*i)->reader; + delete *i; + m_pausedSounds.erase(i); result = true; break; } @@ -282,41 +328,34 @@ bool AUD_SoftwareDevice::stop(AUD_Handle* handle) return result; } -bool AUD_SoftwareDevice::setKeep(AUD_Handle* handle, bool keep) +bool AUD_SoftwareDevice::getKeep(AUD_Handle* handle) { bool result = false; lock(); if(isValid(handle)) - { - ((AUD_SoftwareHandle*)handle)->keep = keep; - result = true; - } + result = ((AUD_SoftwareHandle*)handle)->keep; unlock(); return result; } -bool AUD_SoftwareDevice::sendMessage(AUD_Handle* handle, AUD_Message &message) +bool AUD_SoftwareDevice::setKeep(AUD_Handle* handle, bool keep) { - lock(); - bool result = false; - if(handle == 0) + lock(); + + if(isValid(handle)) { - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) - result |= (*i)->reader->notify(message); - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) - result |= (*i)->reader->notify(message); + ((AUD_SoftwareHandle*)handle)->keep = keep; + result = true; } - else if(isValid(handle)) - result = ((AUD_SoftwareHandle*)handle)->reader->notify(message); + unlock(); + return result; } @@ -361,8 +400,8 @@ AUD_Status AUD_SoftwareDevice::getStatus(AUD_Handle* handle) lock(); - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) + for(AUD_HandleIterator i = m_playingSounds.begin(); + i != m_playingSounds.end(); i++) { if(*i == handle) { @@ -372,8 +411,8 @@ AUD_Status AUD_SoftwareDevice::getStatus(AUD_Handle* handle) } if(status == AUD_STATUS_INVALID) { - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) + for(AUD_HandleIterator i = m_pausedSounds.begin(); + i != m_pausedSounds.end(); i++) { if(*i == handle) { @@ -398,77 +437,76 @@ void AUD_SoftwareDevice::unlock() pthread_mutex_unlock(&m_mutex); } -bool AUD_SoftwareDevice::checkCapability(int capability) +float AUD_SoftwareDevice::getVolume() const { - return capability == AUD_CAPS_SOFTWARE_DEVICE || - capability == AUD_CAPS_VOLUME || - capability == AUD_CAPS_SOURCE_VOLUME; + return m_volume; } -bool AUD_SoftwareDevice::setCapability(int capability, void *value) +void AUD_SoftwareDevice::setVolume(float volume) { - bool result = false; + m_volume = volume; +} - switch(capability) - { - case AUD_CAPS_VOLUME: - lock(); - m_volume = *((float*)value); - if(m_volume > 1.0f) - m_volume = 1.0f; - else if(m_volume < 0.0f) - m_volume = 0.0f; - unlock(); - return true; - case AUD_CAPS_SOURCE_VOLUME: - { - AUD_SourceCaps* caps = (AUD_SourceCaps*) value; - lock(); - if(isValid(caps->handle)) - { - AUD_SoftwareHandle* handle = (AUD_SoftwareHandle*)caps->handle; - handle->volume = caps->value; - if(handle->volume > 1.0f) - handle->volume = 1.0f; - else if(handle->volume < 0.0f) - handle->volume = 0.0f; - result = true; - } - unlock(); - } - break; - } +float AUD_SoftwareDevice::getVolume(AUD_Handle* handle) +{ + lock(); + float result = std::numeric_limits<float>::quiet_NaN(); + if(isValid(handle)) + result = ((AUD_SoftwareHandle*)handle)->volume; + unlock(); + return result; +} - return result;; +bool AUD_SoftwareDevice::setVolume(AUD_Handle* handle, float volume) +{ + lock(); + bool result = isValid(handle); + if(result) + ((AUD_SoftwareHandle*)handle)->volume = volume; + unlock(); + return result; } -bool AUD_SoftwareDevice::getCapability(int capability, void *value) +float AUD_SoftwareDevice::getPitch(AUD_Handle* handle) { - bool result = false; + return std::numeric_limits<float>::quiet_NaN(); +} - switch(capability) - { - case AUD_CAPS_VOLUME: - lock(); - *((float*)value) = m_volume; - unlock(); - return true; - case AUD_CAPS_SOURCE_VOLUME: - { - AUD_SourceCaps* caps = (AUD_SourceCaps*) value; +bool AUD_SoftwareDevice::setPitch(AUD_Handle* handle, float pitch) +{ + return false; +} - lock(); +int AUD_SoftwareDevice::getLoopCount(AUD_Handle* handle) +{ + lock(); + int result = 0; + if(isValid(handle)) + result = ((AUD_SoftwareHandle*)handle)->loopcount; + unlock(); + return result; +} - if(isValid(caps->handle)) - { - caps->value = ((AUD_SoftwareHandle*)caps->handle)->volume; - result = true; - } +bool AUD_SoftwareDevice::setLoopCount(AUD_Handle* handle, int count) +{ + lock(); + bool result = isValid(handle); + if(result) + ((AUD_SoftwareHandle*)handle)->loopcount = count; + unlock(); + return result; +} - unlock(); - } - break; +bool AUD_SoftwareDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data) +{ + lock(); + bool result = isValid(handle); + if(result) + { + AUD_SoftwareHandle* h = (AUD_SoftwareHandle*)handle; + h->stop = callback; + h->stop_data = data; } - + unlock(); return result; } diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h index a12fddb1e00..93b0f165c7a 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.h +++ b/intern/audaspace/intern/AUD_SoftwareDevice.h @@ -29,6 +29,7 @@ #include "AUD_IDevice.h" struct AUD_SoftwareHandle; class AUD_Mixer; +class AUD_Buffer; #include <list> #include <pthread.h> @@ -81,12 +82,12 @@ private: /** * The list of sounds that are currently playing. */ - std::list<AUD_SoftwareHandle*>* m_playingSounds; + std::list<AUD_SoftwareHandle*> m_playingSounds; /** * The list of sounds that are currently paused. */ - std::list<AUD_SoftwareHandle*>* m_pausedSounds; + std::list<AUD_SoftwareHandle*> m_pausedSounds; /** * Whether there is currently playback. @@ -111,21 +112,27 @@ private: bool isValid(AUD_Handle* handle); public: - virtual AUD_DeviceSpecs getSpecs(); + virtual AUD_DeviceSpecs getSpecs() const; virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false); virtual bool pause(AUD_Handle* handle); virtual bool resume(AUD_Handle* handle); virtual bool stop(AUD_Handle* handle); + virtual bool getKeep(AUD_Handle* handle); virtual bool setKeep(AUD_Handle* handle, bool keep); - virtual bool sendMessage(AUD_Handle* handle, AUD_Message &message); virtual bool seek(AUD_Handle* handle, float position); virtual float getPosition(AUD_Handle* handle); virtual AUD_Status getStatus(AUD_Handle* handle); virtual void lock(); virtual void unlock(); - virtual bool checkCapability(int capability); - virtual bool setCapability(int capability, void *value); - virtual bool getCapability(int capability, void *value); + virtual float getVolume() const; + virtual void setVolume(float volume); + virtual float getVolume(AUD_Handle* handle); + virtual bool setVolume(AUD_Handle* handle, float volume); + virtual float getPitch(AUD_Handle* handle); + virtual bool setPitch(AUD_Handle* handle, float pitch); + virtual int getLoopCount(AUD_Handle* handle); + virtual bool setLoopCount(AUD_Handle* handle, int count); + virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = NULL, void* data = NULL); }; #endif //AUD_SOFTWAREDEVICE diff --git a/intern/audaspace/intern/AUD_Space.h b/intern/audaspace/intern/AUD_Space.h index 9e857ce73b0..e411b831d52 100644 --- a/intern/audaspace/intern/AUD_Space.h +++ b/intern/audaspace/intern/AUD_Space.h @@ -33,7 +33,7 @@ /// The size of a sample in the specified format in bytes. #define AUD_SAMPLE_SIZE(specs) (specs.channels * sizeof(sample_t)) /// Throws a AUD_Exception with the provided error code. -#define AUD_THROW(exception) { AUD_Exception e; e.error = exception; throw e; } +#define AUD_THROW(exception, errorstr) { AUD_Exception e; e.error = exception; e.str = errorstr; throw e; } /// Returns the smaller of the two values. #define AUD_MIN(a, b) (((a) < (b)) ? (a) : (b)) @@ -47,64 +47,6 @@ /// The default playback buffer size of a device. #define AUD_DEFAULT_BUFFER_SIZE 1024 -// Capability defines - -/// This capability checks whether a device is a 3D device. See AUD_I3DDevice.h. -#define AUD_CAPS_3D_DEVICE 0x0001 - -/** - * This capability checks whether a device is a software device. See - * AUD_SoftwareDevice. - */ -#define AUD_CAPS_SOFTWARE_DEVICE 0x0002 - -/** - * This capability enables the user to set the overall volume of the device. - * You can set and get it with the pointer pointing to a float value between - * 0.0 (muted) and 1.0 (maximum volume). - */ -#define AUD_CAPS_VOLUME 0x0101 - -/** - * This capability enables the user to set the volume of a source. - * You can set and get it with the pointer pointing to a AUD_SourceValue - * structure defined in AUD_SourceCaps.h. - */ -#define AUD_CAPS_SOURCE_VOLUME 0x1001 - -/** - * This capability enables the user to set the pitch of a source. - * You can set and get it with the pointer pointing to a AUD_SourceValue - * structure defined in AUD_SourceCaps.h. - */ -#define AUD_CAPS_SOURCE_PITCH 0x1002 - -/** - * This capability enables the user to buffer a factory into the device. - * Setting with the factory as pointer loads the factory into a device internal - * buffer. Play function calls with the buffered factory as argument result in - * the internal buffer being played back, so there's no reader created, what - * also results in not being able to send messages to that handle. - * A repeated call with the same factory doesn't do anything. - * A set call with a NULL pointer results in all buffered factories being - * deleted. - * \note This is only possible with factories that create readers of the buffer - * type. - */ -#define AUD_CAPS_BUFFERED_FACTORY 0x2001 - -// Used for debugging memory leaks. -//#define AUD_DEBUG_MEMORY - -#ifdef AUD_DEBUG_MEMORY -extern int AUD_References(int count, const char* text); -#define AUD_NEW(text) AUD_References(1, text); -#define AUD_DELETE(text) AUD_References(-1, text); -#else -#define AUD_NEW(text) -#define AUD_DELETE(text) -#endif - /** * The format of a sample. * The last 4 bit save the byte count of the format. @@ -154,17 +96,6 @@ typedef enum AUD_RATE_192000 = 192000 /// 192000 Hz. } AUD_SampleRate; -/** - * Type of a reader. - * @see AUD_IReader for details. - */ -typedef enum -{ - AUD_TYPE_INVALID = 0, /// Invalid reader type. - AUD_TYPE_BUFFER, /// Reader reads from a buffer. - AUD_TYPE_STREAM /// Reader reads from a stream. -} AUD_ReaderType; - /// Status of a playback handle. typedef enum { @@ -177,23 +108,16 @@ typedef enum typedef enum { AUD_NO_ERROR = 0, - AUD_ERROR_READER, - AUD_ERROR_FACTORY, + AUD_ERROR_SPECS, + AUD_ERROR_PROPS, AUD_ERROR_FILE, + AUD_ERROR_SRC, AUD_ERROR_FFMPEG, - AUD_ERROR_SDL, AUD_ERROR_OPENAL, - AUD_ERROR_JACK + AUD_ERROR_SDL, + AUD_ERROR_JACK, } AUD_Error; -/// Message codes. -typedef enum -{ - AUD_MSG_INVALID = 0, /// Invalid message. - AUD_MSG_LOOP, /// Loop reader message. - AUD_MSG_VOLUME /// Volume reader message. -} AUD_MessageType; - /// Fading types. typedef enum { @@ -201,39 +125,17 @@ typedef enum AUD_FADE_OUT } AUD_FadeType; -/// 3D device settings. -typedef enum -{ - AUD_3DS_NONE, /// No setting. - AUD_3DS_SPEED_OF_SOUND, /// Speed of sound. - AUD_3DS_DOPPLER_FACTOR, /// Doppler factor. - AUD_3DS_DISTANCE_MODEL /// Distance model. -} AUD_3DSetting; - /// Possible distance models for the 3D device. -#define AUD_DISTANCE_MODEL_NONE 0.0f -#define AUD_DISTANCE_MODEL_INVERSE 1.0f -#define AUD_DISTANCE_MODEL_INVERSE_CLAMPED 2.0f -#define AUD_DISTANCE_MODEL_LINEAR 3.0f -#define AUD_DISTANCE_MODEL_LINEAR_CLAMPED 4.0f -#define AUD_DISTANCE_MODEL_EXPONENT 5.0f -#define AUD_DISTANCE_MODEL_EXPONENT_CLAMPED 6.0f - -/// 3D source settings. typedef enum { - AUD_3DSS_NONE, /// No setting. - AUD_3DSS_IS_RELATIVE, /// > 0 tells that the sound source is - /// relative to the listener - AUD_3DSS_MIN_GAIN, /// Minimum gain. - AUD_3DSS_MAX_GAIN, /// Maximum gain. - AUD_3DSS_REFERENCE_DISTANCE, /// Reference distance. - AUD_3DSS_MAX_DISTANCE, /// Maximum distance. - AUD_3DSS_ROLLOFF_FACTOR, /// Rolloff factor. - AUD_3DSS_CONE_INNER_ANGLE, /// Cone inner angle. - AUD_3DSS_CONE_OUTER_ANGLE, /// Cone outer angle. - AUD_3DSS_CONE_OUTER_GAIN /// Cone outer gain. -} AUD_3DSourceSetting; + AUD_DISTANCE_MODEL_INVALID = 0, + AUD_DISTANCE_MODEL_INVERSE, + AUD_DISTANCE_MODEL_INVERSE_CLAMPED, + AUD_DISTANCE_MODEL_LINEAR, + AUD_DISTANCE_MODEL_LINEAR_CLAMPED, + AUD_DISTANCE_MODEL_EXPONENT, + AUD_DISTANCE_MODEL_EXPONENT_CLAMPED, +} AUD_DistanceModel; /// Sample type.(float samples) typedef float sample_t; @@ -280,42 +182,12 @@ typedef struct */ AUD_Error error; - // void* userData; - for the case it is needed someday -} AUD_Exception; - -/// Message structure. -typedef struct -{ /** - * The message type. + * Error string. */ - AUD_MessageType type; - - union - { - // loop reader - struct - { - int loopcount; - float time; - }; - - // volume reader - float volume; - }; -} AUD_Message; + const char* str; -/// Handle structure, for inherition. -typedef struct -{ - /// x, y and z coordinates of the object. - float position[3]; - - /// x, y and z coordinates telling the velocity and direction of the object. - float velocity[3]; - - /// 3x3 matrix telling the orientation of the object. - float orientation[9]; -} AUD_3DData; + // void* userData; - for the case it is needed someday +} AUD_Exception; #endif //AUD_SPACE diff --git a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp index cb97e6125fb..c1eb8161e30 100644 --- a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp +++ b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp @@ -29,15 +29,12 @@ #include <cstring> -AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory) +AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory) : + m_buffer(new AUD_Buffer()) { AUD_IReader* reader = factory->createReader(); - if(reader == NULL) - AUD_THROW(AUD_ERROR_READER); - m_specs = reader->getSpecs(); - m_buffer = AUD_Reference<AUD_Buffer>(new AUD_Buffer()); AUD_NEW("buffer") int sample_size = AUD_SAMPLE_SIZE(m_specs); int length; @@ -68,13 +65,11 @@ AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory) index += length; } - m_buffer.get()->resize(index*sample_size, true); - delete reader; AUD_DELETE("reader") + m_buffer.get()->resize(index * sample_size, true); + delete reader; } -AUD_IReader* AUD_StreamBufferFactory::createReader() +AUD_IReader* AUD_StreamBufferFactory::createReader() const { - AUD_IReader* reader = new AUD_BufferReader(m_buffer, m_specs); - AUD_NEW("reader") - return reader; + return new AUD_BufferReader(m_buffer, m_specs); } diff --git a/intern/audaspace/intern/AUD_StreamBufferFactory.h b/intern/audaspace/intern/AUD_StreamBufferFactory.h index eda06f6c10c..d0cf1001e5c 100644 --- a/intern/audaspace/intern/AUD_StreamBufferFactory.h +++ b/intern/audaspace/intern/AUD_StreamBufferFactory.h @@ -47,6 +47,10 @@ private: */ AUD_Specs m_specs; + // hide copy constructor and operator= + AUD_StreamBufferFactory(const AUD_StreamBufferFactory&); + AUD_StreamBufferFactory& operator=(const AUD_StreamBufferFactory&); + public: /** * Creates the factory and reads the reader created by the factory supplied @@ -56,7 +60,7 @@ public: */ AUD_StreamBufferFactory(AUD_IFactory* factory); - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_STREAMBUFFERFACTORY diff --git a/intern/audaspace/jack/AUD_JackDevice.cpp b/intern/audaspace/jack/AUD_JackDevice.cpp index ae7725be81c..5aa3f7b3fc1 100644 --- a/intern/audaspace/jack/AUD_JackDevice.cpp +++ b/intern/audaspace/jack/AUD_JackDevice.cpp @@ -26,7 +26,6 @@ #include "AUD_Mixer.h" #include "AUD_JackDevice.h" #include "AUD_IReader.h" -#include "AUD_Buffer.h" #include <stdio.h> #include <stdlib.h> @@ -43,8 +42,8 @@ void AUD_JackDevice::updateRingBuffers() unsigned int samplesize = AUD_SAMPLE_SIZE(m_specs); unsigned int i, j; unsigned int channels = m_specs.channels; - sample_t* buffer = m_buffer->getBuffer(); - float* deinterleave = m_deinterleavebuf->getBuffer(); + sample_t* buffer = m_buffer.getBuffer(); + float* deinterleave = m_deinterleavebuf.getBuffer(); jack_transport_state_t state; jack_position_t position; @@ -173,7 +172,13 @@ void AUD_JackDevice::jack_shutdown(void *data) device->m_valid = false; } -AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize) +static const char* clientopen_error = "AUD_JackDevice: Couldn't connect to " + "jack server."; +static const char* port_error = "AUD_JackDevice: Couldn't create output port."; +static const char* activate_error = "AUD_JackDevice: Couldn't activate the " + "client."; + +AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buffersize) { if(specs.channels == AUD_CHANNELS_INVALID) specs.channels = AUD_CHANNELS_STEREO; @@ -186,9 +191,9 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize) jack_status_t status; // open client - m_client = jack_client_open("Blender", options, &status); + m_client = jack_client_open(name.c_str(), options, &status); if(m_client == NULL) - AUD_THROW(AUD_ERROR_JACK); + AUD_THROW(AUD_ERROR_JACK, clientopen_error); // set callbacks jack_set_process_callback(m_client, AUD_JackDevice::jack_mix, this); @@ -196,7 +201,7 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize) jack_set_sync_callback(m_client, AUD_JackDevice::jack_sync, this); // register our output channels which are called ports in jack - m_ports = new jack_port_t*[m_specs.channels]; AUD_NEW("jack_port") + m_ports = new jack_port_t*[m_specs.channels]; try { @@ -208,25 +213,25 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize) JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if(m_ports[i] == NULL) - AUD_THROW(AUD_ERROR_JACK); + AUD_THROW(AUD_ERROR_JACK, port_error); } } - catch(AUD_Exception) + catch(AUD_Exception&) { jack_client_close(m_client); - delete[] m_ports; AUD_DELETE("jack_port") + delete[] m_ports; throw; } m_specs.rate = (AUD_SampleRate)jack_get_sample_rate(m_client); buffersize *= sizeof(sample_t); - m_ringbuffers = new jack_ringbuffer_t*[specs.channels]; AUD_NEW("jack_buffers") + m_ringbuffers = new jack_ringbuffer_t*[specs.channels]; for(unsigned int i = 0; i < specs.channels; i++) m_ringbuffers[i] = jack_ringbuffer_create(buffersize); buffersize *= specs.channels; - m_buffer = new AUD_Buffer(buffersize); AUD_NEW("buffer"); - m_deinterleavebuf = new AUD_Buffer(buffersize); AUD_NEW("buffer"); + m_deinterleavebuf.resize(buffersize); + m_buffer.resize(buffersize); create(); @@ -238,25 +243,19 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize) pthread_mutex_init(&m_mixingLock, NULL); pthread_cond_init(&m_mixingCondition, NULL); - try - { - // activate the client - if(jack_activate(m_client)) - AUD_THROW(AUD_ERROR_JACK); - } - catch(AUD_Exception) + // activate the client + if(jack_activate(m_client)) { jack_client_close(m_client); - delete[] m_ports; AUD_DELETE("jack_port") - delete m_buffer; AUD_DELETE("buffer"); - delete m_deinterleavebuf; AUD_DELETE("buffer"); + delete[] m_ports; for(unsigned int i = 0; i < specs.channels; i++) jack_ringbuffer_free(m_ringbuffers[i]); - delete[] m_ringbuffers; AUD_DELETE("jack_buffers") + delete[] m_ringbuffers; pthread_mutex_destroy(&m_mixingLock); pthread_cond_destroy(&m_mixingCondition); destroy(); - throw; + + AUD_THROW(AUD_ERROR_JACK, activate_error); } const char** ports = jack_get_ports(m_client, NULL, NULL, @@ -284,7 +283,7 @@ AUD_JackDevice::~AUD_JackDevice() jack_client_close(m_client); m_valid = false; - delete[] m_ports; AUD_DELETE("jack_port") + delete[] m_ports; pthread_mutex_lock(&m_mixingLock); pthread_cond_signal(&m_mixingCondition); @@ -293,11 +292,9 @@ AUD_JackDevice::~AUD_JackDevice() pthread_cond_destroy(&m_mixingCondition); pthread_mutex_destroy(&m_mixingLock); - delete m_buffer; AUD_DELETE("buffer"); - delete m_deinterleavebuf; AUD_DELETE("buffer"); for(unsigned int i = 0; i < m_specs.channels; i++) jack_ringbuffer_free(m_ringbuffers[i]); - delete[] m_ringbuffers; AUD_DELETE("jack_buffers") + delete[] m_ringbuffers; destroy(); } diff --git a/intern/audaspace/jack/AUD_JackDevice.h b/intern/audaspace/jack/AUD_JackDevice.h index 58e34978c1f..418992e0db1 100644 --- a/intern/audaspace/jack/AUD_JackDevice.h +++ b/intern/audaspace/jack/AUD_JackDevice.h @@ -28,7 +28,9 @@ #include "AUD_SoftwareDevice.h" -class AUD_Buffer; +#include "AUD_Buffer.h" + +#include <string> #include <jack.h> #include <ringbuffer.h> @@ -54,9 +56,12 @@ private: /** * The output buffer. */ - AUD_Buffer* m_buffer; + AUD_Buffer m_buffer; - AUD_Buffer* m_deinterleavebuf; + /** + * The deinterleaving buffer. + */ + AUD_Buffer m_deinterleavebuf; jack_ringbuffer_t** m_ringbuffers; @@ -114,16 +119,23 @@ private: void updateRingBuffers(); + // hide copy constructor and operator= + AUD_JackDevice(const AUD_JackDevice&); + AUD_JackDevice& operator=(const AUD_JackDevice&); + protected: virtual void playing(bool playing); public: /** * Creates a Jack client for audio output. - * \param specs The wanted audio specification, where only the channel count is important. + * \param name The client name. + * \param specs The wanted audio specification, where only the channel count + * is important. + * \param buffersize The size of the internal buffer. * \exception AUD_Exception Thrown if the audio device cannot be opened. */ - AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE); + AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE); /** * Closes the Jack client. diff --git a/intern/audaspace/sndfile/AUD_SndFileFactory.cpp b/intern/audaspace/sndfile/AUD_SndFileFactory.cpp index bac6dc321f4..d8ea7006073 100644 --- a/intern/audaspace/sndfile/AUD_SndFileFactory.cpp +++ b/intern/audaspace/sndfile/AUD_SndFileFactory.cpp @@ -29,39 +29,21 @@ #include <cstring> -AUD_SndFileFactory::AUD_SndFileFactory(const char* filename) +AUD_SndFileFactory::AUD_SndFileFactory(std::string filename) : + m_filename(filename) { - if(filename != NULL) - { - m_filename = new char[strlen(filename)+1]; AUD_NEW("string") - strcpy(m_filename, filename); - } - else - m_filename = NULL; } -AUD_SndFileFactory::AUD_SndFileFactory(unsigned char* buffer, int size) +AUD_SndFileFactory::AUD_SndFileFactory(const data_t* buffer, int size) : + m_buffer(new AUD_Buffer(size)) { - m_filename = NULL; - m_buffer = AUD_Reference<AUD_Buffer>(new AUD_Buffer(size)); memcpy(m_buffer.get()->getBuffer(), buffer, size); } -AUD_SndFileFactory::~AUD_SndFileFactory() -{ - if(m_filename) - { - delete[] m_filename; AUD_DELETE("string") - } -} - -AUD_IReader* AUD_SndFileFactory::createReader() +AUD_IReader* AUD_SndFileFactory::createReader() const { - AUD_IReader* reader; - if(m_filename) - reader = new AUD_SndFileReader(m_filename); + if(m_buffer.get()) + return new AUD_SndFileReader(m_buffer); else - reader = new AUD_SndFileReader(m_buffer); - AUD_NEW("reader") - return reader; + return new AUD_SndFileReader(m_filename); } diff --git a/intern/audaspace/sndfile/AUD_SndFileFactory.h b/intern/audaspace/sndfile/AUD_SndFileFactory.h index 98187ff1590..350e48abef8 100644 --- a/intern/audaspace/sndfile/AUD_SndFileFactory.h +++ b/intern/audaspace/sndfile/AUD_SndFileFactory.h @@ -30,6 +30,8 @@ #include "AUD_Reference.h" class AUD_Buffer; +#include <string> + /** * This factory reads a sound file via libsndfile. */ @@ -39,33 +41,32 @@ private: /** * The filename of the sound source file. */ - char* m_filename; + std::string m_filename; /** * The buffer to read from. */ AUD_Reference<AUD_Buffer> m_buffer; + // hide copy constructor and operator= + AUD_SndFileFactory(const AUD_SndFileFactory&); + AUD_SndFileFactory& operator=(const AUD_SndFileFactory&); + public: /** * Creates a new factory. * \param filename The sound file path. */ - AUD_SndFileFactory(const char* filename); + AUD_SndFileFactory(std::string filename); /** * Creates a new factory. * \param buffer The buffer to read from. * \param size The size of the buffer. */ - AUD_SndFileFactory(unsigned char* buffer, int size); - - /** - * Destroys the factory. - */ - ~AUD_SndFileFactory(); + AUD_SndFileFactory(const data_t* buffer, int size); - virtual AUD_IReader* createReader(); + virtual AUD_IReader* createReader() const; }; #endif //AUD_SNDFILEFACTORY diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.cpp b/intern/audaspace/sndfile/AUD_SndFileReader.cpp index f9ed8d6388e..488a06d8728 100644 --- a/intern/audaspace/sndfile/AUD_SndFileReader.cpp +++ b/intern/audaspace/sndfile/AUD_SndFileReader.cpp @@ -24,7 +24,6 @@ */ #include "AUD_SndFileReader.h" -#include "AUD_Buffer.h" #include <cstring> @@ -77,30 +76,31 @@ sf_count_t AUD_SndFileReader::vio_tell(void *user_data) return reader->m_memoffset; } -AUD_SndFileReader::AUD_SndFileReader(const char* filename) +static const char* fileopen_error = "AUD_SndFileReader: File couldn't be " + "read."; + +AUD_SndFileReader::AUD_SndFileReader(std::string filename) : + m_position(0) { SF_INFO sfinfo; sfinfo.format = 0; - m_sndfile = sf_open(filename, SFM_READ, &sfinfo); + m_sndfile = sf_open(filename.c_str(), SFM_READ, &sfinfo); if(!m_sndfile) - AUD_THROW(AUD_ERROR_FILE); + AUD_THROW(AUD_ERROR_FILE, fileopen_error); m_specs.channels = (AUD_Channels) sfinfo.channels; m_specs.rate = (AUD_SampleRate) sfinfo.samplerate; m_length = sfinfo.frames; m_seekable = sfinfo.seekable; - m_position = 0; - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } -AUD_SndFileReader::AUD_SndFileReader(AUD_Reference<AUD_Buffer> buffer) +AUD_SndFileReader::AUD_SndFileReader(AUD_Reference<AUD_Buffer> buffer) : + m_position(0), + m_membuffer(buffer), + m_memoffset(0) { - m_membuffer = buffer; - m_memoffset = 0; - m_vio.get_filelen = vio_get_filelen; m_vio.read = vio_read; m_vio.seek = vio_seek; @@ -113,25 +113,20 @@ AUD_SndFileReader::AUD_SndFileReader(AUD_Reference<AUD_Buffer> buffer) m_sndfile = sf_open_virtual(&m_vio, SFM_READ, &sfinfo, this); if(!m_sndfile) - AUD_THROW(AUD_ERROR_FILE); + AUD_THROW(AUD_ERROR_FILE, fileopen_error); m_specs.channels = (AUD_Channels) sfinfo.channels; m_specs.rate = (AUD_SampleRate) sfinfo.samplerate; m_length = sfinfo.frames; m_seekable = sfinfo.seekable; - m_position = 0; - - m_buffer = new AUD_Buffer(); AUD_NEW("buffer") } AUD_SndFileReader::~AUD_SndFileReader() { sf_close(m_sndfile); - - delete m_buffer; AUD_DELETE("buffer") } -bool AUD_SndFileReader::isSeekable() +bool AUD_SndFileReader::isSeekable() const { return m_seekable; } @@ -145,40 +140,30 @@ void AUD_SndFileReader::seek(int position) } } -int AUD_SndFileReader::getLength() +int AUD_SndFileReader::getLength() const { return m_length; } -int AUD_SndFileReader::getPosition() +int AUD_SndFileReader::getPosition() const { return m_position; } -AUD_Specs AUD_SndFileReader::getSpecs() +AUD_Specs AUD_SndFileReader::getSpecs() const { return m_specs; } -AUD_ReaderType AUD_SndFileReader::getType() -{ - return AUD_TYPE_STREAM; -} - -bool AUD_SndFileReader::notify(AUD_Message &message) -{ - return false; -} - void AUD_SndFileReader::read(int & length, sample_t* & buffer) { int sample_size = AUD_SAMPLE_SIZE(m_specs); // resize output buffer if necessary - if(m_buffer->getSize() < length*sample_size) - m_buffer->resize(length*sample_size); + if(m_buffer.getSize() < length*sample_size) + m_buffer.resize(length*sample_size); - buffer = m_buffer->getBuffer(); + buffer = m_buffer.getBuffer(); length = sf_readf_float(m_sndfile, buffer, length); diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.h b/intern/audaspace/sndfile/AUD_SndFileReader.h index 8886b6e9efc..a53189fdecd 100644 --- a/intern/audaspace/sndfile/AUD_SndFileReader.h +++ b/intern/audaspace/sndfile/AUD_SndFileReader.h @@ -28,8 +28,9 @@ #include "AUD_IReader.h" #include "AUD_Reference.h" -class AUD_Buffer; +#include "AUD_Buffer.h" +#include <string> #include <sndfile.h> typedef sf_count_t (*sf_read_f)(SNDFILE *sndfile, void *ptr, sf_count_t frames); @@ -63,7 +64,7 @@ private: /** * The playback buffer. */ - AUD_Buffer* m_buffer; + AUD_Buffer m_buffer; /** * The sndfile. @@ -91,6 +92,10 @@ private: static sf_count_t vio_read(void *ptr, sf_count_t count, void *user_data); static sf_count_t vio_tell(void *user_data); + // hide copy constructor and operator= + AUD_SndFileReader(const AUD_SndFileReader&); + AUD_SndFileReader& operator=(const AUD_SndFileReader&); + public: /** * Creates a new reader. @@ -98,7 +103,7 @@ public: * \exception AUD_Exception Thrown if the file specified does not exist or * cannot be read with libsndfile. */ - AUD_SndFileReader(const char* filename); + AUD_SndFileReader(std::string filename); /** * Creates a new reader. @@ -113,13 +118,11 @@ public: */ virtual ~AUD_SndFileReader(); - virtual bool isSeekable(); + virtual bool isSeekable() const; virtual void seek(int position); - virtual int getLength(); - virtual int getPosition(); - virtual AUD_Specs getSpecs(); - virtual AUD_ReaderType getType(); - virtual bool notify(AUD_Message &message); + virtual int getLength() const; + virtual int getPosition() const; + virtual AUD_Specs getSpecs() const; virtual void read(int & length, sample_t* & buffer); }; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 8fd97a80110..26392132038 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -382,10 +382,8 @@ void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, i void sound_start_play_scene(struct Scene *scene) { - AUD_Sound* sound; - sound = AUD_loopSound(scene->sound_scene); - scene->sound_scene_handle = AUD_play(sound, 1); - AUD_unload(sound); + scene->sound_scene_handle = AUD_play(scene->sound_scene, 1); + AUD_setLoop(scene->sound_scene_handle, -1); } void sound_play_scene(struct Scene *scene) @@ -398,8 +396,6 @@ void sound_play_scene(struct Scene *scene) if(status == AUD_STATUS_INVALID) sound_start_play_scene(scene); - AUD_setLoop(scene->sound_scene_handle, -1, -1); - if(status != AUD_STATUS_PLAYING) { AUD_seek(scene->sound_scene_handle, CFRA / FPS); @@ -437,12 +433,16 @@ void sound_seek_scene(struct bContext *C) if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer) { - AUD_setLoop(scene->sound_scene_handle, -1, 1 / FPS); + // AUD_XXX TODO: fix scrubbing, it currently doesn't stop playing if(scene->audio.flag & AUDIO_SYNC) AUD_seekSequencer(scene->sound_scene_handle, CFRA / FPS); else AUD_seek(scene->sound_scene_handle, CFRA / FPS); AUD_resume(scene->sound_scene_handle); + if(AUD_getStatus(scene->sound_scrub_handle) != AUD_STATUS_INVALID) + AUD_seek(scene->sound_scrub_handle, 0); + else + scene->sound_scrub_handle = AUD_pauseAfter(scene->sound_scene_handle, 1 / FPS); } else { diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index bc9ae0abd99..cc5d256615e 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -795,6 +795,7 @@ typedef struct Scene { void *sound_scene; void *sound_scene_handle; + void *sound_scrub_handle; void *fps_info; /* (runtime) info/cache used for presenting playback framerate info to the user */ diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt index 3c79e9d3056..dcfc8678faa 100644 --- a/source/blender/python/CMakeLists.txt +++ b/source/blender/python/CMakeLists.txt @@ -36,6 +36,7 @@ SET(INC ../windowmanager ../editors/include ../../../intern/guardedalloc + ../../../intern/audaspace/intern ${PYTHON_INC} ) diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript index 17189341136..f062f64249c 100644 --- a/source/blender/python/SConscript +++ b/source/blender/python/SConscript @@ -6,7 +6,7 @@ sources = env.Glob('intern/*.c') incs = '. ../editors/include ../makesdna ../makesrna ../blenlib ../blenkernel ../nodes' incs += ' ../imbuf ../blenloader ../render/extern/include ../windowmanager' incs += ' #intern/guardedalloc #intern/memutil #extern/glew/include' -incs += ' ' + env['BF_PYTHON_INC'] +incs += ' #intern/audaspace/intern ' + env['BF_PYTHON_INC'] defs = [] diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index c86ebc7f691..e107509d844 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -41,6 +41,11 @@ #include "../generic/blf_api.h" #include "../generic/IDProp.h" +#ifndef DISABLE_PYTHON +#define WITH_PYTHON +#endif +#include "AUD_C-API.h" + static char bpy_script_paths_doc[] = ".. function:: script_paths()\n" "\n" @@ -153,7 +158,7 @@ void BPy_init_modules( void ) BGL_Init(); BLF_Init(); IDProp_Init_Types(); - + AUD_initPython(); mod = PyModule_New("_bpy"); diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index a83ec7e132f..b5b9c96a7ff 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -388,9 +388,15 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c ketsjiengine->InitDome(scene->gm.dome.res, scene->gm.dome.mode, scene->gm.dome.angle, scene->gm.dome.resbuf, scene->gm.dome.tilt, scene->gm.dome.warptext); // initialize 3D Audio Settings - AUD_set3DSetting(AUD_3DS_SPEED_OF_SOUND, scene->audio.speed_of_sound); - AUD_set3DSetting(AUD_3DS_DOPPLER_FACTOR, scene->audio.doppler_factor); - AUD_set3DSetting(AUD_3DS_DISTANCE_MODEL, scene->audio.distance_model); + AUD_setSpeedOfSound(scene->audio.speed_of_sound); + AUD_setDopplerFactor(scene->audio.doppler_factor); + AUD_setDistanceModel(AUD_DistanceModel(scene->audio.distance_model)); + + // from see blender.c: + // FIXME: this version patching should really be part of the file-reading code, + // but we still get too many unrelated data-corruption crashes otherwise... + if (blenderdata->versionfile < 250) + do_versions_ipos_to_animato(blenderdata); if (sceneconverter) { diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 71cd8b36045..1a6ae69f792 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -235,7 +235,7 @@ void KX_KetsjiEngine::SetRasterizer(RAS_IRasterizer* rasterizer) #ifndef DISABLE_PYTHON /* - * At the moment the GameLogic module is imported into 'pythondictionary' after this function is called. + * At the moment the bge.logic module is imported into 'pythondictionary' after this function is called. * if this function ever changes to assign a copy, make sure the game logic module is imported into this dictionary before hand. */ void KX_KetsjiEngine::SetPyNamespace(PyObject* pythondictionary) @@ -966,44 +966,17 @@ void KX_KetsjiEngine::DoSound(KX_Scene* scene) KX_Camera* cam = scene->GetActiveCamera(); if (!cam) return; - MT_Point3 listenerposition = cam->NodeGetWorldPosition(); - MT_Vector3 listenervelocity = cam->GetLinearVelocity(); - MT_Matrix3x3 listenerorientation = cam->NodeGetWorldOrientation(); - { - AUD_3DData data; - float f; - - listenerorientation.getValue3x3(data.orientation); - listenerposition.getValue(data.position); - listenervelocity.getValue(data.velocity); - - f = data.position[1]; - data.position[1] = data.position[2]; - data.position[2] = -f; - - f = data.velocity[1]; - data.velocity[1] = data.velocity[2]; - data.velocity[2] = -f; + float f[4]; - f = data.orientation[1]; - data.orientation[1] = data.orientation[2]; - data.orientation[2] = -f; + cam->NodeGetWorldPosition().getValue(f); + AUD_setListenerLocation(f); - f = data.orientation[3]; - data.orientation[3] = -data.orientation[6]; - data.orientation[6] = f; + cam->GetLinearVelocity().getValue(f); + AUD_setListenerVelocity(f); - f = data.orientation[4]; - data.orientation[4] = -data.orientation[8]; - data.orientation[8] = -f; - - f = data.orientation[5]; - data.orientation[5] = data.orientation[7]; - data.orientation[7] = f; - - AUD_updateListener(&data); - } + cam->NodeGetWorldOrientation().getRotation().getValue(f); + AUD_setListenerOrientation(f); } diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 3350a59681b..303890fd630 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -45,6 +45,10 @@ extern "C" { #include "marshal.h" /* python header for loading/saving dicts */ } + +#define WITH_PYTHON +#include "AUD_C-API.h" + #endif #include "KX_PythonInit.h" @@ -262,8 +266,8 @@ static PyObject* gPyRestartGame(PyObject*) } static char gPySaveGlobalDict_doc[] = -"saveGlobalDict()\n\ -Saves GameLogic.globalDict to a file"; + "saveGlobalDict()\n" + "Saves bge.logic.globalDict to a file"; static PyObject* gPySaveGlobalDict(PyObject*) { @@ -299,8 +303,8 @@ static PyObject* gPySaveGlobalDict(PyObject*) } static char gPyLoadGlobalDict_doc[] = -"LoadGlobalDict()\n\ -Loads GameLogic.globalDict from a file"; + "LoadGlobalDict()\n" + "Loads bge.logic.globalDict from a file"; static PyObject* gPyLoadGlobalDict(PyObject*) { @@ -375,15 +379,6 @@ static PyObject* gPyGetSpectrum(PyObject*) return resultlist; } - -static PyObject* gPyStopDSP(PyObject*, PyObject* args) -{ - PyErr_SetString(PyExc_RuntimeError, "no audio device available"); - return NULL; - - Py_RETURN_NONE; -} - static PyObject* gPySetLogicTicRate(PyObject*, PyObject* args) { float ticrate; @@ -752,7 +747,6 @@ static struct PyMethodDef game_methods[] = { {"getRandomFloat",(PyCFunction) gPyGetRandomFloat, METH_NOARGS, (const char *)gPyGetRandomFloat_doc}, {"setGravity",(PyCFunction) gPySetGravity, METH_O, (const char *)"set Gravitation"}, {"getSpectrum",(PyCFunction) gPyGetSpectrum, METH_NOARGS, (const char *)"get audio spectrum"}, - {"stopDSP",(PyCFunction) gPyStopDSP, METH_VARARGS, (const char *)"stop using the audio dsp (for performance reasons)"}, {"getMaxLogicFrame", (PyCFunction) gPyGetMaxLogicFrame, METH_NOARGS, (const char *)"Gets the max number of logic frame per render frame"}, {"setMaxLogicFrame", (PyCFunction) gPySetMaxLogicFrame, METH_VARARGS, (const char *)"Sets the max number of logic frame per render frame"}, {"getMaxPhysicsFrame", (PyCFunction) gPyGetMaxPhysicsFrame, METH_NOARGS, (const char *)"Gets the max number of physics frame per render frame"}, @@ -935,7 +929,6 @@ static PyObject* gPyDisableMist(PyObject*) Py_RETURN_NONE; } - static PyObject* gPySetMistStart(PyObject*, PyObject* args) { @@ -1232,7 +1225,7 @@ static struct PyMethodDef rasterizer_methods[] = { // Initialization function for the module (*must* be called initGameLogic) static char GameLogic_module_documentation[] = -"This is the Python API for the game engine of GameLogic" +"This is the Python API for the game engine of bge.logic" ; static char Rasterizer_module_documentation[] = @@ -1313,7 +1306,6 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack KX_MACRO_addTypesToDict(d, KX_PROPSENSOR_EXPRESSION, SCA_PropertySensor::KX_PROPSENSOR_EXPRESSION); /* 3. Constraint actuator */ - /* XXX, TODO NXBGE, move constants names from KX_ACT_CONSTRAINT_foo to KX_CONSTRAINTACT_foo */ KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_LOCX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCX); KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_LOCY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCY); KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_LOCZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCZ); @@ -1329,18 +1321,18 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIX); KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIY); KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIZ); - KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHPX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPX); - KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHPY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPY); - KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHPZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPZ); - KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHNX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNX); - KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHNY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNY); - KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHNZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNZ); - KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_NORMAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_NORMAL); - KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_MATERIAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_MATERIAL); - KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_PERMANENT, KX_ConstraintActuator::KX_ACT_CONSTRAINT_PERMANENT); - KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_DISTANCE, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DISTANCE); - KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_LOCAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCAL); - KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_DOROTFH, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DOROTFH); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_FHPX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPX); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_FHPY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPY); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_FHPZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPZ); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_FHNX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNX); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_FHNY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNY); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_FHNZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNZ); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_NORMAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_NORMAL); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_MATERIAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_MATERIAL); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_PERMANENT, KX_ConstraintActuator::KX_ACT_CONSTRAINT_PERMANENT); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DISTANCE, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DISTANCE); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_LOCAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCAL); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DOROTFH, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DOROTFH); /* 4. Ipo actuator, simple part */ KX_MACRO_addTypesToDict(d, KX_IPOACT_PLAY, KX_IpoActuator::KX_ACT_IPO_PLAY); @@ -1582,7 +1574,7 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack // Check for errors if (PyErr_Occurred()) { - Py_FatalError("can't initialize module GameLogic"); + Py_FatalError("can't initialize module bge.logic"); } return m; @@ -1979,7 +1971,6 @@ void setupGamePython(KX_KetsjiEngine* ketsjiengine, KX_Scene* startscene, Main * PyDict_SetItemString(PyModule_GetDict(*gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. *gameLogic_keys = PyDict_Keys(PyModule_GetDict(*gameLogic)); - PyDict_SetItemString(dictionaryobject, "GameLogic", *gameLogic); // Same as importing the module. initGameKeys(); initPythonConstraintBinding(); @@ -1987,10 +1978,11 @@ void setupGamePython(KX_KetsjiEngine* ketsjiengine, KX_Scene* startscene, Main * initGeometry(); initBGL(); initBLF(); + AUD_initPython(); initVideoTexture(); /* could be done a lot more nicely, but for now a quick way to get bge.* working */ - PyRun_SimpleString("sys = __import__('sys');mod = sys.modules['bge'] = type(sys)('bge');mod.__dict__.update({'logic':__import__('GameLogic'), 'render':__import__('Rasterizer'), 'events':__import__('GameKeys'), 'constraints':__import__('PhysicsConstraints'), 'types':__import__('GameTypes')})"); + PyRun_SimpleString("sys = __import__('sys');mod = sys.modules['bge'] = type(sys)('bge');mod.__dict__.update({'logic':__import__('GameLogic'), 'render':__import__('Rasterizer'), 'events':__import__('GameKeys'), 'constraints':__import__('PhysicsConstraints'), 'types':__import__('GameTypes')});import bge"); } static struct PyModuleDef Rasterizer_module_def = { @@ -2338,15 +2330,15 @@ int saveGamePythonConfig( char **marshal_buffer) memcpy(*marshal_buffer, marshal_cstring, marshal_length); Py_DECREF(pyGlobalDictMarshal); } else { - printf("Error, GameLogic.globalDict could not be marshal'd\n"); + printf("Error, bge.logic.globalDict could not be marshal'd\n"); } } else { - printf("Error, GameLogic.globalDict was removed\n"); + printf("Error, bge.logic.globalDict was removed\n"); } Py_DECREF(gameLogic); } else { PyErr_Clear(); - printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); + printf("Error, bge.logic failed to import bge.logic.globalDict will be lost\n"); } return marshal_length; } @@ -2378,7 +2370,7 @@ int loadGamePythonConfig(char *marshal_buffer, int marshal_length) } } else { PyErr_Clear(); - printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); + printf("Error, bge.logic failed to import bge.logic.globalDict will be lost\n"); } } return 0; diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index 7f9b090d680..09ad567117f 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -31,6 +31,7 @@ */ #include "KX_SoundActuator.h" +#include "AUD_C-API.h" #include "KX_GameObject.h" #include "KX_PyMath.h" // needed for PyObjectFrom() #include <iostream> @@ -75,23 +76,20 @@ void KX_SoundActuator::play() // this is the sound that will be played and not deleted afterwards AUD_Sound* sound = m_sound; - // this sounds are for temporary stacked sounds, will be deleted if not NULL + // this sound is for temporary stacked sounds, will be deleted if not NULL AUD_Sound* sound2 = NULL; - AUD_Sound* sound3 = NULL; + + bool loop = false; switch (m_type) { case KX_SOUNDACT_LOOPBIDIRECTIONAL: case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP: - // create a ping pong sound on sound2 stacked on the orignal sound - sound2 = AUD_pingpongSound(sound); - // create a loop sound on sound3 stacked on the pingpong sound and let that one play (save it to sound) - sound = sound3 = AUD_loopSound(sound2); - break; + sound = sound2 = AUD_pingpongSound(sound); + // fall through case KX_SOUNDACT_LOOPEND: case KX_SOUNDACT_LOOPSTOP: - // create a loop sound on sound2 stacked on the pingpong sound and let that one play (save it to sound) - sound = sound2 = AUD_loopSound(sound); + loop = true; break; case KX_SOUNDACT_PLAYSTOP: case KX_SOUNDACT_PLAYEND: @@ -102,28 +100,27 @@ void KX_SoundActuator::play() if(m_is3d) { // sound shall be played 3D - m_handle = AUD_play3D(sound, 0); - - AUD_set3DSourceSetting(m_handle, AUD_3DSS_MAX_GAIN, m_3d.max_gain); - AUD_set3DSourceSetting(m_handle, AUD_3DSS_MIN_GAIN, m_3d.min_gain); - AUD_set3DSourceSetting(m_handle, AUD_3DSS_REFERENCE_DISTANCE, m_3d.reference_distance); - AUD_set3DSourceSetting(m_handle, AUD_3DSS_MAX_DISTANCE, m_3d.max_distance); - AUD_set3DSourceSetting(m_handle, AUD_3DSS_ROLLOFF_FACTOR, m_3d.rolloff_factor); - AUD_set3DSourceSetting(m_handle, AUD_3DSS_CONE_INNER_ANGLE, m_3d.cone_inner_angle); - AUD_set3DSourceSetting(m_handle, AUD_3DSS_CONE_OUTER_ANGLE, m_3d.cone_outer_angle); - AUD_set3DSourceSetting(m_handle, AUD_3DSS_CONE_OUTER_GAIN, m_3d.cone_outer_gain); + m_handle = AUD_play(sound, 0); + + AUD_setRelative(m_handle, true); + AUD_setVolumeMaximum(m_handle, m_3d.max_gain); + AUD_setVolumeMinimum(m_handle, m_3d.min_gain); + AUD_setDistanceReference(m_handle, m_3d.reference_distance); + AUD_setDistanceMaximum(m_handle, m_3d.max_distance); + AUD_setAttenuation(m_handle, m_3d.rolloff_factor); + AUD_setConeAngleInner(m_handle, m_3d.cone_inner_angle); + AUD_setConeAngleOuter(m_handle, m_3d.cone_outer_angle); + AUD_setConeVolumeOuter(m_handle, m_3d.cone_outer_gain); } else m_handle = AUD_play(sound, 0); + if(loop) + AUD_setLoop(m_handle, -1); AUD_setSoundPitch(m_handle, m_pitch); AUD_setSoundVolume(m_handle, m_volume); m_isplaying = true; - // now we unload the pingpong and loop sounds, as we don't need them anymore - // the started sound will continue playing like it was created, don't worry! - if(sound3) - AUD_unload(sound3); if(sound2) AUD_unload(sound2); } @@ -183,7 +180,7 @@ bool KX_SoundActuator::Update(double curtime, bool frame) case KX_SOUNDACT_LOOPBIDIRECTIONAL: { // stop the looping so that the sound stops when it finished - AUD_setLoop(m_handle, 0, -1); + AUD_setLoop(m_handle, 0); break; } default: @@ -215,39 +212,15 @@ bool KX_SoundActuator::Update(double curtime, bool frame) { if(m_is3d) { - AUD_3DData data; - float f; - ((KX_GameObject*)this->GetParent())->NodeGetWorldPosition().getValue(data.position); - ((KX_GameObject*)this->GetParent())->GetLinearVelocity().getValue(data.velocity); - ((KX_GameObject*)this->GetParent())->NodeGetWorldOrientation().getValue3x3(data.orientation); - - /* - * The 3D data from blender has to be transformed for OpenAL: - * - In blender z is up and y is forwards - * - In OpenAL y is up and z is backwards - * We have to do that for all 5 vectors. - */ - f = data.position[1]; - data.position[1] = data.position[2]; - data.position[2] = -f; - - f = data.velocity[1]; - data.velocity[1] = data.velocity[2]; - data.velocity[2] = -f; - - f = data.orientation[1]; - data.orientation[1] = data.orientation[2]; - data.orientation[2] = -f; - - f = data.orientation[4]; - data.orientation[4] = data.orientation[5]; - data.orientation[5] = -f; - - f = data.orientation[7]; - data.orientation[7] = data.orientation[8]; - data.orientation[8] = -f; - - AUD_update3DSource(m_handle, &data); + KX_GameObject* obj = (KX_GameObject*)this->GetParent(); + float f[4]; + + obj->NodeGetWorldPosition().getValue(f); + AUD_setSourceLocation(m_handle, f); + obj->GetLinearVelocity().getValue(f); + AUD_setSourceVelocity(m_handle, f); + obj->NodeGetWorldOrientation().getRotation().getValue(f); + AUD_setSourceOrientation(m_handle, f); } result = true; } @@ -300,19 +273,18 @@ PyMethodDef KX_SoundActuator::Methods[] = { PyAttributeDef KX_SoundActuator::Attributes[] = { KX_PYATTRIBUTE_BOOL_RO("is3D", KX_SoundActuator, m_is3d), - KX_PYATTRIBUTE_RW_FUNCTION("maxGain3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), - KX_PYATTRIBUTE_RW_FUNCTION("minGain3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), - KX_PYATTRIBUTE_RW_FUNCTION("referenceDistance3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), - KX_PYATTRIBUTE_RW_FUNCTION("maxDistance3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), - KX_PYATTRIBUTE_RW_FUNCTION("rolloffFactor3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), - KX_PYATTRIBUTE_RW_FUNCTION("coneInnerAngle3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), - KX_PYATTRIBUTE_RW_FUNCTION("coneOuterAngle3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), - KX_PYATTRIBUTE_RW_FUNCTION("coneOuterGain3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), - + KX_PYATTRIBUTE_RW_FUNCTION("volume_maximum", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), + KX_PYATTRIBUTE_RW_FUNCTION("volume_minimum", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), + KX_PYATTRIBUTE_RW_FUNCTION("distance_reference", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), + KX_PYATTRIBUTE_RW_FUNCTION("distance_maximum", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), + KX_PYATTRIBUTE_RW_FUNCTION("attenuation", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), + KX_PYATTRIBUTE_RW_FUNCTION("cone_angle_inner", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), + KX_PYATTRIBUTE_RW_FUNCTION("cone_angle_outer", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), + KX_PYATTRIBUTE_RW_FUNCTION("cone_volume_outer", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property), + KX_PYATTRIBUTE_RW_FUNCTION("time", KX_SoundActuator, pyattr_get_audposition, pyattr_set_audposition), KX_PYATTRIBUTE_RW_FUNCTION("volume", KX_SoundActuator, pyattr_get_gain, pyattr_set_gain), KX_PYATTRIBUTE_RW_FUNCTION("pitch", KX_SoundActuator, pyattr_get_pitch, pyattr_set_pitch), - KX_PYATTRIBUTE_RW_FUNCTION("rollOffFactor", KX_SoundActuator, pyattr_get_rollOffFactor, pyattr_set_rollOffFactor), KX_PYATTRIBUTE_ENUM_RW("mode",KX_SoundActuator::KX_SOUNDACT_NODEF+1,KX_SoundActuator::KX_SOUNDACT_MAX-1,false,KX_SoundActuator,m_type), { NULL } //Sentinel }; @@ -358,28 +330,28 @@ PyObject* KX_SoundActuator::pyattr_get_3d_property(void *self, const struct KX_P const char* prop = attrdef->m_name; float result_value = 0.0; - if(!strcmp(prop, "maxGain3D")) { + if(!strcmp(prop, "volume_maximum")) { result_value = actuator->m_3d.max_gain; - } else if (!strcmp(prop, "minGain3D")) { + } else if (!strcmp(prop, "volume_minimum")) { result_value = actuator->m_3d.min_gain; - } else if (!strcmp(prop, "referenceDistance3D")) { + } else if (!strcmp(prop, "distance_reference")) { result_value = actuator->m_3d.reference_distance; - } else if (!strcmp(prop, "maxDistance3D")) { + } else if (!strcmp(prop, "distance_maximum")) { result_value = actuator->m_3d.max_distance; - } else if (!strcmp(prop, "rolloffFactor3D")) { + } else if (!strcmp(prop, "attenuation")) { result_value = actuator->m_3d.rolloff_factor; - } else if (!strcmp(prop, "coneInnerAngle3D")) { + } else if (!strcmp(prop, "cone_angle_inner")) { result_value = actuator->m_3d.cone_inner_angle; - } else if (!strcmp(prop, "coneOuterAngle3D")) { + } else if (!strcmp(prop, "cone_angle_outer")) { result_value = actuator->m_3d.cone_outer_angle; - } else if (!strcmp(prop, "coneOuterGain3D")) { + } else if (!strcmp(prop, "cone_volume_outer")) { result_value = actuator->m_3d.cone_outer_gain; } else { @@ -423,66 +395,63 @@ PyObject* KX_SoundActuator::pyattr_get_pitch(void *self, const struct KX_PYATTRI return result; } -PyObject* KX_SoundActuator::pyattr_get_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) -{ - KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); - float rollofffactor = actuator->m_3d.rolloff_factor; - PyObject* result = PyFloat_FromDouble(rollofffactor); - - return result; -} - int KX_SoundActuator::pyattr_set_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); const char* prop = attrdef->m_name; float prop_value = 0.0; - AUD_3DSourceSetting setting = AUD_3DSS_NONE; if (!PyArg_Parse(value, "f", &prop_value)) return PY_SET_ATTR_FAIL; - // update the internal value - if(!strcmp(prop, "maxGain3D")) { + // if sound is working and 3D, set the new setting + if(!actuator->m_is3d) + return PY_SET_ATTR_FAIL; + + if(!strcmp(prop, "volume_maximum")) { actuator->m_3d.max_gain = prop_value; - setting = AUD_3DSS_MAX_GAIN; + if(actuator->m_handle) + AUD_setVolumeMaximum(actuator->m_handle, prop_value); - } else if (!strcmp(prop, "minGain3D")) { + } else if (!strcmp(prop, "volume_minimum")) { actuator->m_3d.min_gain = prop_value; - setting = AUD_3DSS_MIN_GAIN; + if(actuator->m_handle) + AUD_setVolumeMinimum(actuator->m_handle, prop_value); - } else if (!strcmp(prop, "referenceDistance3D")) { + } else if (!strcmp(prop, "distance_reference")) { actuator->m_3d.reference_distance = prop_value; - setting = AUD_3DSS_REFERENCE_DISTANCE; + if(actuator->m_handle) + AUD_setDistanceReference(actuator->m_handle, prop_value); - } else if (!strcmp(prop, "maxDistance3D")) { + } else if (!strcmp(prop, "distance_maximum")) { actuator->m_3d.max_distance = prop_value; - setting = AUD_3DSS_MAX_DISTANCE; + if(actuator->m_handle) + AUD_setDistanceMaximum(actuator->m_handle, prop_value); - } else if (!strcmp(prop, "rolloffFactor3D")) { + } else if (!strcmp(prop, "attenuation")) { actuator->m_3d.rolloff_factor = prop_value; - setting = AUD_3DSS_ROLLOFF_FACTOR; + if(actuator->m_handle) + AUD_setAttenuation(actuator->m_handle, prop_value); - } else if (!!strcmp(prop, "coneInnerAngle3D")) { + } else if (!!strcmp(prop, "cone_angle_inner")) { actuator->m_3d.cone_inner_angle = prop_value; - setting = AUD_3DSS_CONE_INNER_ANGLE; + if(actuator->m_handle) + AUD_setConeAngleInner(actuator->m_handle, prop_value); - } else if (!strcmp(prop, "coneOuterAngle3D")) { + } else if (!strcmp(prop, "cone_angle_outer")) { actuator->m_3d.cone_outer_angle = prop_value; - setting = AUD_3DSS_CONE_OUTER_ANGLE; + if(actuator->m_handle) + AUD_setConeAngleOuter(actuator->m_handle, prop_value); - } else if (!strcmp(prop, "coneOuterGain3D")) { + } else if (!strcmp(prop, "cone_volume_outer")) { actuator->m_3d.cone_outer_gain = prop_value; - setting = AUD_3DSS_CONE_OUTER_GAIN; + if(actuator->m_handle) + AUD_setConeVolumeOuter(actuator->m_handle, prop_value); } else { return PY_SET_ATTR_FAIL; - } + } - // if sound is working and 3D, set the new setting - if(actuator->m_handle && actuator->m_is3d && setting != AUD_3DSS_NONE) - AUD_set3DSourceSetting(actuator->m_handle, setting, prop_value); - return PY_SET_ATTR_SUCCESS; } @@ -527,18 +496,4 @@ int KX_SoundActuator::pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_D return PY_SET_ATTR_SUCCESS; } -int KX_SoundActuator::pyattr_set_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) -{ - KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); - float rollofffactor = 1.0; - if (!PyArg_Parse(value, "f", &rollofffactor)) - return PY_SET_ATTR_FAIL; - - actuator->m_3d.rolloff_factor = rollofffactor; - if(actuator->m_handle) - AUD_set3DSourceSetting(actuator->m_handle, AUD_3DSS_ROLLOFF_FACTOR, rollofffactor); - - return PY_SET_ATTR_SUCCESS; -} - #endif // DISABLE_PYTHON diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h index 1eaea276191..c175a184a15 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.h +++ b/source/gameengine/Ketsji/KX_SoundActuator.h @@ -58,7 +58,7 @@ class KX_SoundActuator : public SCA_IActuator float m_pitch; bool m_is3d; KX_3DSoundSettings m_3d; - AUD_Handle* m_handle; + AUD_Channel* m_handle; void play(); @@ -107,14 +107,12 @@ public: static int pyattr_set_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); - static int pyattr_set_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_set_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); #endif // DISABLE_PYTHON |