svn merge -r 31314:31370 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorJoerg Mueller <nexyon@gmail.com>
Mon, 16 Aug 2010 09:37:08 +0000 (09:37 +0000)
committerJoerg Mueller <nexyon@gmail.com>
Mon, 16 Aug 2010 09:37:08 +0000 (09:37 +0000)
192 files changed:
intern/audaspace/CMakeLists.txt
intern/audaspace/FX/AUD_AccumulatorFactory.cpp
intern/audaspace/FX/AUD_AccumulatorFactory.h
intern/audaspace/FX/AUD_AccumulatorReader.cpp [deleted file]
intern/audaspace/FX/AUD_AccumulatorReader.h [deleted file]
intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp [new file with mode: 0644]
intern/audaspace/FX/AUD_BaseIIRFilterReader.h [new file with mode: 0644]
intern/audaspace/FX/AUD_ButterworthFactory.cpp
intern/audaspace/FX/AUD_ButterworthFactory.h
intern/audaspace/FX/AUD_ButterworthReader.cpp [deleted file]
intern/audaspace/FX/AUD_ButterworthReader.h [deleted file]
intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp [moved from intern/audaspace/FX/AUD_RectifyReader.cpp with 56% similarity]
intern/audaspace/FX/AUD_CallbackIIRFilterReader.h [new file with mode: 0644]
intern/audaspace/FX/AUD_DelayFactory.cpp
intern/audaspace/FX/AUD_DelayFactory.h
intern/audaspace/FX/AUD_DelayReader.cpp
intern/audaspace/FX/AUD_DelayReader.h
intern/audaspace/FX/AUD_DoubleFactory.cpp [new file with mode: 0644]
intern/audaspace/FX/AUD_DoubleFactory.h [moved from intern/audaspace/FX/AUD_SquareReader.h with 53% similarity]
intern/audaspace/FX/AUD_DoubleReader.cpp
intern/audaspace/FX/AUD_DoubleReader.h
intern/audaspace/FX/AUD_EffectFactory.cpp
intern/audaspace/FX/AUD_EffectFactory.h
intern/audaspace/FX/AUD_EffectReader.cpp
intern/audaspace/FX/AUD_EffectReader.h
intern/audaspace/FX/AUD_EnvelopeFactory.cpp
intern/audaspace/FX/AUD_EnvelopeFactory.h
intern/audaspace/FX/AUD_EnvelopeReader.cpp [deleted file]
intern/audaspace/FX/AUD_EnvelopeReader.h [deleted file]
intern/audaspace/FX/AUD_FaderFactory.cpp
intern/audaspace/FX/AUD_FaderFactory.h
intern/audaspace/FX/AUD_FaderReader.cpp
intern/audaspace/FX/AUD_FaderReader.h
intern/audaspace/FX/AUD_HighpassFactory.cpp
intern/audaspace/FX/AUD_HighpassFactory.h
intern/audaspace/FX/AUD_HighpassReader.cpp [deleted file]
intern/audaspace/FX/AUD_HighpassReader.h [deleted file]
intern/audaspace/FX/AUD_IIRFilterFactory.cpp [new file with mode: 0644]
intern/audaspace/FX/AUD_IIRFilterFactory.h [new file with mode: 0644]
intern/audaspace/FX/AUD_IIRFilterReader.cpp [new file with mode: 0644]
intern/audaspace/FX/AUD_IIRFilterReader.h [moved from intern/audaspace/FX/AUD_VolumeReader.h with 54% similarity]
intern/audaspace/FX/AUD_LimiterFactory.cpp
intern/audaspace/FX/AUD_LimiterFactory.h
intern/audaspace/FX/AUD_LimiterReader.cpp
intern/audaspace/FX/AUD_LimiterReader.h
intern/audaspace/FX/AUD_LoopFactory.cpp
intern/audaspace/FX/AUD_LoopFactory.h
intern/audaspace/FX/AUD_LoopReader.cpp
intern/audaspace/FX/AUD_LoopReader.h
intern/audaspace/FX/AUD_LowpassFactory.cpp
intern/audaspace/FX/AUD_LowpassFactory.h
intern/audaspace/FX/AUD_LowpassReader.cpp [deleted file]
intern/audaspace/FX/AUD_PingPongFactory.cpp
intern/audaspace/FX/AUD_PingPongFactory.h
intern/audaspace/FX/AUD_PitchFactory.cpp
intern/audaspace/FX/AUD_PitchFactory.h
intern/audaspace/FX/AUD_PitchReader.cpp
intern/audaspace/FX/AUD_PitchReader.h
intern/audaspace/FX/AUD_RectifyFactory.cpp
intern/audaspace/FX/AUD_RectifyFactory.h
intern/audaspace/FX/AUD_ReverseFactory.cpp
intern/audaspace/FX/AUD_ReverseFactory.h
intern/audaspace/FX/AUD_ReverseReader.cpp
intern/audaspace/FX/AUD_ReverseReader.h
intern/audaspace/FX/AUD_SquareFactory.cpp
intern/audaspace/FX/AUD_SquareFactory.h
intern/audaspace/FX/AUD_SumFactory.cpp
intern/audaspace/FX/AUD_SumFactory.h
intern/audaspace/FX/AUD_SumReader.cpp [deleted file]
intern/audaspace/FX/AUD_SuperposeFactory.cpp [new file with mode: 0644]
intern/audaspace/FX/AUD_SuperposeFactory.h [new file with mode: 0644]
intern/audaspace/FX/AUD_SuperposeReader.cpp [new file with mode: 0644]
intern/audaspace/FX/AUD_SuperposeReader.h [new file with mode: 0644]
intern/audaspace/FX/AUD_VolumeFactory.cpp
intern/audaspace/FX/AUD_VolumeFactory.h
intern/audaspace/FX/AUD_VolumeReader.cpp [deleted file]
intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
intern/audaspace/OpenAL/AUD_OpenALDevice.h
intern/audaspace/Python/AUD_PyAPI.cpp [new file with mode: 0644]
intern/audaspace/Python/AUD_PyAPI.h [new file with mode: 0644]
intern/audaspace/SConscript
intern/audaspace/SDL/AUD_SDLDevice.cpp
intern/audaspace/SDL/AUD_SDLDevice.h
intern/audaspace/SRC/AUD_SRCResampleFactory.cpp
intern/audaspace/SRC/AUD_SRCResampleFactory.h
intern/audaspace/SRC/AUD_SRCResampleReader.cpp
intern/audaspace/SRC/AUD_SRCResampleReader.h
intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp
intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h
intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
intern/audaspace/ffmpeg/AUD_FFMPEGReader.h
intern/audaspace/fftw/AUD_BandPassReader.h
intern/audaspace/intern/AUD_3DMath.h [new file with mode: 0644]
intern/audaspace/intern/AUD_Buffer.cpp
intern/audaspace/intern/AUD_Buffer.h
intern/audaspace/intern/AUD_BufferReader.cpp
intern/audaspace/intern/AUD_BufferReader.h
intern/audaspace/intern/AUD_C-API.cpp
intern/audaspace/intern/AUD_C-API.h
intern/audaspace/intern/AUD_ChannelMapperFactory.cpp
intern/audaspace/intern/AUD_ChannelMapperFactory.h
intern/audaspace/intern/AUD_ChannelMapperReader.cpp
intern/audaspace/intern/AUD_ChannelMapperReader.h
intern/audaspace/intern/AUD_ConverterFactory.cpp
intern/audaspace/intern/AUD_ConverterFactory.h
intern/audaspace/intern/AUD_ConverterReader.cpp
intern/audaspace/intern/AUD_ConverterReader.h
intern/audaspace/intern/AUD_DefaultMixer.cpp [new file with mode: 0644]
intern/audaspace/intern/AUD_DefaultMixer.h [moved from intern/audaspace/FX/AUD_SumReader.h with 58% similarity]
intern/audaspace/intern/AUD_FileFactory.cpp
intern/audaspace/intern/AUD_FileFactory.h
intern/audaspace/intern/AUD_I3DDevice.h
intern/audaspace/intern/AUD_IDevice.h
intern/audaspace/intern/AUD_IFactory.h
intern/audaspace/intern/AUD_IReader.h
intern/audaspace/intern/AUD_LinearResampleFactory.cpp
intern/audaspace/intern/AUD_LinearResampleFactory.h
intern/audaspace/intern/AUD_LinearResampleReader.cpp
intern/audaspace/intern/AUD_LinearResampleReader.h
intern/audaspace/intern/AUD_Mixer.cpp
intern/audaspace/intern/AUD_Mixer.h
intern/audaspace/intern/AUD_MixerFactory.cpp
intern/audaspace/intern/AUD_MixerFactory.h
intern/audaspace/intern/AUD_NULLDevice.cpp
intern/audaspace/intern/AUD_NULLDevice.h
intern/audaspace/intern/AUD_ReadDevice.cpp
intern/audaspace/intern/AUD_ReadDevice.h
intern/audaspace/intern/AUD_Reference.h
intern/audaspace/intern/AUD_SequencerFactory.cpp
intern/audaspace/intern/AUD_SequencerFactory.h
intern/audaspace/intern/AUD_SequencerReader.cpp
intern/audaspace/intern/AUD_SequencerReader.h
intern/audaspace/intern/AUD_SilenceFactory.cpp [moved from intern/audaspace/intern/AUD_SourceCaps.h with 74% similarity]
intern/audaspace/intern/AUD_SilenceFactory.h [moved from intern/audaspace/FX/AUD_RectifyReader.h with 59% similarity]
intern/audaspace/intern/AUD_SilenceReader.cpp [moved from intern/audaspace/FX/AUD_SquareReader.cpp with 52% similarity]
intern/audaspace/intern/AUD_SilenceReader.h [moved from intern/audaspace/FX/AUD_LowpassReader.h with 52% similarity]
intern/audaspace/intern/AUD_SinusFactory.cpp
intern/audaspace/intern/AUD_SinusFactory.h
intern/audaspace/intern/AUD_SinusReader.cpp
intern/audaspace/intern/AUD_SinusReader.h
intern/audaspace/intern/AUD_SoftwareDevice.cpp
intern/audaspace/intern/AUD_SoftwareDevice.h
intern/audaspace/intern/AUD_Space.h
intern/audaspace/intern/AUD_StreamBufferFactory.cpp
intern/audaspace/intern/AUD_StreamBufferFactory.h
intern/audaspace/jack/AUD_JackDevice.cpp
intern/audaspace/jack/AUD_JackDevice.h
intern/audaspace/sndfile/AUD_SndFileFactory.cpp
intern/audaspace/sndfile/AUD_SndFileFactory.h
intern/audaspace/sndfile/AUD_SndFileReader.cpp
intern/audaspace/sndfile/AUD_SndFileReader.h
release/scripts/op/console_python.py
source/blender/blenkernel/intern/sound.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/space_logic/logic_window.c
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/intern/rna_actuator.c
source/blender/python/CMakeLists.txt
source/blender/python/SConscript
source/blender/python/doc/sphinx_doc_gen.py
source/blender/python/generic/blf_api.c
source/blender/python/generic/mathutils_color.c
source/blender/python/generic/mathutils_euler.c
source/blender/python/generic/mathutils_matrix.c
source/blender/python/generic/mathutils_quat.c
source/blender/python/generic/mathutils_vector.c
source/blender/python/intern/bpy.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm_init_exit.c
source/blender/windowmanager/intern/wm_window.c
source/blender/windowmanager/wm_window.h
source/creator/creator.c
source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
source/gameengine/Expressions/PyObjectPlus.h
source/gameengine/GameLogic/SCA_ISensor.cpp
source/gameengine/GameLogic/SCA_ISensor.h
source/gameengine/GameLogic/SCA_JoystickSensor.cpp
source/gameengine/GameLogic/SCA_PythonController.cpp
source/gameengine/Ketsji/KX_BlenderMaterial.cpp
source/gameengine/Ketsji/KX_BlenderMaterial.h
source/gameengine/Ketsji/KX_Camera.cpp
source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
source/gameengine/Ketsji/KX_ConstraintWrapper.h
source/gameengine/Ketsji/KX_KetsjiEngine.cpp
source/gameengine/Ketsji/KX_PolyProxy.cpp
source/gameengine/Ketsji/KX_PolyProxy.h
source/gameengine/Ketsji/KX_PolygonMaterial.cpp
source/gameengine/Ketsji/KX_PythonInit.cpp
source/gameengine/Ketsji/KX_SoundActuator.cpp
source/gameengine/Ketsji/KX_SoundActuator.h
source/gameengine/Ketsji/KX_VertexProxy.cpp
source/gameengine/Ketsji/KX_VertexProxy.h

index 0965a467201172cbfe5930306c29a68d4ee494c8..c1d59dcd3e9c145e48cc8fd753fd96ee37758da8 100644 (file)
@@ -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}")
index 20709c57ee5ee7a2304f82a0b3fc1fe4bc22a9a5..0c51e5241e41cffc293ae33547b41ad46281d019 100644 (file)
  */
 
 #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);
 }
index e475a19ccf62fee2710f2c25e15c3111c16cfd6e..2b90fa43bdfdbc659b4f3dd214f43e860fd57c2a 100644 (file)
@@ -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 (file)
index 67ab415..0000000
+++ /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 (file)
index 8ad1dda..0000000
+++ /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 (file)
index 0000000..9e14bcf
--- /dev/null
@@ -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 (file)
index 0000000..7e2b719
--- /dev/null
@@ -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
index fd0a53def7cfd603b273886f18d9e8c5474e3b27..874ff0f635144acc4cc405723feff3203674e8cb 100644 (file)
  */
 
 #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);
 }
index 69169531d7070681fa662c644f94982fa3cb6d61..30b7a402c574ae20e3f08a2521edb43312ea7128 100644 (file)
@@ -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 (file)
index 2129dfe..0000000
+++ /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 (file)
index b1cbd4e..0000000
+++ /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
similarity index 56%
rename from intern/audaspace/FX/AUD_RectifyReader.cpp
rename to intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp
index 5d3ce80e811e58f6eaedc8d34860b8e05d6c7c66..02ab6e185fee92e016bc9220d4ecb7b05552d50e 100644 (file)
  * ***** 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 (file)
index 0000000..6472c7b
--- /dev/null
@@ -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
index 25ce4faed4c93a74d030c6f5270b5096225af088..f98743d6fb74efcd18216cb25332aadfcfa8327d 100644 (file)
 
 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);
 }
index 5ad4b9ab99611185a7da0158b8fcdf9814b7ff3f..721262fb73f368e92490f9cd44869fe18d82c8b4 100644 (file)
@@ -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
index f2521f645aa9f8a8251a04b01bc50f327edb0f2a..e9f0c15b9b417922105ec2f111979bf3c9cc158f 100644 (file)
  */
 
 #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);
index 4662b455dfca8e907c84eae1f5de1751432511a8..121842b0c6b6792102fc967dc750b7f9dea4a63c 100644 (file)
@@ -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 (file)
index 0000000..9f625d0
--- /dev/null
@@ -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);
+}
similarity index 53%
rename from intern/audaspace/FX/AUD_SquareReader.h
rename to intern/audaspace/FX/AUD_DoubleFactory.h
index 63dda351445acd0f4996c670c099e38817b6b44f..f2e83b2e27a0589a85d3cbada0c74070a70f4c8c 100644 (file)
  * ***** 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
index 1e51a094427e5b507cc525166eb9f6122880b408..5c6ca6a1fc5f366b1b2efec30d74e08fc7bb2379 100644 (file)
  */
 
 #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;
                }
        }
index d82b81ec0baa93b61afdd80567ec1f0ca5e95670..d80ba33dfe3af263b2774c52f22e53ec37734b99 100644 (file)
@@ -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);
 };
 
index 882499416b7cd49424ce723765b7469687fec444..eda4e4e04b2ea7c87340189645a5328ecbd66e3d 100644 (file)
 #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;
 }
index 67259b9e6c3dffd0f9e636bcb633b39e918c1283..fd3746d0da3f5189f8f00b84c56aea4469ff1afb 100644 (file)
  */
 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
index 47026b88440b3fabdac7c559961d433cf6ad111e..b54ca279088fe62718b2e82afa6349c2418e651d 100644 (file)
 
 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);
index f64bf34077ddd579398dd61b5bcd8f91d219674d..c447f79bc6ec8d39f8b7283352af5f233c561f1d 100644 (file)
  */
 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);
 };
 
index c3b2c3f24fe4b0867e7be421c5cca8d5804fc369..4777da70404e17a12f3773c0747ea4ae588842af 100644 (file)
  */
 
 #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);
 }
index c79e5472e30609ab4f81aa8863d229d872090729..c31c6727d0370a827202ce1c9be65ab3ceb2c5f0 100644 (file)
@@ -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 (file)
index 71ccbfd..0000000
+++ /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 (file)
index ff9dd23..0000000
+++ /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
index 4357e11bd4396d76dbdce211bcf3c44315a99f3a..bbe9319c928cf927215fee5ea8f6b51c151ea373 100644 (file)
@@ -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);
 }
index 4999ccac8f1135ca9b7b21a672ee72efa1ffc8d8..af5d18538eae625fea7845ec752407a8261fe250 100644 (file)
@@ -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
index 4e919fff323f86e60c10937933012292969d5671..2292fa06102f97b635a179c8c174712e6f22da6a 100644 (file)
@@ -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;
        }
 }
index a75ac6e7a47553da010ed79e9aa68d80a142a3a1..d9d685af956b605f53398b81cda127d2224a7714 100644 (file)
@@ -27,7 +27,7 @@
 #define AUD_FADERREADER
 
 #include "AUD_EffectReader.h"
-class AUD_Buffer;
+#include "AUD_Buffer.h"
 
 /**
  * This class fades another reader.
@@ -37,25 +37,34 @@ class AUD_Buffer;
 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);
 };
 
index 384d36beab729ddf5835c91d1bc1ea11f16a091f..d222e7f615e7da48da5753d9f2f9c074479152c7 100644 (file)
  */
 
 #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);
 }
index 5e31053ed6c809677bee12cd6133faaf485eec15..1220157a776bf7d8d6cacbe49b8aac6f6efb4296 100644 (file)
@@ -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 (file)
index 36b1bb8..0000000
+++ /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 (file)
index dc28a62..0000000
+++ /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 (file)
index 0000000..8cd49a0
--- /dev/null
@@ -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 (file)
index 0000000..567d4f3
--- /dev/null
@@ -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 (file)
index 0000000..120c9f8
--- /dev/null
@@ -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;
+}
similarity index 54%
rename from intern/audaspace/FX/AUD_VolumeReader.h
rename to intern/audaspace/FX/AUD_IIRFilterReader.h
index 489f85b10f214d63d364b95eea0566b3ebde7b3d..303bc6d92dfd063a6515ad1a1c47f7fc91849584 100644 (file)
  * ***** 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
index 6f19575240a9ccf2e25eed4338f3b41f13f93fe8..75501afcec329d0f62421cbc627e23c93de3d3f8 100644 (file)
@@ -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);
 }
index 588fea6eb4b3176c63fc0a1ed8d5d4db70ac568e..5d9491f60aaf7e00d477e35647cdf8d5102336bb 100644 (file)
@@ -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
index 05882369001804c258c703a657c6ddb2a681ba55..dd7301213c938e7d855812bb6b03e44faed3286f 100644 (file)
 
 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)
                {
index 9921f5ee1b0f580386556d71c7898801f9473c2e..59d6096dcba26f703850bcedfbc40bcb6674f685 100644 (file)
@@ -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);
 };
 
index 90186f623ffd5a308b7512253ca83f090ad52b23..6805a8e4b426243daca32276e58e165b13483bf2 100644 (file)
 
 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);
 }
index c81d906b82e61b54e8351d39cb02370dce7c35d9..f9e358af52d555e6ce68db22b7185f0fc3d6297b 100644 (file)
@@ -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
index 3bcd8c2f9d32e4484bc117b1569dd315dbeb0848..7521f914a5c3bf7f61abf0c98e4e387e1c0553ab 100644 (file)
 #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;
index e61a49cb0db39c4c13c1a7c4c7dc259f9ae4e6b0..e0ed4cb6bf33f0f9ace7ee83f97f7ccdec8c3a1e 100644 (file)
@@ -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);
 };
 
index 05dc5ff3994d0617031e0655b4d78f48b972c60d..9244e07631b483773abbbb6e78999525d1169795 100644 (file)
  */
 
 #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);
 }
index 8a419823de02edc1b2274996c26ead7a6b87faa8..61b76510a9e2e3f53b45643284f12b3780f289fc 100644 (file)
@@ -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 (file)
index 6dc0bf6..0000000
+++ /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;
-               }
-       }
-}
index 8b72afe05e72468c56036e02b5b6b9224155a77f..b3aaa9e80a45aaeb64321b1453d6c0247c29dd0e 100644 (file)
 #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);
 }
index b8854da550a85c1518bb06a865ddf0e7d9fe7b08..82aedca8f7f7825cf23f81295adbd426457701d6 100644 (file)
  */
 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
index 5f814283c12a17b3c0a2d7dd82e2d063dc00403e..be285562db3711615c4e97c8166ff0e8afbd4d33 100644 (file)
 
 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);
 }
index 96c4d0d7e9209832675b5596889b56d585c6969c..52b9b7d99e5ebfa44ddcee808d5d3e2c644fc742 100644 (file)
@@ -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
index c53264e1350a72d22a55c96339ae39b92ef51d8b..19c3be31968eb8ef682bcc0b23837855410a08ef 100644 (file)
 #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));
index 440e9cc843c08e7dfe7ef8f97e7954d90ec39d0d..cc188cf0ee4a1fc28c6be3b6a86abdd426fe3478 100644 (file)
@@ -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
index f97defd793b6dd8bb92f521aac69612b4f1379a7..2228f949dfeeadb806902e1addfa4d82095b5f5c 100644 (file)
  */
 
 #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);
 }
index ed00620d3183e99dd8608de37c4566a4a482b278..d8b39e83fdfca7dba12090d4dddcef866a88c86f 100644 (file)
  */
 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
index 1242641c350928fded7f271ec4f6eac4b26cef00..1002e2de87eb0956305e9e9ad0d13570abfc65d0 100644 (file)
 #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());
 }
index 4b664c47281db5b5c7e54fdda1d1cf991b8f3c5e..a1995ee68f92c9ca616c4247eae20bf9b4b3bb72 100644 (file)
  */
 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
index 82d6c70ce53fa48eafaabddf556286d01aad5cd8..c651ea7957726eb556c25d60a5e30f889949abf7 100644 (file)
  */
 
 #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();
 }
index 045d2ac5a8ec714c3e5179f14a31f968afbfc7c4..8eb960a5dee7bd89aa33ad051b66f64fcb27bb4f 100644 (file)
@@ -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);
 };
 
index 638acaa9a327a3c3403f853ee06516fa00d7fdee..c321a13d79a0e482753f0b4725dcb255db0e956b 100644 (file)
  */
 
 #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));
 }
index dfbe5ae2887f9bc4e66d734afcd64d8d112b76d4..da87dc6f8889735b3ed9371df640b2d33df4ebe8 100644 (file)
@@ -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
index f7990aab8a162ba2fa5ee8da9760e0cb23475ba6..a128e50504cab2e1a6d4409e7b3ac60191971e72 100644 (file)
  */
 
 #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);
 }
index 5cb48e26b1042101c4436c742dc8deb2c2d9a14d..045a0a3a625c0fb1fd54620622e5f91e1d67dca3 100644 (file)
  */
 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 (file)
index 0874779..0000000
+++ /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 (file)
index 0000000..6bfc112
--- /dev/null
@@ -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 (file)
index 0000000..a7fde2c
--- /dev/null
@@ -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 (file)
index 0000000..546b79a
--- /dev/null
@@ -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 (file)
index 0000000..eeceb9a
--- /dev/null
@@ -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
index fbde608aa122c69f92d6d1772cd4d2a4c82cc3b3..1b341a5a51acbe0a146eaafa530c3dad707e57b7 100644 (file)
  */
 
 #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);
 }
index 09f91241b4705c483a508236e89b191ff89a0187..a086aab4640ab4e74e4ff9d4a1f710d7faa5c537 100644 (file)
@@ -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 (file)
index f094c1e..0000000
+++ /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;
-}
index 796764989ba22d58bae29b682d696a91a7694de0..aa7cfcfd880d36f481680c80acd993d269f29556 100644 (file)
@@ -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;
index cb8c83ab810e247e5bfdf972d543a9e997bfc9aa..985954fc20b39d748a4e63783a79a42a7e4e87b4 100644 (file)
@@ -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>
@@ -63,11 +62,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.
         */
@@ -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 (file)
index 0000000..4b1298b
--- /dev/null
@@ -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;
+               }
+   &