Merge with trunk r37757.
authorJoerg Mueller <nexyon@gmail.com>
Thu, 23 Jun 2011 17:30:56 +0000 (17:30 +0000)
committerJoerg Mueller <nexyon@gmail.com>
Thu, 23 Jun 2011 17:30:56 +0000 (17:30 +0000)
264 files changed:
intern/audaspace/CMakeLists.txt
intern/audaspace/FX/AUD_AccumulatorFactory.cpp
intern/audaspace/FX/AUD_AccumulatorFactory.h
intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp
intern/audaspace/FX/AUD_BaseIIRFilterReader.h
intern/audaspace/FX/AUD_ButterworthFactory.cpp
intern/audaspace/FX/AUD_ButterworthFactory.h
intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp
intern/audaspace/FX/AUD_CallbackIIRFilterReader.h
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
intern/audaspace/FX/AUD_DoubleFactory.h
intern/audaspace/FX/AUD_DoubleReader.cpp
intern/audaspace/FX/AUD_DoubleReader.h
intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp [new file with mode: 0644]
intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h [new file with mode: 0644]
intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp [new file with mode: 0644]
intern/audaspace/FX/AUD_DynamicIIRFilterReader.h [new file with mode: 0644]
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_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_IIRFilterFactory.cpp
intern/audaspace/FX/AUD_IIRFilterFactory.h
intern/audaspace/FX/AUD_IIRFilterReader.cpp
intern/audaspace/FX/AUD_IIRFilterReader.h
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_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_SuperposeFactory.cpp
intern/audaspace/FX/AUD_SuperposeFactory.h
intern/audaspace/FX/AUD_SuperposeReader.cpp
intern/audaspace/FX/AUD_SuperposeReader.h
intern/audaspace/FX/AUD_VolumeFactory.cpp
intern/audaspace/FX/AUD_VolumeFactory.h
intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
intern/audaspace/OpenAL/AUD_OpenALDevice.h
intern/audaspace/Python/AUD_PyAPI.cpp
intern/audaspace/Python/AUD_PyAPI.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.cpp
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_ConverterFunctions.cpp
intern/audaspace/intern/AUD_ConverterReader.cpp
intern/audaspace/intern/AUD_ConverterReader.h
intern/audaspace/intern/AUD_DefaultMixer.cpp [deleted file]
intern/audaspace/intern/AUD_FileFactory.cpp
intern/audaspace/intern/AUD_FileFactory.h
intern/audaspace/intern/AUD_I3DDevice.h
intern/audaspace/intern/AUD_I3DHandle.h [new file with mode: 0644]
intern/audaspace/intern/AUD_IDevice.h
intern/audaspace/intern/AUD_IFactory.h
intern/audaspace/intern/AUD_IHandle.h [new file with mode: 0644]
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_Reference.h
intern/audaspace/intern/AUD_ReferenceHandler.cpp [moved from intern/audaspace/intern/AUD_ResampleFactory.h with 81% similarity]
intern/audaspace/intern/AUD_ResampleReader.cpp [new file with mode: 0644]
intern/audaspace/intern/AUD_ResampleReader.h [moved from intern/audaspace/intern/AUD_DefaultMixer.h with 57% similarity]
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
intern/audaspace/intern/AUD_SilenceFactory.h
intern/audaspace/intern/AUD_SilenceReader.cpp
intern/audaspace/intern/AUD_SilenceReader.h
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/sndfile/AUD_SndFileFactory.cpp
intern/audaspace/sndfile/AUD_SndFileFactory.h
intern/audaspace/sndfile/AUD_SndFileReader.cpp
intern/audaspace/sndfile/AUD_SndFileReader.h
release/scripts/modules/bpy_types.py
release/scripts/modules/mocap_tools.py [new file with mode: 0644]
release/scripts/modules/retarget.py [new file with mode: 0644]
release/scripts/presets/ffmpeg/DV.py
release/scripts/presets/ffmpeg/DVD.py
release/scripts/presets/ffmpeg/SVCD.py
release/scripts/presets/ffmpeg/VCD.py
release/scripts/startup/bl_operators/nla.py
release/scripts/startup/bl_operators/object.py
release/scripts/startup/bl_ui/properties_object_constraint.py
release/scripts/startup/bl_ui/properties_render.py
release/scripts/startup/bl_ui/properties_scene.py
release/scripts/startup/bl_ui/space_sequencer.py
release/scripts/startup/bl_ui/space_userpref.py
release/scripts/startup/bl_ui/space_view3d.py
source/blender/blenfont/BLF_api.h
source/blender/blenfont/intern/blf.c
source/blender/blenkernel/BKE_constraint.h
source/blender/blenkernel/BKE_sound.h
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/fcurve.c
source/blender/blenkernel/intern/fmodifier.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/seqeffects.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/sound.c
source/blender/blenkernel/intern/writeffmpeg.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/collada/AnimationExporter.cpp [new file with mode: 0644]
source/blender/collada/AnimationExporter.h [new file with mode: 0644]
source/blender/collada/AnimationImporter.cpp
source/blender/collada/AnimationImporter.h
source/blender/collada/ArmatureImporter.cpp
source/blender/collada/ArmatureImporter.h
source/blender/collada/CMakeLists.txt
source/blender/collada/DocumentExporter.cpp
source/blender/collada/DocumentImporter.cpp
source/blender/collada/SkinInfo.cpp
source/blender/editors/animation/anim_channels_defines.c
source/blender/editors/animation/anim_channels_edit.c
source/blender/editors/animation/anim_deps.c
source/blender/editors/animation/anim_filter.c
source/blender/editors/animation/anim_markers.c
source/blender/editors/animation/fmodifier_ui.c
source/blender/editors/animation/keyframes_draw.c
source/blender/editors/animation/keyframes_edit.c
source/blender/editors/animation/keyframes_general.c
source/blender/editors/animation/keyingsets.c
source/blender/editors/armature/poseobject.c
source/blender/editors/include/ED_anim_api.h
source/blender/editors/include/ED_markers.h
source/blender/editors/interface/interface_style.c
source/blender/editors/interface/resources.c
source/blender/editors/object/object_constraint.c
source/blender/editors/space_action/action_draw.c
source/blender/editors/space_action/action_edit.c
source/blender/editors/space_action/action_ops.c
source/blender/editors/space_action/action_select.c
source/blender/editors/space_graph/graph_buttons.c
source/blender/editors/space_graph/graph_draw.c
source/blender/editors/space_graph/graph_edit.c
source/blender/editors/space_graph/graph_ops.c
source/blender/editors/space_graph/graph_select.c
source/blender/editors/space_graph/graph_utils.c
source/blender/editors/space_graph/space_graph.c
source/blender/editors/space_logic/logic_window.c
source/blender/editors/space_nla/nla_buttons.c
source/blender/editors/space_nla/nla_channels.c
source/blender/editors/space_nla/nla_draw.c
source/blender/editors/space_nla/nla_edit.c
source/blender/editors/space_nla/nla_ops.c
source/blender/editors/space_nla/nla_select.c
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/editors/space_text/text_draw.c
source/blender/editors/space_view3d/drawarmature.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/editors/transform/transform_ops.c
source/blender/makesdna/DNA_actuator_types.h
source/blender/makesdna/DNA_anim_types.h
source/blender/makesdna/DNA_armature_types.h
source/blender/makesdna/DNA_constraint_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_actuator.c
source/blender/makesrna/intern/rna_animation.c
source/blender/makesrna/intern/rna_armature.c
source/blender/makesrna/intern/rna_constraint.c
source/blender/makesrna/intern/rna_fcurve.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_sequencer.c
source/blender/makesrna/intern/rna_userdef.c
source/blender/windowmanager/intern/wm_files.c
source/gameengine/Converter/BL_ActionActuator.cpp
source/gameengine/Converter/BL_ActionActuator.h
source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp
source/gameengine/Converter/KX_BlenderScalarInterpolator.h
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Converter/KX_IpoConvert.cpp
source/gameengine/Converter/KX_IpoConvert.h
source/gameengine/Expressions/PyObjectPlus.h
source/gameengine/Ketsji/BL_Action.cpp [new file with mode: 0644]
source/gameengine/Ketsji/BL_Action.h [new file with mode: 0644]
source/gameengine/Ketsji/BL_ActionManager.cpp [new file with mode: 0644]
source/gameengine/Ketsji/BL_ActionManager.h [new file with mode: 0644]
source/gameengine/Ketsji/CMakeLists.txt
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_SoundActuator.cpp
source/gameengine/Ketsji/KX_SoundActuator.h
source/gameengine/Ketsji/SConscript
source/gameengine/SceneGraph/SG_IObject.cpp
source/gameengine/SceneGraph/SG_IObject.h

index ab88c9ecabd23601efdc48dc7c75f396825592ad..4b2a3c42ba4cdeb33cd87efcb7a8605969ed0bc9 100644 (file)
@@ -41,6 +41,8 @@ set(SRC
        FX/AUD_DelayReader.cpp
        FX/AUD_DoubleFactory.cpp
        FX/AUD_DoubleReader.cpp
+       FX/AUD_DynamicIIRFilterFactory.cpp
+       FX/AUD_DynamicIIRFilterReader.cpp
        FX/AUD_EffectFactory.cpp
        FX/AUD_EffectReader.cpp
        FX/AUD_EnvelopeFactory.cpp
@@ -82,13 +84,13 @@ set(SRC
        intern/AUD_ConverterFunctions.h
        intern/AUD_ConverterReader.cpp
        intern/AUD_ConverterReader.h
-       intern/AUD_DefaultMixer.cpp
-       intern/AUD_DefaultMixer.h
        intern/AUD_FileFactory.cpp
        intern/AUD_FileFactory.h
        intern/AUD_I3DDevice.h
+       intern/AUD_I3DHandle.h
        intern/AUD_IDevice.h
        intern/AUD_IFactory.h
+       intern/AUD_IHandle.h
        intern/AUD_IReader.h
        intern/AUD_LinearResampleFactory.cpp
        intern/AUD_LinearResampleFactory.h
@@ -104,7 +106,9 @@ set(SRC
        intern/AUD_ReadDevice.cpp
        intern/AUD_ReadDevice.h
        intern/AUD_Reference.h
-       intern/AUD_ResampleFactory.h
+       intern/AUD_ReferenceHandler.cpp
+       intern/AUD_ResampleReader.cpp
+       intern/AUD_ResampleReader.h
        intern/AUD_SequencerFactory.cpp
        intern/AUD_SequencerFactory.h
        intern/AUD_SequencerReader.cpp
@@ -131,6 +135,8 @@ set(SRC
        FX/AUD_DelayReader.h
        FX/AUD_DoubleFactory.h
        FX/AUD_DoubleReader.h
+       FX/AUD_DynamicIIRFilterFactory.h
+       FX/AUD_DynamicIIRFilterReader.h
        FX/AUD_EffectFactory.h
        FX/AUD_EffectReader.h
        FX/AUD_EnvelopeFactory.h
index d60924958b162ea25af477a565db5d7bac25c66b..0dffa7fc9ea57f8916e07c8bb9c3bd41cf3320ac 100644 (file)
@@ -32,7 +32,7 @@
 #include "AUD_AccumulatorFactory.h"
 #include "AUD_CallbackIIRFilterReader.h"
 
-sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless)
+sample_t AUD_AccumulatorFactory::accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless)
 {
        float in = reader->x(0);
        float lastin = reader->x(-1);
@@ -42,7 +42,7 @@ sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* us
        return out;
 }
 
-sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
+sample_t AUD_AccumulatorFactory::accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
 {
        float in = reader->x(0);
        float lastin = reader->x(-1);
@@ -52,14 +52,14 @@ sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
        return out;
 }
 
-AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_IFactory* factory,
+AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_Reference<AUD_IFactory> factory,
                                                                                           bool additive) :
                AUD_EffectFactory(factory),
                m_additive(additive)
 {
 }
 
-AUD_IReader* AUD_AccumulatorFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_AccumulatorFactory::createReader()
 {
        return new AUD_CallbackIIRFilterReader(getReader(), 2, 2,
                                                        m_additive ? accumulatorFilterAdditive : accumulatorFilter);
index 3c3b32ce0711d5c0b6f6a108515093accf54f41a..5838ccee7f081f98827302bafdf6ea7ad331916a 100644 (file)
@@ -33,6 +33,7 @@
 #define AUD_ACCUMULATORFACTORY
 
 #include "AUD_EffectFactory.h"
+class AUD_CallbackIIRFilterReader;
 
 /**
  * This factory creates an accumulator reader.
@@ -55,9 +56,12 @@ public:
         * \param factory The input factory.
         * \param additive Whether the accumulator is additive.
         */
-       AUD_AccumulatorFactory(AUD_IFactory* factory, bool additive = false);
+       AUD_AccumulatorFactory(AUD_Reference<AUD_IFactory> factory, bool additive = false);
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
+
+       static sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless);
+       static sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless);
 };
 
 #endif //AUD_ACCUMULATORFACTORY
index 563722d921397b00496e0310fba4b851c9f93900..29ff6d90080b17df533cec5b3432ccecf03037bd 100644 (file)
 
 #include <cstring>
 
-#define CC m_channels + m_channel
+#define CC m_specs.channels + m_channel
 
-AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_IReader* reader, int in,
+AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in,
                                                                                                 int out) :
                AUD_EffectReader(reader),
-               m_channels(reader->getSpecs().channels),
+               m_specs(reader->getSpecs()),
                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];
+       m_x = new sample_t[m_xlen * m_specs.channels];
+       m_y = new sample_t[m_ylen * m_specs.channels];
 
-       memset(m_x, 0, sizeof(sample_t) * in * m_channels);
-       memset(m_y, 0, sizeof(sample_t) * out * m_channels);
+       memset(m_x, 0, sizeof(sample_t) * m_xlen * m_specs.channels);
+       memset(m_y, 0, sizeof(sample_t) * m_ylen * m_specs.channels);
 }
 
 AUD_BaseIIRFilterReader::~AUD_BaseIIRFilterReader()
@@ -55,24 +55,77 @@ AUD_BaseIIRFilterReader::~AUD_BaseIIRFilterReader()
        delete[] m_y;
 }
 
-void AUD_BaseIIRFilterReader::read(int & length, sample_t* & buffer)
+void AUD_BaseIIRFilterReader::setLengths(int in, int out)
 {
-       sample_t* buf;
+       if(in != m_xlen)
+       {
+               sample_t* xn = new sample_t[in * m_specs.channels];
+               memset(xn, 0, sizeof(sample_t) * in * m_specs.channels);
+
+               for(m_channel = 0; m_channel < m_specs.channels; m_channel++)
+               {
+                       for(int i = 1; i <= in && i <= m_xlen; i++)
+                       {
+                               xn[(in - i) * CC] = x(-i);
+                       }
+               }
+
+               delete[] m_x;
+               m_x = xn;
+               m_xpos = 0;
+               m_xlen = in;
+       }
+
+       if(out != m_ylen)
+       {
+               sample_t* yn = new sample_t[out * m_specs.channels];
+               memset(yn, 0, sizeof(sample_t) * out * m_specs.channels);
+
+               for(m_channel = 0; m_channel < m_specs.channels; m_channel++)
+               {
+                       for(int i = 1; i <= out && i <= m_ylen; i++)
+                       {
+                               yn[(out - i) * CC] = y(-i);
+                       }
+               }
+
+               delete[] m_y;
+               m_y = yn;
+               m_ypos = 0;
+               m_ylen = out;
+       }
+}
+
+void AUD_BaseIIRFilterReader::read(int& length, bool& eos, sample_t* buffer)
+{
+       AUD_Specs specs = m_reader->getSpecs();
+       if(specs.channels != m_specs.channels)
+       {
+               m_specs.channels = specs.channels;
+
+               delete[] m_x;
+               delete[] m_y;
 
-       int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs());
+               m_x = new sample_t[m_xlen * m_specs.channels];
+               m_y = new sample_t[m_ylen * m_specs.channels];
 
-       m_reader->read(length, buf);
+               memset(m_x, 0, sizeof(sample_t) * m_xlen * m_specs.channels);
+               memset(m_y, 0, sizeof(sample_t) * m_ylen * m_specs.channels);
+       }
 
-       if(m_buffer.getSize() < length * samplesize)
-               m_buffer.resize(length * samplesize);
+       if(specs.rate != m_specs.rate)
+       {
+               m_specs = specs;
+               sampleRateChanged(m_specs.rate);
+       }
 
-       buffer = m_buffer.getBuffer();
+       m_reader->read(length, eos, buffer);
 
-       for(m_channel = 0; m_channel < m_channels; m_channel++)
+       for(m_channel = 0; m_channel < m_specs.channels; m_channel++)
        {
                for(int i = 0; i < length; i++)
                {
-                       m_x[m_xpos * CC] = buf[i * CC];
+                       m_x[m_xpos * CC] = buffer[i * CC];
                        m_y[m_ypos * CC] = buffer[i * CC] = filter();
 
                        m_xpos = (m_xpos + 1) % m_xlen;
@@ -80,3 +133,7 @@ void AUD_BaseIIRFilterReader::read(int & length, sample_t* & buffer)
                }
        }
 }
+
+void AUD_BaseIIRFilterReader::sampleRateChanged(AUD_SampleRate rate)
+{
+}
index 436e6469a58284ce86d875347878fc0e2fade4ee..644bcffbfafff80b4463cf5c06c0b99d312f60bd 100644 (file)
@@ -42,24 +42,19 @@ class AUD_BaseIIRFilterReader : public AUD_EffectReader
 {
 private:
        /**
-        * Channel count.
+        * Specs.
         */
-       const int m_channels;
+       AUD_Specs m_specs;
 
        /**
         * Length of input samples needed.
         */
-       const int m_xlen;
+       int m_xlen;
 
        /**
         * Length of output samples needed.
         */
-       const int m_ylen;
-
-       /**
-        * The playback buffer.
-        */
-       AUD_Buffer m_buffer;
+       int m_ylen;
 
        /**
         * The last in samples array.
@@ -97,24 +92,27 @@ protected:
         * \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);
+       AUD_BaseIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, int out);
+
+       void setLengths(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];
+               return m_x[(m_xpos + pos + m_xlen) % m_xlen * m_specs.channels + m_channel];
        }
 
        inline sample_t y(int pos)
        {
-               return m_y[(m_ypos + pos + m_ylen) % m_ylen * m_channels + m_channel];
+               return m_y[(m_ypos + pos + m_ylen) % m_ylen * m_specs.channels + m_channel];
        }
 
        virtual ~AUD_BaseIIRFilterReader();
 
-       virtual void read(int & length, sample_t* & buffer);
+       virtual void read(int& length, bool& eos, sample_t* buffer);
 
        virtual sample_t filter()=0;
+       virtual void sampleRateChanged(AUD_SampleRate rate);
 };
 
 #endif //AUD_BASEIIRFILTERREADER
index ea957c81ed37733bae638771ce73de8110c6b174..4b45512ffa64c2b3dbb640796703f29a183efce1 100644 (file)
 #define BWPB41 0.76536686473
 #define BWPB42 1.84775906502
 
-AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_IFactory* factory,
+AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory,
                                                                                           float frequency) :
-               AUD_EffectFactory(factory),
+               AUD_DynamicIIRFilterFactory(factory),
                m_frequency(frequency)
 {
 }
 
-AUD_IReader* AUD_ButterworthFactory::createReader() const
+void AUD_ButterworthFactory::recalculateCoefficients(AUD_SampleRate rate,
+                                                                                                        std::vector<float> &b,
+                                                                                                        std::vector<float> &a)
 {
-       AUD_IReader* reader = getReader();
-
-       // calculate coefficients
-       float omega = 2 * tan(m_frequency * M_PI / reader->getSpecs().rate);
+       float omega = 2 * tan(m_frequency * M_PI / rate);
        float o2 = omega * omega;
        float o4 = o2 * o2;
        float x1 = o2 + 2 * BWPB41 * omega + 4;
@@ -62,7 +61,6 @@ AUD_IReader* AUD_ButterworthFactory::createReader() const
        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);
@@ -73,6 +71,4 @@ AUD_IReader* AUD_ButterworthFactory::createReader() const
        b.push_back(6 * o4 / norm);
        b.push_back(b[1]);
        b.push_back(b[0]);
-
-       return new AUD_IIRFilterReader(reader, b, a);
 }
index c8b731449c4e90d04ca223cf6a77b35ff374436a..16d0b3dbc23a0b4d0cec3a3d79c3dac24ac3170f 100644 (file)
 #ifndef AUD_BUTTERWORTHFACTORY
 #define AUD_BUTTERWORTHFACTORY
 
-#include "AUD_EffectFactory.h"
+#include "AUD_DynamicIIRFilterFactory.h"
 
 /**
  * This factory creates a butterworth filter reader.
  */
-class AUD_ButterworthFactory : public AUD_EffectFactory
+class AUD_ButterworthFactory : public AUD_DynamicIIRFilterFactory
 {
 private:
        /**
@@ -55,9 +55,11 @@ public:
         * \param factory The input factory.
         * \param frequency The cutoff frequency.
         */
-       AUD_ButterworthFactory(AUD_IFactory* factory, float frequency);
+       AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory, float frequency);
 
-       virtual AUD_IReader* createReader() const;
+       virtual void recalculateCoefficients(AUD_SampleRate rate,
+                                                                                std::vector<float>& b,
+                                                                                std::vector<float>& a);
 };
 
 #endif //AUD_BUTTERWORTHFACTORY
index 2f9bb7762a04af704d08badcc550ed68a4afe19e..e6c83322435dc72a2d5226afd303bd587bb44013 100644 (file)
@@ -31,7 +31,7 @@
 
 #include "AUD_CallbackIIRFilterReader.h"
 
-AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(AUD_IReader* reader,
+AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(AUD_Reference<AUD_IReader> reader,
                                                                                                                 int in, int out,
                                                                                                                 doFilterIIR doFilter,
                                                                                                                 endFilterIIR endFilter,
index a969db7297ef0692adf236323b51d49be701ea0f..6d53edeecc2e1c90264db1701ca958a80727cc01 100644 (file)
@@ -76,7 +76,7 @@ public:
         * \param endFilter The finishing callback.
         * \param data Data pointer for the callbacks.
         */
-       AUD_CallbackIIRFilterReader(AUD_IReader* reader, int in, int out,
+       AUD_CallbackIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, int out,
                                                                doFilterIIR doFilter,
                                                                endFilterIIR endFilter = 0,
                                                                void* data = 0);
index 1d2d99adc03fcf12bf4003a72cd226c414fa61eb..e452870281d27c2f79c125635a6112e85c6275ea 100644 (file)
@@ -33,7 +33,7 @@
 #include "AUD_DelayReader.h"
 #include "AUD_Space.h"
 
-AUD_DelayFactory::AUD_DelayFactory(AUD_IFactory* factory, float delay) :
+AUD_DelayFactory::AUD_DelayFactory(AUD_Reference<AUD_IFactory> factory, float delay) :
                AUD_EffectFactory(factory),
                m_delay(delay)
 {
@@ -44,7 +44,7 @@ float AUD_DelayFactory::getDelay() const
        return m_delay;
 }
 
-AUD_IReader* AUD_DelayFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_DelayFactory::createReader()
 {
        return new AUD_DelayReader(getReader(), m_delay);
 }
index 1e67cd689909c5dd7b3e8fb93903f7533cb65e6e..5ab7f850d2f1700f87fb8d40fbb50ddc10e23e23 100644 (file)
@@ -55,14 +55,14 @@ public:
         * \param factory The input factory.
         * \param delay The desired delay in seconds.
         */
-       AUD_DelayFactory(AUD_IFactory* factory, float delay = 0);
+       AUD_DelayFactory(AUD_Reference<AUD_IFactory> factory, float delay = 0);
 
        /**
         * Returns the delay in seconds.
         */
        float getDelay() const;
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
 };
 
 #endif //AUD_DELAYFACTORY
index 374b876455d42f95a24aa238d21937564c5c689d..7d58b3dae4f33c82269e4e85c17df2c864b097fa 100644 (file)
 
 #include <cstring>
 
-AUD_DelayReader::AUD_DelayReader(AUD_IReader* reader, float delay) :
+AUD_DelayReader::AUD_DelayReader(AUD_Reference<AUD_IReader> reader, float delay) :
                AUD_EffectReader(reader),
                m_delay(int(delay * reader->getSpecs().rate)),
-               m_remdelay(int(delay * reader->getSpecs().rate)),
-               m_empty(true)
+               m_remdelay(int(delay * reader->getSpecs().rate))
 {
 }
 
@@ -70,49 +69,30 @@ int AUD_DelayReader::getPosition() const
        return m_reader->getPosition() + m_delay;
 }
 
-void AUD_DelayReader::read(int & length, sample_t* & buffer)
+void AUD_DelayReader::read(int& length, bool& eos, sample_t* buffer)
 {
        if(m_remdelay > 0)
        {
                AUD_Specs specs = m_reader->getSpecs();
                int samplesize = AUD_SAMPLE_SIZE(specs);
 
-               if(m_buffer.getSize() < length * samplesize)
-               {
-                       m_buffer.resize(length * samplesize);
-                       m_empty = false;
-               }
-
-               buffer = m_buffer.getBuffer();
-
                if(length > m_remdelay)
                {
-                       if(!m_empty)
-                               memset(buffer, 0, m_remdelay * samplesize);
+                       memset(buffer, 0, m_remdelay * samplesize);
 
                        int len = length - m_remdelay;
-                       sample_t* buf;
-                       m_reader->read(len, buf);
-
-                       memcpy(buffer + m_remdelay * specs.channels,
-                                  buf, len * samplesize);
+                       m_reader->read(len, eos, buffer + m_remdelay * specs.channels);
 
-                       if(len < length-m_remdelay)
-                               length = m_remdelay + len;
+                       length = m_remdelay + len;
 
                        m_remdelay = 0;
-                       m_empty = false;
                }
                else
                {
-                       if(!m_empty)
-                       {
-                               memset(buffer, 0, length * samplesize);
-                               m_empty = true;
-                       }
+                       memset(buffer, 0, length * samplesize);
                        m_remdelay -= length;
                }
        }
        else
-               m_reader->read(length, buffer);
+               m_reader->read(length, eos, buffer);
 }
index 5f0af660bdf90bf5c36fa27d070b660754986119..a89afe73b372be8e9977a32b3e40c3aa97a1b6f1 100644 (file)
 class AUD_DelayReader : public AUD_EffectReader
 {
 private:
-       /**
-        * The playback buffer.
-        */
-       AUD_Buffer m_buffer;
-
        /**
         * The delay level.
         */
@@ -56,11 +51,6 @@ private:
         */
        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&);
@@ -71,12 +61,12 @@ public:
         * \param reader The reader to read from.
         * \param delay The delay in seconds.
         */
-       AUD_DelayReader(AUD_IReader* reader, float delay);
+       AUD_DelayReader(AUD_Reference<AUD_IReader> reader, float delay);
 
        virtual void seek(int position);
        virtual int getLength() const;
        virtual int getPosition() const;
-       virtual void read(int & length, sample_t* & buffer);
+       virtual void read(int& length, bool& eos, sample_t* buffer);
 };
 
 #endif //AUD_DELAYREADER
index 7a40f1f8c96b07def0543d307370adc0888109b1..e1e6ba504359c03adf82c789ffcb11582d92825a 100644 (file)
 #include "AUD_DoubleFactory.h"
 #include "AUD_DoubleReader.h"
 
-AUD_DoubleFactory::AUD_DoubleFactory(AUD_IFactory* factory1, AUD_IFactory* factory2) :
+AUD_DoubleFactory::AUD_DoubleFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2) :
                m_factory1(factory1), m_factory2(factory2)
 {
 }
 
-AUD_IReader* AUD_DoubleFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_DoubleFactory::createReader()
 {
-       AUD_IReader* reader1 = m_factory1->createReader();
-       AUD_IReader* reader2;
-
-       try
-       {
-               reader2 = m_factory2->createReader();
-       }
-       catch(AUD_Exception&)
-       {
-               delete reader1;
-               throw;
-       }
+       AUD_Reference<AUD_IReader> reader1 = m_factory1->createReader();
+       AUD_Reference<AUD_IReader> reader2 = m_factory2->createReader();
 
        return new AUD_DoubleReader(reader1, reader2);
 }
index 52a299c7157dc79cdc4221d7e10240bff18f08d5..f2be71324427d8f6b7578876afa846a6aef64d34 100644 (file)
@@ -44,12 +44,12 @@ private:
        /**
         * First played factory.
         */
-       AUD_IFactory* m_factory1;
+       AUD_Reference<AUD_IFactory> m_factory1;
 
        /**
         * Second played factory.
         */
-       AUD_IFactory* m_factory2;
+       AUD_Reference<AUD_IFactory> m_factory2;
 
        // hide copy constructor and operator=
        AUD_DoubleFactory(const AUD_DoubleFactory&);
@@ -61,9 +61,9 @@ public:
         * \param factory1 The first input factory.
         * \param factory2 The second input factory.
         */
-       AUD_DoubleFactory(AUD_IFactory* factory1, AUD_IFactory* factory2);
+       AUD_DoubleFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2);
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
 };
 
 #endif //AUD_DOUBLEFACTORY
index 113bed14ce3a0bd5b25354ed9f2dd07242bf2311..fd2419a86e8d6b0a38e3ec23bba5cb012f3e260d 100644 (file)
 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) :
+AUD_DoubleReader::AUD_DoubleReader(AUD_Reference<AUD_IReader> reader1,
+                                                                  AUD_Reference<AUD_IReader> reader2) :
                m_reader1(reader1), m_reader2(reader2), m_finished1(false)
 {
        AUD_Specs s1, s2;
        s1 = reader1->getSpecs();
        s2 = reader2->getSpecs();
-       if(memcmp(&s1, &s2, sizeof(AUD_Specs)) != 0)
-       {
-               delete reader1;
-               delete reader2;
-               AUD_THROW(AUD_ERROR_SPECS, specs_error);
-       }
 }
 
 AUD_DoubleReader::~AUD_DoubleReader()
 {
-       delete m_reader1;
-       delete m_reader2;
 }
 
 bool AUD_DoubleReader::isSeekable() const
@@ -90,43 +82,19 @@ int AUD_DoubleReader::getPosition() const
 
 AUD_Specs AUD_DoubleReader::getSpecs() const
 {
-       return m_reader1->getSpecs();
+       return m_finished1 ? m_reader1->getSpecs() : m_reader2->getSpecs();
 }
 
-void AUD_DoubleReader::read(int & length, sample_t* & buffer)
+void AUD_DoubleReader::read(int& length, bool& eos, sample_t* buffer)
 {
+       eos = false;
+
        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);
-
-                       sample_t* buf = buffer;
-                       buffer = m_buffer.getBuffer();
-
-                       memcpy(buffer, buf, len * samplesize);
-
-                       len = length - len;
-                       length -= len;
-                       m_reader2->read(len, buf);
-
-                       memcpy(buffer + length * specs.channels, buf,
-                                  len * samplesize);
-
-                       length += len;
-
-                       m_finished1 = true;
-               }
+               m_reader1->read(length, m_finished1, buffer);
        }
        else
        {
-               m_reader2->read(length, buffer);
+               m_reader2->read(length, eos, buffer);
        }
 }
index 7b3b812ef80f8f794b66ae31bc8869bb322980ea..86f636e2cb28fa18d760e5227c5fd4421cf78d32 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "AUD_IReader.h"
 #include "AUD_Buffer.h"
+#include "AUD_Reference.h"
 
 /**
  * This reader plays two readers with the same specs sequently.
@@ -44,12 +45,12 @@ private:
        /**
         * The first reader.
         */
-       AUD_IReader* m_reader1;
+       AUD_Reference<AUD_IReader> m_reader1;
 
        /**
         * The second reader.
         */
-       AUD_IReader* m_reader2;
+       AUD_Reference<AUD_IReader> m_reader2;
 
        /**
         * Whether we've reached the end of the first reader.
@@ -72,7 +73,7 @@ public:
         * \param reader2 The second reader to read from.
         * \exception AUD_Exception Thrown if the specs from the readers differ.
         */
-       AUD_DoubleReader(AUD_IReader* reader1, AUD_IReader* reader2);
+       AUD_DoubleReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2);
 
        /**
         * Destroys the reader.
@@ -84,7 +85,7 @@ public:
        virtual int getLength() const;
        virtual int getPosition() const;
        virtual AUD_Specs getSpecs() const;
-       virtual void read(int & length, sample_t* & buffer);
+       virtual void read(int& length, bool& eos, sample_t* buffer);
 };
 
 #endif //AUD_DOUBLEREADER
diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp
new file mode 100644 (file)
index 0000000..3018a2d
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/FX/AUD_DynamicIIRFilterFactory.cpp
+ *  \ingroup audfx
+ */
+
+#include "AUD_DynamicIIRFilterFactory.h"
+#include "AUD_DynamicIIRFilterReader.h"
+
+AUD_DynamicIIRFilterFactory::AUD_DynamicIIRFilterFactory(AUD_Reference<AUD_IFactory> factory) :
+       AUD_EffectFactory(factory)
+{
+}
+
+AUD_Reference<AUD_IReader> AUD_DynamicIIRFilterFactory::createReader()
+{
+       return new AUD_DynamicIIRFilterReader(getReader(), this);
+}
diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h
new file mode 100644 (file)
index 0000000..19c1a0f
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/FX/AUD_DynamicIIRFilterFactory.h
+ *  \ingroup audfx
+ */
+
+#ifndef AUD_DYNAMICIIRFILTERFACTORY
+#define AUD_DYNAMICIIRFILTERFACTORY
+
+#include "AUD_EffectFactory.h"
+#include <vector>
+
+class AUD_DynamicIIRFilterFactory : public AUD_EffectFactory
+{
+public:
+       AUD_DynamicIIRFilterFactory(AUD_Reference<AUD_IFactory> factory);
+
+       virtual AUD_Reference<AUD_IReader> createReader();
+
+       virtual void recalculateCoefficients(AUD_SampleRate rate,
+                                                                                std::vector<float>& b,
+                                                                                std::vector<float>& a)=0;
+};
+
+#endif // AUD_DYNAMICIIRFILTERFACTORY
diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp
new file mode 100644 (file)
index 0000000..ed9b2d3
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/FX/AUD_DynamicIIRFilterReader.cpp
+ *  \ingroup audfx
+ */
+
+#include "AUD_DynamicIIRFilterReader.h"
+
+AUD_DynamicIIRFilterReader::AUD_DynamicIIRFilterReader(AUD_Reference<AUD_IReader> reader,
+                                                                                                          AUD_Reference<AUD_DynamicIIRFilterFactory> factory) :
+       AUD_IIRFilterReader(reader, std::vector<float>(), std::vector<float>())
+{
+       sampleRateChanged(reader->getSpecs().rate);
+}
+
+void AUD_DynamicIIRFilterReader::sampleRateChanged(AUD_SampleRate rate)
+{
+       std::vector<float> a, b;
+       m_factory->recalculateCoefficients(rate, b, a);
+       setCoefficients(b, a);
+}
diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h
new file mode 100644 (file)
index 0000000..92f491f
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * Copyright 2009-2011 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * Audaspace is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Audaspace; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file audaspace/FX/AUD_DynamicIIRFilterReader.h
+ *  \ingroup audfx
+ */
+
+#ifndef AUD_DYNAMICIIRFILTERREADER
+#define AUD_DYNAMICIIRFILTERREADER
+
+#include "AUD_IIRFilterReader.h"
+#include "AUD_DynamicIIRFilterFactory.h"
+
+class AUD_DynamicIIRFilterReader : public AUD_IIRFilterReader
+{
+private:
+       /**
+        * The factory for dynamically recalculating filter coefficients.
+        */
+       AUD_Reference<AUD_DynamicIIRFilterFactory> m_factory;
+
+public:
+       AUD_DynamicIIRFilterReader(AUD_Reference<AUD_IReader> reader,
+                                                          AUD_Reference<AUD_DynamicIIRFilterFactory> factory);
+
+       virtual void sampleRateChanged(AUD_SampleRate rate);
+};
+
+#endif // AUD_DYNAMICIIRFILTERREADER
index a0d9256e6911c94381deae8c96b76bcfbaeaacc3..6173ffb5a979a5bfcd3d2fc9188dacbd532274c2 100644 (file)
@@ -32,7 +32,7 @@
 #include "AUD_EffectFactory.h"
 #include "AUD_IReader.h"
 
-AUD_EffectFactory::AUD_EffectFactory(AUD_IFactory* factory)
+AUD_EffectFactory::AUD_EffectFactory(AUD_Reference<AUD_IFactory> factory)
 {
        m_factory = factory;
 }
@@ -41,7 +41,7 @@ AUD_EffectFactory::~AUD_EffectFactory()
 {
 }
 
-AUD_IFactory* AUD_EffectFactory::getFactory() const
+AUD_Reference<AUD_IFactory> AUD_EffectFactory::getFactory() const
 {
        return m_factory;
 }
index a6a28eea5770e4eee5338fa27886d949125c47b8..72fdb3f0833b968baea1a1d00fdc69c36ee49d12 100644 (file)
@@ -49,7 +49,7 @@ protected:
        /**
         * If there is no reader it is created out of this factory.
         */
-       AUD_IFactory* m_factory;
+       AUD_Reference<AUD_IFactory> m_factory;
 
        /**
         * Returns the reader created out of the factory.
@@ -57,7 +57,7 @@ protected:
         * classes.
         * \return The reader created out of the factory.
         */
-       inline AUD_IReader* getReader() const
+       inline AUD_Reference<AUD_IReader> getReader() const
        {
                return m_factory->createReader();
        }
@@ -67,7 +67,7 @@ public:
         * Creates a new factory.
         * \param factory The input factory.
         */
-       AUD_EffectFactory(AUD_IFactory* factory);
+       AUD_EffectFactory(AUD_Reference<AUD_IFactory> factory);
 
        /**
         * Destroys the factory.
@@ -78,7 +78,7 @@ public:
         * Returns the saved factory.
         * \return The factory or NULL if there has no factory been saved.
         */
-       AUD_IFactory* getFactory() const;
+       AUD_Reference<AUD_IFactory> getFactory() const;
 };
 
 #endif //AUD_EFFECTFACTORY
index 3ad9f67bfd6ce93794c5da8eb4c6299bddad0eb7..4d14af76438ac1ede4de8492890b2905ffaf078b 100644 (file)
 
 #include "AUD_EffectReader.h"
 
-AUD_EffectReader::AUD_EffectReader(AUD_IReader* reader)
+AUD_EffectReader::AUD_EffectReader(AUD_Reference<AUD_IReader> reader)
 {
        m_reader = reader;
 }
 
 AUD_EffectReader::~AUD_EffectReader()
 {
-       delete m_reader;
 }
 
 bool AUD_EffectReader::isSeekable() const
@@ -66,7 +65,7 @@ AUD_Specs AUD_EffectReader::getSpecs() const
        return m_reader->getSpecs();
 }
 
-void AUD_EffectReader::read(int & length, sample_t* & buffer)
+void AUD_EffectReader::read(int& length, bool& eos, sample_t* buffer)
 {
-       m_reader->read(length, buffer);
+       m_reader->read(length, eos, buffer);
 }
index fb8066f36d8c0a300104dd6574d139ca05e7309c..c03abd1182891577e149c485ff58a15170593922 100644 (file)
@@ -33,6 +33,7 @@
 #define AUD_EFFECTREADER
 
 #include "AUD_IReader.h"
+#include "AUD_Reference.h"
 
 /**
  * This reader is a base class for all effect readers that take one other reader
@@ -49,14 +50,14 @@ protected:
        /**
         * The reader to read from.
         */
-       AUD_IReader* m_reader;
+       AUD_Reference<AUD_IReader> m_reader;
 
 public:
        /**
         * Creates a new effect reader.
         * \param reader The reader to read from.
         */
-       AUD_EffectReader(AUD_IReader* reader);
+       AUD_EffectReader(AUD_Reference<AUD_IReader> reader);
 
        /**
         * Destroys the reader.
@@ -68,7 +69,7 @@ public:
        virtual int getLength() const;
        virtual int getPosition() const;
        virtual AUD_Specs getSpecs() const;
-       virtual void read(int & length, sample_t* & buffer);
+       virtual void read(int& length, bool& eos, sample_t* buffer);
 };
 
 #endif //AUD_EFFECTREADER
index 069317d1c8b1a766ca49fdb57e356ebcdc74476a..80df7e9f8748e249c5fce9610c5bb32a97103b62 100644 (file)
@@ -42,7 +42,7 @@ struct EnvelopeParameters
        float arthreshold;
 };
 
-sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param)
+sample_t AUD_EnvelopeFactory::envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param)
 {
        float in = fabs(reader->x(0));
        float out = reader->y(-1);
@@ -51,12 +51,12 @@ sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters*
        return (in > out ? param->attack : param->release) * (out - in) + in;
 }
 
-void endEnvelopeFilter(EnvelopeParameters* param)
+void AUD_EnvelopeFactory::endEnvelopeFilter(EnvelopeParameters* param)
 {
        delete param;
 }
 
-AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack,
+AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_Reference<AUD_IFactory> factory, float attack,
                                                                                 float release, float threshold,
                                                                                 float arthreshold) :
                AUD_EffectFactory(factory),
@@ -67,14 +67,14 @@ AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack,
 {
 }
 
-AUD_IReader* AUD_EnvelopeFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_EnvelopeFactory::createReader()
 {
-       AUD_IReader* reader = getReader();
+       AUD_Reference<AUD_IReader> reader = getReader();
 
        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->attack = pow(m_arthreshold, 1.0f/(static_cast<float>(reader->getSpecs().rate) * m_attack));
+       param->release = pow(m_arthreshold, 1.0f/(static_cast<float>(reader->getSpecs().rate) * m_release));
        param->threshold = m_threshold;
 
        return new AUD_CallbackIIRFilterReader(reader, 1, 2,
index 45ee811b6e040274f765f33a91ecd19ed9ef0dc4..a480a05d47801789a00640a8a056087dfe8af8c9 100644 (file)
@@ -33,6 +33,8 @@
 #define AUD_ENVELOPEFACTORY
 
 #include "AUD_EffectFactory.h"
+class AUD_CallbackIIRFilterReader;
+struct EnvelopeParameters;
 
 /**
  * This factory creates an envelope follower reader.
@@ -73,10 +75,13 @@ public:
         * \param threshold The threshold value.
         * \param arthreshold The attack/release threshold value.
         */
-       AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, float release,
+       AUD_EnvelopeFactory(AUD_Reference<AUD_IFactory> factory, float attack, float release,
                                                float threshold, float arthreshold);
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
+
+       static sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param);
+       static void endEnvelopeFilter(EnvelopeParameters* param);
 };
 
 #endif //AUD_ENVELOPEFACTORY
index d887e9e68d9cc69b65ac7e07a59c11c728bd866c..635873e0ee572eb8b80c094aecb1dee4060666a5 100644 (file)
@@ -32,7 +32,7 @@
 #include "AUD_FaderFactory.h"
 #include "AUD_FaderReader.h"
 
-AUD_FaderFactory::AUD_FaderFactory(AUD_IFactory* factory, AUD_FadeType type,
+AUD_FaderFactory::AUD_FaderFactory(AUD_Reference<AUD_IFactory> factory, AUD_FadeType type,
                                                                   float start, float length) :
                AUD_EffectFactory(factory),
                m_type(type),
@@ -56,7 +56,7 @@ float AUD_FaderFactory::getLength() const
        return m_length;
 }
 
-AUD_IReader* AUD_FaderFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_FaderFactory::createReader()
 {
        return new AUD_FaderReader(getReader(), m_type, m_start, m_length);
 }
index b85475bc5346dc710bd7c3a32e86f4dd24f053e4..d8314c77ed4c2a1ee1c4bbc1e5c9a5b8e14203c5 100644 (file)
@@ -69,7 +69,7 @@ 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,
+       AUD_FaderFactory(AUD_Reference<AUD_IFactory> factory,
                                          AUD_FadeType type = AUD_FADE_IN,
                                          float start = 0.0f, float length = 1.0f);
 
@@ -88,7 +88,7 @@ public:
         */
        float getLength() const;
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
 };
 
 #endif //AUD_FADERFACTORY
index 6114bb486fce871784a94a0fe37d898ada54d70d..4a6050cf0f359984310b56df07f63b9d5f72aa67 100644 (file)
 
 #include <cstring>
 
-AUD_FaderReader::AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type,
+AUD_FaderReader::AUD_FaderReader(AUD_Reference<AUD_IReader> reader, AUD_FadeType type,
                                                                 float start,float length) :
                AUD_EffectReader(reader),
                m_type(type),
                m_start(start),
-               m_length(length),
-               m_empty(true)
+               m_length(length)
 {
 }
 
-void AUD_FaderReader::read(int & length, sample_t* & buffer)
+void AUD_FaderReader::read(int& length, bool& eos, sample_t* buffer)
 {
        int position = m_reader->getPosition();
        AUD_Specs specs = m_reader->getSpecs();
        int samplesize = AUD_SAMPLE_SIZE(specs);
 
-       m_reader->read(length, buffer);
+       m_reader->read(length, eos, buffer);
 
        if((position + length) / (float)specs.rate <= m_start)
        {
                if(m_type != AUD_FADE_OUT)
                {
-                       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;
-                       }
+                       memset(buffer, 0, length * samplesize);
                }
        }
        else if(position / (float)specs.rate >= m_start+m_length)
        {
                if(m_type == AUD_FADE_OUT)
                {
-                       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;
-                       }
+                       memset(buffer, 0, length * samplesize);
                }
        }
        else
        {
-               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++)
@@ -111,10 +82,7 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer)
                                        volume = 1.0f - volume;
                        }
 
-                       buf[i] = buffer[i] * volume;
+                       buffer[i] = buffer[i] * volume;
                }
-
-               buffer = buf;
-               m_empty = false;
        }
 }
index fb927192b45ae310e91f1f17d41994d3f70d3dbd..e702ac0ec19be9c79792d5bcfd03bb1189fadc04 100644 (file)
@@ -58,16 +58,6 @@ private:
         */
        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&);
@@ -79,10 +69,10 @@ public:
         * \param start The time where fading should start in seconds.
         * \param length How long fading should last in seconds.
         */
-       AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type,
+       AUD_FaderReader(AUD_Reference<AUD_IReader> reader, AUD_FadeType type,
                                        float start,float length);
 
-       virtual void read(int & length, sample_t* & buffer);
+       virtual void read(int& length, bool& eos, sample_t* buffer);
 };
 
 #endif //AUD_FADERREADER
index 61008eea44e7162423630deeb83ec6f8801d913c..399ec5ca406d8bb3fcfb3bb1dc6f9345d9ff733d 100644 (file)
 #define M_PI 3.14159265358979323846
 #endif
 
-AUD_HighpassFactory::AUD_HighpassFactory(AUD_IFactory* factory, float frequency,
+AUD_HighpassFactory::AUD_HighpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency,
                                                                                 float Q) :
-               AUD_EffectFactory(factory),
+               AUD_DynamicIIRFilterFactory(factory),
                m_frequency(frequency),
                m_Q(Q)
 {
 }
 
-AUD_IReader* AUD_HighpassFactory::createReader() const
+void AUD_HighpassFactory::recalculateCoefficients(AUD_SampleRate rate,
+                                                                                                 std::vector<float> &b,
+                                                                                                 std::vector<float> &a)
 {
-       AUD_IReader* reader = getReader();
-
-       // calculate coefficients
-       float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate;
+       float w0 = 2 * M_PI * m_frequency / 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 new AUD_IIRFilterReader(reader, b, a);
 }
index 48f4c1baefc4ccd7bc856f27e993a4449a042bd0..51d5f55cb36b775a69d2034e6e426ff1f0018861 100644 (file)
 #ifndef AUD_HIGHPASSFACTORY
 #define AUD_HIGHPASSFACTORY
 
-#include "AUD_EffectFactory.h"
+#include "AUD_DynamicIIRFilterFactory.h"
 
 /**
  * This factory creates a highpass filter reader.
  */
-class AUD_HighpassFactory : public AUD_EffectFactory
+class AUD_HighpassFactory : public AUD_DynamicIIRFilterFactory
 {
 private:
        /**
@@ -61,9 +61,9 @@ public:
         * \param frequency The cutoff frequency.
         * \param Q The Q factor.
         */
-       AUD_HighpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0f);
+       AUD_HighpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f);
 
-       virtual AUD_IReader* createReader() const;
+       virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector<float> &b, std::vector<float> &a);
 };
 
 #endif //AUD_HIGHPASSFACTORY
index ff90ce6273910bff479d59bcbbaf624cdce02c8c..f6ccda6f67e5f6f9a9c12e0d46c90a461ad3c4cd 100644 (file)
 #include "AUD_IIRFilterFactory.h"
 #include "AUD_IIRFilterReader.h"
 
-AUD_IIRFilterFactory::AUD_IIRFilterFactory(AUD_IFactory* factory,
+AUD_IIRFilterFactory::AUD_IIRFilterFactory(AUD_Reference<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
+AUD_Reference<AUD_IReader> AUD_IIRFilterFactory::createReader()
 {
        return new AUD_IIRFilterReader(getReader(), m_b, m_a);
 }
index d48ad453ee46c115fb679141d50afd3800f07f56..0e92ab1a568e88d712ee4c55d3b4b7d269cd6dbf 100644 (file)
@@ -63,10 +63,10 @@ public:
         * \param b The input filter coefficients.
         * \param a The output filter coefficients.
         */
-       AUD_IIRFilterFactory(AUD_IFactory* factory, std::vector<float> b,
+       AUD_IIRFilterFactory(AUD_Reference<AUD_IFactory> factory, std::vector<float> b,
                                                 std::vector<float> a);
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
 };
 
 #endif //AUD_IIRFILTERFACTORY
index 0d55421d2b4965312456f0ff06c35f0a43ce9542..1bfb9b97b62a2b4b2a79886d349523bd811f5d6a 100644 (file)
@@ -31,9 +31,9 @@
 
 #include "AUD_IIRFilterReader.h"
 
-AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_IReader* reader,
-                                                                                std::vector<float> b,
-                                                                                std::vector<float> a) :
+AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_Reference<AUD_IReader> reader,
+                                                                                const std::vector<float>& b,
+                                                                                const 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++)
@@ -54,3 +54,11 @@ sample_t AUD_IIRFilterReader::filter()
 
        return out;
 }
+
+void AUD_IIRFilterReader::setCoefficients(const std::vector<float>& b,
+                                                                                 const std::vector<float>& a)
+{
+       setLengths(m_b.size(), m_a.size());
+       m_a = a;
+       m_b = b;
+}
index af50b6f1cdc26a70adbac271467b455fe916dc72..41de67d4d27419de773ba8e73162bd0b81463aab 100644 (file)
@@ -63,10 +63,13 @@ public:
         * \param b The input filter coefficients.
         * \param a The output filter coefficients.
         */
-       AUD_IIRFilterReader(AUD_IReader* reader, std::vector<float> b,
-                                               std::vector<float> a);
+       AUD_IIRFilterReader(AUD_Reference<AUD_IReader> reader, const std::vector<float>& b,
+                                               const std::vector<float>& a);
 
        virtual sample_t filter();
+
+       void setCoefficients(const std::vector<float>& b,
+                                                const std::vector<float>& a);
 };
 
 #endif //AUD_IIRFILTERREADER
index 62ea01bb76191e58c2147a08c10969faf12eb651..8d1dd14f3aed7601f2a370fb8cf15d8d9b4175a8 100644 (file)
@@ -33,7 +33,7 @@
 #include "AUD_LimiterReader.h"
 #include "AUD_Space.h"
 
-AUD_LimiterFactory::AUD_LimiterFactory(AUD_IFactory* factory,
+AUD_LimiterFactory::AUD_LimiterFactory(AUD_Reference<AUD_IFactory> factory,
                                                                           float start, float end) :
                AUD_EffectFactory(factory),
                m_start(start),
@@ -51,7 +51,7 @@ float AUD_LimiterFactory::getEnd() const
        return m_end;
 }
 
-AUD_IReader* AUD_LimiterFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_LimiterFactory::createReader()
 {
        return new AUD_LimiterReader(getReader(), m_start, m_end);
 }
index f93f4b3276c4d650e07e3fe683d415cd7a572371..c04bfe861b2752c7bea69493a7fa347a1f73256c 100644 (file)
@@ -62,7 +62,7 @@ public:
         * \param end The desired end time, a negative value signals that it should
         *            play to the end.
         */
-       AUD_LimiterFactory(AUD_IFactory* factory,
+       AUD_LimiterFactory(AUD_Reference<AUD_IFactory> factory,
                                           float start = 0, float end = -1);
 
        /**
@@ -75,7 +75,7 @@ public:
         */
        float getEnd() const;
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
 };
 
 #endif //AUD_LIMITERFACTORY
index d67fbb4d0e52931c9e1aadf710d2b8a9669f44a5..92feac8a6a38291a7c4d2b675bc3b203f04f98a5 100644 (file)
 
 #include <iostream>
 
-AUD_LimiterReader::AUD_LimiterReader(AUD_IReader* reader,
+AUD_LimiterReader::AUD_LimiterReader(AUD_Reference<AUD_IReader> reader,
                                                                         float start, float end) :
                AUD_EffectReader(reader),
-               m_start(int(start * reader->getSpecs().rate)),
-               m_end(int(end * reader->getSpecs().rate))
+               m_start(start),
+               m_end(end)
 {
        if(m_start > 0)
        {
+               AUD_Specs specs = m_reader->getSpecs();
+               AUD_Specs specs2;
+
                if(m_reader->isSeekable())
-                       m_reader->seek(m_start);
+                       m_reader->seek(m_start * specs.rate);
                else
                {
                        // skip first m_start samples by reading them
                        int length = AUD_DEFAULT_BUFFER_SIZE;
-                       sample_t* buffer;
-                       for(int len = m_start;
-                               length == AUD_DEFAULT_BUFFER_SIZE;
-                               len -= AUD_DEFAULT_BUFFER_SIZE)
+                       AUD_Buffer buffer(AUD_DEFAULT_BUFFER_SIZE * AUD_SAMPLE_SIZE(specs));
+                       bool eos = false;
+                       for(int len = m_start * specs.rate;
+                               length > 0 && !eos;
+                               len -= length)
                        {
                                if(len < AUD_DEFAULT_BUFFER_SIZE)
                                        length = len;
-                               m_reader->read(length, buffer);
+
+                               m_reader->read(length, eos, buffer.getBuffer());
+
+                               specs2 = m_reader->getSpecs();
+                               if(specs2.rate != specs.rate)
+                               {
+                                       len = len * specs2.rate / specs.rate;
+                                       specs.rate = specs2.rate;
+                               }
+
+                               if(specs2.channels != specs.channels)
+                               {
+                                       specs = specs2;
+                                       buffer.assureSize(AUD_DEFAULT_BUFFER_SIZE * AUD_SAMPLE_SIZE(specs));
+                               }
                        }
                }
        }
@@ -63,35 +81,71 @@ AUD_LimiterReader::AUD_LimiterReader(AUD_IReader* reader,
 
 void AUD_LimiterReader::seek(int position)
 {
-       m_reader->seek(position + m_start);
+       m_reader->seek(position + m_start * m_reader->getSpecs().rate);
 }
 
 int AUD_LimiterReader::getLength() const
 {
        int len = m_reader->getLength();
-       if(len < 0 || (len > m_end && m_end >= 0))
-               len = m_end;
-       return len - m_start;
+       AUD_SampleRate rate = m_reader->getSpecs().rate;
+       if(len < 0 || (len > m_end * rate && m_end >= 0))
+               len = m_end * rate;
+       return len - m_start * rate;
 }
 
 int AUD_LimiterReader::getPosition() const
 {
        int pos = m_reader->getPosition();
-       return AUD_MIN(pos, m_end) - m_start;
+       AUD_SampleRate rate = m_reader->getSpecs().rate;
+       return AUD_MIN(pos, m_end * rate) - m_start * rate;
 }
 
-void AUD_LimiterReader::read(int & length, sample_t* & buffer)
+void AUD_LimiterReader::read(int& length, bool& eos, sample_t* buffer)
 {
+       eos = false;
        if(m_end >= 0)
        {
                int position = m_reader->getPosition();
-               if(position + length > m_end)
-                       length = m_end - position;
+               AUD_SampleRate rate = m_reader->getSpecs().rate;
+
+               if(position + length > m_end * rate)
+               {
+                       length = m_end * rate - position;
+                       eos = true;
+               }
+
+               if(position < m_start * rate)
+               {
+                       int len2 = length;
+                       for(int len = m_start * rate - position;
+                               len2 == length && !eos;
+                               len -= length)
+                       {
+                               if(len < length)
+                                       len2 = len;
+
+                               m_reader->read(len2, eos, buffer);
+                               position += len2;
+                       }
+
+                       if(position < m_start * rate)
+                       {
+                               length = 0;
+                               return;
+                       }
+               }
+
                if(length < 0)
                {
                        length = 0;
                        return;
                }
        }
-       m_reader->read(length, buffer);
+       if(eos)
+       {
+               m_reader->read(length, eos, buffer);
+               eos = true;
+       }
+       else
+               m_reader->read(length, eos, buffer);
 }
index 4375ed9e10dc7f4ef46dfe8e857c80ed40f0af7d..d9bee6f6463b49df620e667d1fa4d6056ac007d2 100644 (file)
@@ -43,12 +43,12 @@ private:
        /**
         * The start sample: inclusive.
         */
-       const int m_start;
+       const float m_start;
 
        /**
         * The end sample: exlusive.
         */
-       const int m_end;
+       const float m_end;
 
        // hide copy constructor and operator=
        AUD_LimiterReader(const AUD_LimiterReader&);
@@ -62,12 +62,12 @@ public:
         * \param end The desired end sample (exklusive), a negative value signals
         *            that it should play to the end.
         */
-       AUD_LimiterReader(AUD_IReader* reader, float start = 0, float end = -1);
+       AUD_LimiterReader(AUD_Reference<AUD_IReader> reader, float start = 0, float end = -1);
 
        virtual void seek(int position);
        virtual int getLength() const;
        virtual int getPosition() const;
-       virtual void read(int & length, sample_t* & buffer);
+       virtual void read(int& length, bool& eos, sample_t* buffer);
 };
 
 #endif //AUD_LIMITERREADER
index 49d3481757fb89b4e8f5197d282aba0b4aa0b64b..fd39ac901c1f84ac828237a1a222b66e41e31ca7 100644 (file)
@@ -32,7 +32,7 @@
 #include "AUD_LoopFactory.h"
 #include "AUD_LoopReader.h"
 
-AUD_LoopFactory::AUD_LoopFactory(AUD_IFactory* factory, int loop) :
+AUD_LoopFactory::AUD_LoopFactory(AUD_Reference<AUD_IFactory> factory, int loop) :
                AUD_EffectFactory(factory),
                m_loop(loop)
 {
@@ -43,7 +43,7 @@ int AUD_LoopFactory::getLoop() const
        return m_loop;
 }
 
-AUD_IReader* AUD_LoopFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_LoopFactory::createReader()
 {
        return new AUD_LoopReader(getReader(), m_loop);
 }
index dfbbbe4fd20d155a25f1b6d53bedc308ce217ebb..03c00dc40ceeda788c260dccee0ba7ebd78af57b 100644 (file)
@@ -57,14 +57,14 @@ public:
         * \param loop The desired loop count, negative values result in endless
         *        looping.
         */
-       AUD_LoopFactory(AUD_IFactory* factory, int loop = -1);
+       AUD_LoopFactory(AUD_Reference<AUD_IFactory> factory, int loop = -1);
 
        /**
         * Returns the loop count.
         */
        int getLoop() const;
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
 };
 
 #endif //AUD_LOOPFACTORY
index b2e8e97a60295cc679d5cbfdbe0033ff17919580..de67a445ab2d29a52b0a8e7d00dfcdaf8a96261b 100644 (file)
@@ -34,7 +34,7 @@
 
 #include <cstring>
 
-AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) :
+AUD_LoopReader::AUD_LoopReader(AUD_Reference<AUD_IReader> reader, int loop) :
                AUD_EffectReader(reader), m_count(loop), m_left(loop)
 {
 }
@@ -68,29 +68,20 @@ int AUD_LoopReader::getPosition() const
        return m_reader->getPosition() * (m_count < 0 ? 1 : m_count);
 }
 
-void AUD_LoopReader::read(int & length, sample_t* & buffer)
+void AUD_LoopReader::read(int& length, bool& eos, sample_t* buffer)
 {
-       AUD_Specs specs = m_reader->getSpecs();
-       int samplesize = AUD_SAMPLE_SIZE(specs);
+       const AUD_Specs specs = m_reader->getSpecs();
 
        int len = length;
 
-       m_reader->read(len, buffer);
+       m_reader->read(length, eos, buffer);
 
-       if(len < length && m_left)
+       if(length < len && eos && m_left)
        {
-               int pos = 0;
-
-               if(m_buffer.getSize() < length * samplesize)
-                       m_buffer.resize(length * samplesize);
-
-               sample_t* buf = m_buffer.getBuffer();
-
-               memcpy(buf + pos * specs.channels, buffer, len * samplesize);
-
-               pos += len;
+               int pos = length;
+               length = len;
 
-               while(pos < length && m_left)
+               while(pos < length && eos && m_left)
                {
                        if(m_left > 0)
                                m_left--;
@@ -98,20 +89,15 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer)
                        m_reader->seek(0);
 
                        len = length - pos;
-                       m_reader->read(len, buffer);
+                       m_reader->read(len, eos, buffer + pos * specs.channels);
 
                        // prevent endless loop
                        if(!len)
                                break;
 
-                       memcpy(buf + pos * specs.channels, buffer, len * samplesize);
-
                        pos += len;
                }
 
                length = pos;
-               buffer = buf;
        }
-       else
-               length = len;
 }
index 45017901c568cf941a8785037e7eda72ac2b0d81..5ccf7e543a0c7d8d543c249081ad7e933870bb19 100644 (file)
 class AUD_LoopReader : public AUD_EffectReader
 {
 private:
-       /**
-        * The playback buffer.
-        */
-       AUD_Buffer m_buffer;
-
        /**
         * The loop count.
         */
@@ -68,12 +63,12 @@ public:
         * \param loop The desired loop count, negative values result in endless
         *        looping.
         */
-       AUD_LoopReader(AUD_IReader* reader, int loop);
+       AUD_LoopReader(AUD_Reference<AUD_IReader> reader, int loop);
 
        virtual void seek(int position);
        virtual int getLength() const;
        virtual int getPosition() const;
-       virtual void read(int & length, sample_t* & buffer);
+       virtual void read(int& length, bool& eos, sample_t* buffer);
 };
 
 #endif //AUD_LOOPREADER
index d24a04b5a94d77a92483381d66039136c8d7a2f9..3ef25c3c16ed269070007ddc3978798c7401be5d 100644 (file)
 #define M_PI 3.14159265358979323846
 #endif
 
-AUD_LowpassFactory::AUD_LowpassFactory(AUD_IFactory* factory, float frequency,
+AUD_LowpassFactory::AUD_LowpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency,
                                                                           float Q) :
-               AUD_EffectFactory(factory),
+               AUD_DynamicIIRFilterFactory(factory),
                m_frequency(frequency),
                m_Q(Q)
 {
 }
 
-AUD_IReader* AUD_LowpassFactory::createReader() const
+void AUD_LowpassFactory::recalculateCoefficients(AUD_SampleRate rate,
+                                                                                                std::vector<float> &b,
+                                                                                                std::vector<float> &a)
 {
-       AUD_IReader* reader = getReader();
-
-       // calculate coefficients
-       float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate;
+       float w0 = 2 * M_PI * m_frequency / 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 new AUD_IIRFilterReader(reader, b, a);
 }
index d60c0bd22d182c12d46a640f1929a2e7f025db07..6558663df4e874db8c796e867aeb15ddc1bb89ec 100644 (file)
 #ifndef AUD_LOWPASSFACTORY
 #define AUD_LOWPASSFACTORY
 
-#include "AUD_EffectFactory.h"
+#include "AUD_DynamicIIRFilterFactory.h"
 
 /**
  * This factory creates a lowpass filter reader.
  */
-class AUD_LowpassFactory : public AUD_EffectFactory
+class AUD_LowpassFactory : public AUD_DynamicIIRFilterFactory
 {
 private:
        /**
@@ -61,9 +61,9 @@ public:
         * \param frequency The cutoff frequency.
         * \param Q The Q factor.
         */
-       AUD_LowpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0f);
+       AUD_LowpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f);
 
-       virtual AUD_IReader* createReader() const;
+       virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector<float> &b, std::vector<float> &a);
 };
 
 #endif //AUD_LOWPASSFACTORY
index fa14055594358c2cd4cd10a7f600dc032f683b0a..e5f2193ea565116ee62628b38f0be1c721a11d50 100644 (file)
 #include "AUD_DoubleReader.h"
 #include "AUD_ReverseFactory.h"
 
-AUD_PingPongFactory::AUD_PingPongFactory(AUD_IFactory* factory) :
+AUD_PingPongFactory::AUD_PingPongFactory(AUD_Reference<AUD_IFactory> factory) :
                AUD_EffectFactory(factory)
 {
 }
 
-AUD_IReader* AUD_PingPongFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_PingPongFactory::createReader()
 {
-       AUD_IReader* reader = getReader();
-       AUD_IReader* reader2;
+       AUD_Reference<AUD_IReader> reader = getReader();
        AUD_ReverseFactory factory(m_factory);
-
-       try
-       {
-               reader2 = factory.createReader();
-       }
-       catch(AUD_Exception&)
-       {
-               delete reader;
-               throw;
-       }
+       AUD_Reference<AUD_IReader> reader2 = factory.createReader();
 
        return new AUD_DoubleReader(reader, reader2);
 }
index 4ae0c494eb7104b9290ae52d75f76c975bdc7bc1..908591a6ebec6dc8c95568c93e406b6778933205 100644 (file)
@@ -50,9 +50,9 @@ public:
         * Creates a new ping pong factory.
         * \param factory The input factory.
         */
-       AUD_PingPongFactory(AUD_IFactory* factory);
+       AUD_PingPongFactory(AUD_Reference<AUD_IFactory> factory);
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
 };
 
 #endif //AUD_PINGPONGFACTORY
index b4ae8582cafaa27bed3894351eee0cebff9be619..e52028754e9be51f390c1accccb23bee30239096 100644 (file)
 #include "AUD_PitchReader.h"
 #include "AUD_Space.h"
 
-AUD_PitchFactory::AUD_PitchFactory(AUD_IFactory* factory, float pitch) :
+AUD_PitchFactory::AUD_PitchFactory(AUD_Reference<AUD_IFactory> factory, float pitch) :
                AUD_EffectFactory(factory),
                m_pitch(pitch)
 {
 }
 
-AUD_IReader* AUD_PitchFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_PitchFactory::createReader()
 {
        return new AUD_PitchReader(getReader(), m_pitch);
 }
index 8fa5be9293f6b82bd483c157d74faab1afb47bde..2642d41af89d89b5d44298e60f839f92b88a302d 100644 (file)
@@ -55,9 +55,9 @@ public:
         * \param factory The input factory.
         * \param pitch The desired pitch.
         */
-       AUD_PitchFactory(AUD_IFactory* factory, float pitch);
+       AUD_PitchFactory(AUD_Reference<AUD_IFactory> factory, float pitch);
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
 };
 
 #endif //AUD_PITCHFACTORY
index e2e89e2c45731e01d201476963b766b127ec857b..81dd6e4355cbc366da0c2b60665c4f6d8e2b880d 100644 (file)
@@ -31,7 +31,7 @@
 
 #include "AUD_PitchReader.h"
 
-AUD_PitchReader::AUD_PitchReader(AUD_IReader* reader, float pitch) :
+AUD_PitchReader::AUD_PitchReader(AUD_Reference<AUD_IReader> reader, float pitch) :
                AUD_EffectReader(reader), m_pitch(pitch)
 {
 }
@@ -39,6 +39,16 @@ AUD_PitchReader::AUD_PitchReader(AUD_IReader* reader, float pitch) :
 AUD_Specs AUD_PitchReader::getSpecs() const
 {
        AUD_Specs specs = m_reader->getSpecs();
-       specs.rate = (AUD_SampleRate)((int)(specs.rate * m_pitch));
+       specs.rate *= m_pitch;
        return specs;
 }
+
+float AUD_PitchReader::getPitch() const
+{
+       return m_pitch;
+}
+
+void AUD_PitchReader::setPitch(float pitch)
+{
+       m_pitch = pitch;
+}
index 120cebc58beb42b2a2485f0be260345a5b5a0878..7418531ca55a3f4c9326385bfb19bcdad674573d 100644 (file)
@@ -43,7 +43,7 @@ private:
        /**
         * The pitch level.
         */
-       const float m_pitch;
+       float m_pitch;
 
        // hide copy constructor and operator=
        AUD_PitchReader(const AUD_PitchReader&);
@@ -55,9 +55,12 @@ public:
         * \param reader The reader to read from.
         * \param pitch The size of the buffer.
         */
-       AUD_PitchReader(AUD_IReader* reader, float pitch);
+       AUD_PitchReader(AUD_Reference<AUD_IReader> reader, float pitch);
 
        virtual AUD_Specs getSpecs() const;
+
+       float getPitch() const;
+       void setPitch(float pitch);
 };
 
 #endif //AUD_PITCHREADER
index 609d827cce49e51e8bafb16791367e74a3e0f4e9..cbb676a9a32b6ed6dbf22b9ec401b686d2e8e59a 100644 (file)
 
 #include <cmath>
 
-sample_t rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
+sample_t AUD_RectifyFactory::rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
 {
        return fabs(reader->x(0));
 }
 
-AUD_RectifyFactory::AUD_RectifyFactory(AUD_IFactory* factory) :
+AUD_RectifyFactory::AUD_RectifyFactory(AUD_Reference<AUD_IFactory> factory) :
                AUD_EffectFactory(factory)
 {
 }
 
-AUD_IReader* AUD_RectifyFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_RectifyFactory::createReader()
 {
        return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, rectifyFilter);
 }
index c3529c7beef6773d21a3ef2fecb439bf347fb7e3..16b44469c056a949e47c68cb30560339a519ab24 100644 (file)
@@ -33,6 +33,7 @@
 #define AUD_RECTIFYFACTORY
 
 #include "AUD_EffectFactory.h"
+class AUD_CallbackIIRFilterReader;
 
 /**
  * This factory rectifies another factory.
@@ -49,9 +50,11 @@ public:
         * Creates a new rectify factory.
         * \param factory The input factory.
         */
-       AUD_RectifyFactory(AUD_IFactory* factory);
+       AUD_RectifyFactory(AUD_Reference<AUD_IFactory> factory);
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
+
+       static sample_t rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless);
 };
 
 #endif //AUD_RECTIFYFACTORY
index 22b12e3142008b1dddde233d46e7e81c03039ff9..060a618dd6802825c1b35607175d2b92fa56d915 100644 (file)
 #include "AUD_ReverseReader.h"
 #include "AUD_Space.h"
 
-AUD_ReverseFactory::AUD_ReverseFactory(AUD_IFactory* factory) :
+AUD_ReverseFactory::AUD_ReverseFactory(AUD_Reference<AUD_IFactory> factory) :
                AUD_EffectFactory(factory)
 {
 }
 
-AUD_IReader* AUD_ReverseFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_ReverseFactory::createReader()
 {
        return new AUD_ReverseReader(getReader());
 }
index 7b20546302e3efcc3de19a2364bba726cca9bd90..b501b4e76c86b8c346e6791ecdee379bb1bf88aa 100644 (file)
@@ -50,9 +50,9 @@ public:
         * Creates a new reverse factory.
         * \param factory The input factory.
         */
-       AUD_ReverseFactory(AUD_IFactory* factory);
+       AUD_ReverseFactory(AUD_Reference<AUD_IFactory> factory);
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
 };
 
 #endif //AUD_REVERSEFACTORY
index a4a03936c76743f1fdef172cf0036e18b736aa5a..73f6830f3fa6a495e56b811d7515383adc3ba66c 100644 (file)
@@ -36,7 +36,7 @@
 static const char* props_error = "AUD_ReverseReader: The reader has to be "
                                                                 "seekable and a finite length.";
 
-AUD_ReverseReader::AUD_ReverseReader(AUD_IReader* reader) :
+AUD_ReverseReader::AUD_ReverseReader(AUD_Reference<AUD_IReader> reader) :
                AUD_EffectReader(reader),
                m_length(reader->getLength()),
                m_position(0)
@@ -60,7 +60,7 @@ int AUD_ReverseReader::getPosition() const
        return m_position;
 }
 
-void AUD_ReverseReader::read(int & length, sample_t* & buffer)
+void AUD_ReverseReader::read(int& length, bool& eos, sample_t* buffer)
 {
        // first correct the length
        if(m_position + length > m_length)
@@ -69,39 +69,39 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer)
        if(length <= 0)
        {
                length = 0;
+               eos = true;
                return;
        }
 
-       AUD_Specs specs = getSpecs();
-       int samplesize = AUD_SAMPLE_SIZE(specs);
+       const AUD_Specs specs = getSpecs();
+       const int samplesize = AUD_SAMPLE_SIZE(specs);
 
-       // resize buffer if needed
-       if(m_buffer.getSize() < length * samplesize)
-               m_buffer.resize(length * samplesize);
+       sample_t temp[AUD_CHANNEL_MAX];
 
-       buffer = m_buffer.getBuffer();
-
-       sample_t* buf;
        int len = length;
 
        // read from reader
        m_reader->seek(m_length - m_position - len);
-       m_reader->read(len, buf);
+       m_reader->read(len, eos, buffer);
 
        // set null if reader didn't give enough data
        if(len < length)
-       {
                memset(buffer, 0, (length - len) * samplesize);
-               buffer += (length - len) * specs.channels;
-       }
 
        // copy the samples reverted
-       for(int i = 0; i < len; i++)
+       for(int i = 0; i < length / 2; i++)
+       {
+               memcpy(temp,
+                          buffer + (len - 1 - i) * specs.channels,
+                          samplesize);
+               memcpy(buffer + (len - 1 - i) * specs.channels,
+                          buffer + i * specs.channels,
+                          samplesize);
                memcpy(buffer + i * specs.channels,
-                          buf + (len - 1 - i) * specs.channels,
+                          temp,
                           samplesize);
+       }
 
        m_position += length;
-
-       buffer = m_buffer.getBuffer();
+       eos = false;
 }
index e12f2b2119191ab3bdcf09bdba1ecae85e13557b..da0add9464e49b89c06dc4eb988e761115ebb16f 100644 (file)
@@ -52,11 +52,6 @@ private:
         */
        int m_position;
 
-       /**
-        * The playback buffer.
-        */
-       AUD_Buffer m_buffer;
-
        // hide copy constructor and operator=
        AUD_ReverseReader(const AUD_ReverseReader&);
        AUD_ReverseReader& operator=(const AUD_ReverseReader&);
@@ -68,12 +63,12 @@ public:
         * \exception AUD_Exception Thrown if the reader specified has an
         *            undeterminable/infinite length or is not seekable.
         */
-       AUD_ReverseReader(AUD_IReader* reader);
+       AUD_ReverseReader(AUD_Reference<AUD_IReader> reader);
 
        virtual void seek(int position);
        virtual int getLength() const;
        virtual int getPosition() const;
-       virtual void read(int & length, sample_t* & buffer);
+       virtual void read(int& length, bool& eos, sample_t* buffer);
 };
 
 #endif //AUD_REVERSEREADER
index a075773d2cba1d4c4a27a833a9a3de7a255757b9..226085a18146bdafb8362360abdf9bb37e1c5a1e 100644 (file)
@@ -32,7 +32,7 @@
 #include "AUD_SquareFactory.h"
 #include "AUD_CallbackIIRFilterReader.h"
 
-sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold)
+sample_t AUD_SquareFactory::squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold)
 {
        float in = reader->x(0);
        if(in >= *threshold)
@@ -43,12 +43,12 @@ sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold)
                return 0;
 }
 
-void endSquareFilter(float* threshold)
+void AUD_SquareFactory::endSquareFilter(float* threshold)
 {
        delete threshold;
 }
 
-AUD_SquareFactory::AUD_SquareFactory(AUD_IFactory* factory, float threshold) :
+AUD_SquareFactory::AUD_SquareFactory(AUD_Reference<AUD_IFactory> factory, float threshold) :
                AUD_EffectFactory(factory),
                m_threshold(threshold)
 {
@@ -59,7 +59,7 @@ float AUD_SquareFactory::getThreshold() const
        return m_threshold;
 }
 
-AUD_IReader* AUD_SquareFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_SquareFactory::createReader()
 {
        return new AUD_CallbackIIRFilterReader(getReader(), 1, 1,
                                                                                   (doFilterIIR) squareFilter,
index 8060e98e2819f1ffd417926b3a630880b2965753..21284361ccaef796a69a5ae0c0e13d3cfb4cd13c 100644 (file)
@@ -33,6 +33,7 @@
 #define AUD_SQUAREFACTORY
 
 #include "AUD_EffectFactory.h"
+class AUD_CallbackIIRFilterReader;
 
 /**
  * This factory Transforms any signal to a square signal.
@@ -55,14 +56,17 @@ public:
         * \param factory The input factory.
         * \param threshold The threshold.
         */
-       AUD_SquareFactory(AUD_IFactory* factory, float threshold = 0.0f);
+       AUD_SquareFactory(AUD_Reference<AUD_IFactory> factory, float threshold = 0.0f);
 
        /**
         * Returns the threshold.
         */
        float getThreshold() const;
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
+
+       static sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold);
+       static void endSquareFilter(float* threshold);
 };
 
 #endif //AUD_SQUAREFACTORY
index 6d8368d6e3527dd11870d1a5f04f0af2e09a673c..befcc30360f38f27cff205b64624cff2b3732b06 100644 (file)
 #include "AUD_SumFactory.h"
 #include "AUD_IIRFilterReader.h"
 
-AUD_SumFactory::AUD_SumFactory(AUD_IFactory* factory) :
+AUD_SumFactory::AUD_SumFactory(AUD_Reference<AUD_IFactory> factory) :
                AUD_EffectFactory(factory)
 {
 }
 
-AUD_IReader* AUD_SumFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_SumFactory::createReader()
 {
        std::vector<float> a, b;
        a.push_back(1);
index ed19a0f258a6075ee1665955986246d08a0d9417..cdb4caf6e496e7a4e6c1f189f797c08ea8e7fbc0 100644 (file)
@@ -49,9 +49,9 @@ public:
         * Creates a new sum factory.
         * \param factory The input factory.
         */
-       AUD_SumFactory(AUD_IFactory* factory);
+       AUD_SumFactory(AUD_Reference<AUD_IFactory> factory);
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
 };
 
 #endif //AUD_SUMFACTORY
index c13a0d0dd9532e369a64c1345d35148f0c543608..d514bfd8fca21d30ea69c4e4435dceab14ffd606 100644 (file)
 #include "AUD_SuperposeFactory.h"
 #include "AUD_SuperposeReader.h"
 
-AUD_SuperposeFactory::AUD_SuperposeFactory(AUD_IFactory* factory1, AUD_IFactory* factory2) :
+AUD_SuperposeFactory::AUD_SuperposeFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2) :
                m_factory1(factory1), m_factory2(factory2)
 {
 }
 
-AUD_IReader* AUD_SuperposeFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_SuperposeFactory::createReader()
 {
-       AUD_IReader* reader1 = m_factory1->createReader();
-       AUD_IReader* reader2;
-       try
-       {
-               reader2 = m_factory2->createReader();
-       }
-       catch(AUD_Exception&)
-       {
-               delete reader1;
-               throw;
-       }
+       AUD_Reference<AUD_IReader> reader1 = m_factory1->createReader();
+       AUD_Reference<AUD_IReader> reader2 = m_factory2->createReader();
 
        return new AUD_SuperposeReader(reader1, reader2);
 }
index 32232012e4e3a0aea6227f5f6c24f2cbdd1a97ec..ac7ec0801343fc1948637bf0c4b6d47210080299 100644 (file)
@@ -44,12 +44,12 @@ private:
        /**
         * First played factory.
         */
-       AUD_IFactory* m_factory1;
+       AUD_Reference<AUD_IFactory> m_factory1;
 
        /**
         * Second played factory.
         */
-       AUD_IFactory* m_factory2;
+       AUD_Reference<AUD_IFactory> m_factory2;
 
        // hide copy constructor and operator=
        AUD_SuperposeFactory(const AUD_SuperposeFactory&);
@@ -61,9 +61,9 @@ public:
         * \param factory1 The first input factory.
         * \param factory2 The second input factory.
         */
-       AUD_SuperposeFactory(AUD_IFactory* factory1, AUD_IFactory* factory2);
+       AUD_SuperposeFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2);
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
 };
 
 #endif //AUD_SUPERPOSEFACTORY
index e64cf79188e09998ad23194e817c22e4e6311970..a0dc12fea96e161b783b0f020199edc5e953a1a4 100644 (file)
 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) :
+AUD_SuperposeReader::AUD_SuperposeReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<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
@@ -94,28 +77,31 @@ AUD_Specs AUD_SuperposeReader::getSpecs() const
        return m_reader1->getSpecs();
 }
 
-void AUD_SuperposeReader::read(int & length, sample_t* & buffer)
+void AUD_SuperposeReader::read(int& length, bool& eos, sample_t* buffer)
 {
        AUD_Specs specs = m_reader1->getSpecs();
+       AUD_Specs s2 = m_reader2->getSpecs();
+       if(memcmp(&specs, &s2, sizeof(AUD_Specs)))
+               AUD_THROW(AUD_ERROR_SPECS, specs_error);
+
        int samplesize = AUD_SAMPLE_SIZE(specs);
 
-       if(m_buffer.getSize() < length * samplesize)
-               m_buffer.resize(length * samplesize);
-       buffer = m_buffer.getBuffer();
+       m_buffer.assureSize(length * samplesize);
 
        int len1 = length;
-       sample_t* buf;
-       m_reader1->read(len1, buf);
-       memcpy(buffer, buf, len1 * samplesize);
+       m_reader1->read(len1, eos, buffer);
 
        if(len1 < length)
                memset(buffer + len1 * specs.channels, 0, (length - len1) * samplesize);
 
        int len2 = length;
-       m_reader2->read(len2, buf);
+       bool eos2;
+       sample_t* buf = m_buffer.getBuffer();
+       m_reader2->read(len2, eos2, buf);
 
        for(int i = 0; i < len2 * specs.channels; i++)
                buffer[i] += buf[i];
 
        length = AUD_MAX(len1, len2);
+       eos &= eos2;
 }
index b256aade7ba7236a2dfb696a12c9e756287cd48f..a87f1fdb739e42b3c4c429491487302b2774faa6 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "AUD_IReader.h"
 #include "AUD_Buffer.h"
+#include "AUD_Reference.h"
 
 /**
  * This reader plays two readers with the same specs sequently.
@@ -44,12 +45,12 @@ private:
        /**
         * The first reader.
         */
-       AUD_IReader* m_reader1;
+       AUD_Reference<AUD_IReader> m_reader1;
 
        /**
         * The second reader.
         */
-       AUD_IReader* m_reader2;
+       AUD_Reference<AUD_IReader> m_reader2;
 
        /**
         * The playback buffer for the intersecting part.
@@ -67,7 +68,7 @@ public:
         * \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);
+       AUD_SuperposeReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2);
 
        /**
         * Destroys the reader.
@@ -79,7 +80,7 @@ public:
        virtual int getLength() const;
        virtual int getPosition() const;
        virtual AUD_Specs getSpecs() const;
-       virtual void read(int & length, sample_t* & buffer);
+       virtual void read(int& length, bool& eos, sample_t* buffer);
 };
 
 #endif //AUD_SUPERPOSEREADER
index 166fbf615122664f304e9e9b9846576b92db1329..17cefd4f3c3bc8ffac0c013563e3ffdf4d0dd23f 100644 (file)
@@ -32,7 +32,7 @@
 #include "AUD_VolumeFactory.h"
 #include "AUD_IIRFilterReader.h"
 
-AUD_VolumeFactory::AUD_VolumeFactory(AUD_IFactory* factory, float volume) :
+AUD_VolumeFactory::AUD_VolumeFactory(AUD_Reference<AUD_IFactory> factory, float volume) :
                AUD_EffectFactory(factory),
                m_volume(volume)
 {
@@ -43,7 +43,7 @@ float AUD_VolumeFactory::getVolume() const
        return m_volume;
 }
 
-AUD_IReader* AUD_VolumeFactory::createReader() const
+AUD_Reference<AUD_IReader> AUD_VolumeFactory::createReader()
 {
        std::vector<float> a, b;
        a.push_back(1);
index fa40ca110826125a034430bf31e6dbff1611df6e..bcc08e7d04ad1f1b29f695fd53acdde85885e88b 100644 (file)
@@ -57,14 +57,14 @@ public:
         * \param factory The input factory.
         * \param volume The desired volume.
         */
-       AUD_VolumeFactory(AUD_IFactory* factory, float volume);
+       AUD_VolumeFactory(AUD_Reference<AUD_IFactory> factory, float volume);
 
        /**
         * Returns the volume.
         */
        float getVolume() const;
 
-       virtual AUD_IReader* createReader() const;
+       virtual AUD_Reference<AUD_IReader> createReader();
 };
 
 #endif //AUD_VOLUMEFACTORY
index b9e30bbf62aa94897b901f29962de288a8820859..c36f29aa179b5f683ff4ba6d77a93c3c8e3f9bb9 100644 (file)
 #include <unistd.h>
 #endif
 
-#define AUD_OPENAL_CYCLE_BUFFERS 3
+/*struct AUD_OpenALBufferedFactory
+{
+       /// The factory.
+       AUD_IFactory* factory;
+
+       /// The OpenAL buffer.
+       ALuint buffer;
+};*/
+
+//typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator;
+
+
+/******************************************************************************/
+/*********************** AUD_OpenALHandle Handle Code *************************/
+/******************************************************************************/
+
+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_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference<AUD_IReader> reader, bool keep) :
+       m_isBuffered(false), m_reader(reader), m_keep(keep), m_format(format), m_current(0),
+       m_eos(false), m_loopcount(0), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING),
+       m_device(device)
+{
+       AUD_DeviceSpecs specs = m_device->m_specs;
+       specs.specs = m_reader->getSpecs();
+
+       // OpenAL playback code
+       alGenBuffers(CYCLE_BUFFERS, m_buffers);
+       if(alGetError() != AL_NO_ERROR)
+               AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error);
+
+       try
+       {
+               m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
+               int length;
+               bool eos;
+
+               for(int i = 0; i < CYCLE_BUFFERS; i++)
+               {
+                       length = m_device->m_buffersize;
+                       reader->read(length, eos, m_device->m_buffer.getBuffer());
+                       alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(),
+                                                length * AUD_DEVICE_SAMPLE_SIZE(specs),
+                                                specs.rate);
+                       if(alGetError() != AL_NO_ERROR)
+                               AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error);
+               }
+
+               alGenSources(1, &m_source);
+               if(alGetError() != AL_NO_ERROR)
+                       AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
+
+               try
+               {
+                       alSourceQueueBuffers(m_source, CYCLE_BUFFERS,
+                                                                m_buffers);
+                       if(alGetError() != AL_NO_ERROR)
+                               AUD_THROW(AUD_ERROR_OPENAL, queue_error);
+               }
+               catch(AUD_Exception&)
+               {
+                       alDeleteSources(1, &m_source);
+                       throw;
+               }
+       }
+       catch(AUD_Exception&)
+       {
+               alDeleteBuffers(CYCLE_BUFFERS, m_buffers);
+               throw;
+       }
+       alSourcei(m_source, AL_SOURCE_RELATIVE, 1);
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::pause()
+{
+       if(m_status)
+       {
+               m_device->lock();
+
+               if(m_status == AUD_STATUS_PLAYING)
+               {
+                       m_device->m_playingSounds.remove(this);
+                       m_device->m_pausedSounds.push_back(this);
+
+                       alSourcePause(m_source);
+
+                       m_status = AUD_STATUS_PAUSED;
+                       m_device->unlock();
+
+                       return true;
+               }
+
+               m_device->unlock();
+       }
+
+       return false;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::resume()
+{
+       if(m_status)
+       {
+               m_device->lock();
+
+               if(m_status == AUD_STATUS_PAUSED)
+               {
+                       m_device->m_pausedSounds.remove(this);
+                       m_device->m_playingSounds.push_back(this);
+
+                       m_device->start();
+                       m_status = AUD_STATUS_PLAYING;
+                       m_device->unlock();
+                       return true;
+               }
+
+               m_device->unlock();
+       }
+
+       return false;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::stop()
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       if(m_status == AUD_STATUS_PLAYING)
+               m_device->m_playingSounds.remove(this);
+       else
+               m_device->m_pausedSounds.remove(this);
+
+       m_device->unlock();
+
+       alDeleteSources(1, &m_source);
+       if(!m_isBuffered)
+               alDeleteBuffers(CYCLE_BUFFERS, m_buffers);
+
+       m_status = AUD_STATUS_INVALID;
+       return true;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::getKeep()
+{
+       if(m_status)
+               return m_keep;
+
+       return false;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setKeep(bool keep)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       m_keep = keep;
+
+       m_device->unlock();
+
+       return true;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       if(m_isBuffered)
+               alSourcef(m_source, AL_SEC_OFFSET, position);
+       else
+       {
+               m_reader->seek((int)(position * m_reader->getSpecs().rate));
+               m_eos = false;
+
+               ALint info;
+
+               alGetSourcei(m_source, AL_SOURCE_STATE, &info);
+
+               if(info != AL_PLAYING)
+               {
+                       if(info == AL_PAUSED)
+                               alSourceStop(m_source);
+
+                       alSourcei(m_source, AL_BUFFER, 0);
+                       m_current = 0;
+
+                       ALenum err;
+                       if((err = alGetError()) == AL_NO_ERROR)
+                       {
+                               int length;
+                               AUD_DeviceSpecs specs = m_device->m_specs;
+                               specs.specs = m_reader->getSpecs();
+                               m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
+
+                               for(int i = 0; i < CYCLE_BUFFERS; i++)
+                               {
+                                       length = m_device->m_buffersize;
+                                       m_reader->read(length, m_eos, m_device->m_buffer.getBuffer());
+                                       alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(),
+                                                                length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate);
+
+                                       if(alGetError() != AL_NO_ERROR)
+                                               break;
+                               }
+
+                               if(m_loopcount != 0)
+                                       m_eos = false;
+
+                               alSourceQueueBuffers(m_source, CYCLE_BUFFERS, m_buffers);
+                       }
+
+                       alSourceRewind(m_source);
+               }
+       }
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getPosition()
+{
+       if(!m_status)
+               return 0.0f;
+
+       m_device->lock();
+
+       float position = 0.0f;
+
+       alGetSourcef(m_source, AL_SEC_OFFSET, &position);
+
+       if(!m_isBuffered)
+       {
+               AUD_Specs specs = m_reader->getSpecs();
+               position += (m_reader->getPosition() - m_device->m_buffersize *
+                                        CYCLE_BUFFERS) / (float)specs.rate;
+       }
+
+       m_device->unlock();
+
+       return position;
+}
+
+AUD_Status AUD_OpenALDevice::AUD_OpenALHandle::getStatus()
+{
+       return m_status;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getVolume()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_GAIN, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setVolume(float volume)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_GAIN, volume);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getPitch()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_PITCH, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setPitch(float pitch)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_PITCH, pitch);
+
+       m_device->unlock();
+
+       return true;
+}
+
+int AUD_OpenALDevice::AUD_OpenALHandle::getLoopCount()
+{
+       if(!m_status)
+               return 0;
+       return m_loopcount;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setLoopCount(int count)
+{
+       if(!m_status)
+               return false;
+       m_loopcount = count;
+       return true;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setStopCallback(stopCallback callback, void* data)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       m_stop = callback;
+       m_stop_data = data;
+
+       m_device->unlock();
+
+       return true;
+}
+
+/******************************************************************************/
+/********************* AUD_OpenALHandle 3DHandle Code *************************/
+/******************************************************************************/
+
+AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceLocation()
+{
+       AUD_Vector3 result = AUD_Vector3(0, 0, 0);
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       ALfloat p[3];
+       alGetSourcefv(m_source, AL_POSITION, p);
+
+       m_device->unlock();
+
+       result = AUD_Vector3(p[0], p[1], p[2]);
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceLocation(const AUD_Vector3& location)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcefv(m_source, AL_POSITION, (ALfloat*)location.get());
+
+       m_device->unlock();
+
+       return true;
+}
+
+AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceVelocity()
+{
+       AUD_Vector3 result = AUD_Vector3(0, 0, 0);
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       ALfloat v[3];
+       alGetSourcefv(m_source, AL_VELOCITY, v);
+
+       m_device->unlock();
+
+       result = AUD_Vector3(v[0], v[1], v[2]);
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceVelocity(const AUD_Vector3& velocity)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcefv(m_source, AL_VELOCITY, (ALfloat*)velocity.get());
+
+       m_device->unlock();
+
+       return true;
+}
+
+AUD_Quaternion AUD_OpenALDevice::AUD_OpenALHandle::getSourceOrientation()
+{
+       // AUD_XXX not implemented yet
+       return AUD_Quaternion(0, 0, 0, 0);
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceOrientation(const AUD_Quaternion& orientation)
+{
+       if(!m_status)
+               return false;
+
+       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;
+       m_device->lock();
+
+       alSourcefv(m_source, AL_DIRECTION, direction);
+
+       m_device->unlock();
+
+       return true;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::isRelative()
+{
+       int result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcei(m_source, AL_SOURCE_RELATIVE, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setRelative(bool relative)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcei(m_source, AL_SOURCE_RELATIVE, relative);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMaximum()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_MAX_GAIN, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMaximum(float volume)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_MAX_GAIN, volume);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMinimum()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_MIN_GAIN, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMinimum(float volume)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_MIN_GAIN, volume);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceMaximum()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_MAX_DISTANCE, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceMaximum(float distance)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_MAX_DISTANCE, distance);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceReference()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceReference(float distance)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_REFERENCE_DISTANCE, distance);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getAttenuation()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setAttenuation(float factor)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_ROLLOFF_FACTOR, factor);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleOuter()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
 
-/// Saves the data for playback.
-struct AUD_OpenALHandle : AUD_Handle
+       alGetSourcef(m_source, AL_CONE_OUTER_ANGLE, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleOuter(float angle)
 {
-       /// Whether it's a buffered or a streamed source.
-       bool isBuffered;
+       if(!m_status)
+               return false;
 
-       /// The reader source.
-       AUD_IReader* reader;
+       m_device->lock();
 
-       /// Whether to keep the source if end of it is reached.
-       bool keep;
+       alSourcef(m_source, AL_CONE_OUTER_ANGLE, angle);
 
-       /// OpenAL sample format.
-       ALenum format;
+       m_device->unlock();
 
-       /// OpenAL source.
-       ALuint source;
+       return true;
+}
 
-       /// OpenAL buffers.
-       ALuint buffers[AUD_OPENAL_CYCLE_BUFFERS];
+float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleInner()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
 
-       /// The first buffer to be read next.
-       int current;
+       if(!m_status)
+               return result;
 
-       /// Whether the stream doesn't return any more data.
-       bool data_end;
+       m_device->lock();
 
-       /// The loop count of the source.
-       int loopcount;
+       alGetSourcef(m_source, AL_CONE_INNER_ANGLE, &result);
 
-       /// The stop callback.
-       stopCallback stop;
+       m_device->unlock();
 
-       /// Stop callback data.
-       void* stop_data;
-};
+       return result;
+}
 
-struct AUD_OpenALBufferedFactory
+bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleInner(float angle)
 {
-       /// The factory.
-       AUD_IFactory* factory;
+       if(!m_status)
+               return false;
 
-       /// The OpenAL buffer.
-       ALuint buffer;
-};
+       m_device->lock();
+
+       alSourcef(m_source, AL_CONE_INNER_ANGLE, angle);
+
+       m_device->unlock();
+
+       return true;
+}
+
+float AUD_OpenALDevice::AUD_OpenALHandle::getConeVolumeOuter()
+{
+       float result = std::numeric_limits<float>::quiet_NaN();
+
+       if(!m_status)
+               return result;
+
+       m_device->lock();
+
+       alGetSourcef(m_source, AL_CONE_OUTER_GAIN, &result);
+
+       m_device->unlock();
+
+       return result;
+}
+
+bool AUD_OpenALDevice::AUD_OpenALHandle::setConeVolumeOuter(float volume)
+{
+       if(!m_status)
+               return false;
+
+       m_device->lock();
+
+       alSourcef(m_source, AL_CONE_OUTER_GAIN, volume);
+
+       m_device->unlock();
 
-typedef std::list<AUD_OpenALHandle*>::iterator AUD_HandleIterator;
-typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator;
+       return true;
+}
 
 /******************************************************************************/
 /**************************** Threading Code **********************************/
@@ -127,16 +793,15 @@ void AUD_OpenALDevice::start()
 
 void AUD_OpenALDevice::updateStreams()
 {
-       AUD_OpenALHandle* sound;
+       AUD_Reference<AUD_OpenALHandle> sound;
 
        int length;
-       sample_t* buffer;
 
        ALint info;
        AUD_DeviceSpecs specs = m_specs;
        ALCenum cerr;
-       std::list<AUD_OpenALHandle*> stopSounds;
-       std::list<AUD_OpenALHandle*> pauseSounds;
+       std::list<AUD_Reference<AUD_OpenALHandle> > stopSounds;
+       std::list<AUD_Reference<AUD_OpenALHandle> > pauseSounds;
        AUD_HandleIterator it;
 
        while(1)
@@ -148,83 +813,86 @@ void AUD_OpenALDevice::updateStreams()
                if(cerr == ALC_NO_ERROR)
                {
                        // for all sounds
-                       for(it = m_playingSounds->begin(); it != m_playingSounds->end(); it++)
+                       for(it = m_playingSounds.begin(); it != m_playingSounds.end(); it++)
                        {
                                sound = *it;
 
                                // is it a streamed sound?
-                               if(!sound->isBuffered)
+                               if(!sound->m_isBuffered)
                                {
                                        // check for buffer refilling
-                                       alGetSourcei(sound->source, AL_BUFFERS_PROCESSED, &info);
+                                       alGetSourcei(sound->m_source, AL_BUFFERS_PROCESSED, &info);
 
                                        if(info)
                                        {
-                                               specs.specs = sound->reader->getSpecs();
+                                               specs.specs = sound->m_reader->getSpecs();
+                                               m_buffer.assureSize(m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs));
 
                                                // for all empty buffers
                                                while(info--)
                                                {
                                                        // if there's still data to play back
-                                                       if(!sound->data_end)
+                                                       if(!sound->m_eos)
                                                        {
                                                                // read data
                                                                length = m_buffersize;
-                                                               sound->reader->read(length, buffer);
+                                                               sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer());
 
                                                                // looping necessary?
-                                                               if(length == 0 && sound->loopcount)
+                                                               if(length == 0 && sound->m_loopcount)
                                                                {
-                                                                       if(sound->loopcount > 0)
-                                                                               sound->loopcount--;
+                                                                       if(sound->m_loopcount > 0)
+                                                                               sound->m_loopcount--;
 
-                                                                       sound->reader->seek(0);
+                                                                       sound->m_reader->seek(0);
 
                                                                        length = m_buffersize;
-                                                                       sound->reader->read(length, buffer);
+                                                                       sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer());
                                                                }
 
+                                                               if(sound->m_loopcount != 0)
+                                                                       sound->m_eos = false;
+
                                                                // read nothing?
                                                                if(length == 0)
                                                                {
-                                                                       sound->data_end = true;
                                                                        break;
                                                                }
 
                                                                // unqueue buffer
-                                                               alSourceUnqueueBuffers(sound->source, 1,
-                                                                                               &sound->buffers[sound->current]);
+                                                               alSourceUnqueueBuffers(sound->m_source, 1,
+                                                                                               &sound->m_buffers[sound->m_current]);
                                                                ALenum err;
                                                                if((err = alGetError()) != AL_NO_ERROR)
                                                                {
-                                                                       sound->data_end = true;
+                                                                       sound->m_eos = true;
                                                                        break;
                                                                }
 
                                                                // fill with new data
-                                                               alBufferData(sound->buffers[sound->current],
-                                                                                        sound->format,
-                                                                                        buffer, length *
+                                                               alBufferData(sound->m_buffers[sound->m_current],
+                                                                                        sound->m_format,
+                                                                                        m_buffer.getBuffer(), length *
                                                                                         AUD_DEVICE_SAMPLE_SIZE(specs),
                                                                                         specs.rate);
 
                                                                if((err = alGetError()) != AL_NO_ERROR)
                                                                {
-                                                                       sound->data_end = true;
+                                                                       sound->m_eos = true;
                                                                        break;
                                                                }
 
                                                                // and queue again
-                                                               alSourceQueueBuffers(sound->source, 1,
-                                                                                               &sound->buffers[sound->current]);
+                                                               alSourceQueueBuffers(sound->m_source, 1,
+                                                                                               &sound->m_buffers[sound->m_current]);
                                                                if(alGetError() != AL_NO_ERROR)
                                                                {
-                                                                       sound->data_end = true;
+                                                                       sound->m_eos = true;
                                                                        break;
                                                                }
 
-                                                               sound->current = (sound->current+1) %
-                                                                                                AUD_OPENAL_CYCLE_BUFFERS;
+                                                               sound->m_current = (sound->m_current+1) %
+                                                                                                AUD_OpenALHandle::CYCLE_BUFFERS;
                                                        }
                                                        else
                                                                break;
@@ -233,18 +901,18 @@ void AUD_OpenALDevice::updateStreams()
                                }
 
                                // check if the sound has been stopped
-                               alGetSourcei(sound->source, AL_SOURCE_STATE, &info);
+                               alGetSourcei(sound->m_source, AL_SOURCE_STATE, &info);
 
                                if(info != AL_PLAYING)
                                {
                                        // if it really stopped
-                                       if(sound->data_end)
+                                       if(sound->m_eos)
                                        {
-                                               if(sound->stop)
-                                                       sound->stop(sound->stop_data);
+                                               if(sound->m_stop)
+                                                       sound->m_stop(sound->m_stop_data);
 
                                                // pause or
-                                               if(sound->keep)
+                                               if(sound->m_keep)
                                                        pauseSounds.push_back(sound);
                                                // stop
                                                else
@@ -252,15 +920,15 @@ void AUD_OpenALDevice::updateStreams()
                                        }
                                        // continue playing
                                        else
-                                               alSourcePlay(sound->source);
+                                               alSourcePlay(sound->m_source);
                                }
                        }
 
                        for(it = pauseSounds.begin(); it != pauseSounds.end(); it++)
-                               pause(*it);
+                               (*it)->pause();
 
                        for(it = stopSounds.begin(); it != stopSounds.end(); it++)
-                               stop(*it);
+                               (*it)->stop();
 
                        pauseSounds.clear();
                        stopSounds.clear();
@@ -269,7 +937,7 @@ void AUD_OpenALDevice::updateStreams()
                }
 
                // stop thread
-               if(m_playingSounds->empty() || (cerr != ALC_NO_ERROR))
+               if(m_playingSounds.empty() || (cerr != ALC_NO_ERROR))
                {
                        unlock();
                        m_playing = false;
@@ -290,19 +958,6 @@ void AUD_OpenALDevice::updateStreams()
 /**************************** IDevice Code ************************************/
 /******************************************************************************/
 
-bool AUD_OpenALDevice::isValid(AUD_Handle* handle)
-{
-       for(AUD_HandleIterator i = m_playingSounds->begin();
-               i != m_playingSounds->end(); i++)
-               if(*i == handle)
-                       return true;
-       for(AUD_HandleIterator i = m_pausedSounds->begin();
-               i != m_pausedSounds->end(); i++)
-               if(*i == handle)
-                       return true;
-       return false;
-}
-
 static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened.";
 
 AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
@@ -355,9 +1010,7 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
        m_buffersize = buffersize;
        m_playing = false;
 
-       m_playingSounds = new std::list<AUD_OpenALHandle*>();
-       m_pausedSounds = new std::list<AUD_OpenALHandle*>();
-       m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
+//     m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
 
        pthread_mutexattr_t attr;
        pthread_mutexattr_init(&attr);
@@ -370,46 +1023,23 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
 
 AUD_OpenALDevice::~AUD_OpenALDevice()
 {
-       AUD_OpenALHandle* sound;
-
        lock();
        alcSuspendContext(m_context);
 
-       // delete all playing sounds
-       while(!m_playingSounds->empty())
-       {
-               sound = *(m_playingSounds->begin());
-               alDeleteSources(1, &sound->source);
-               if(!sound->isBuffered)
-               {
-                       delete sound->reader;
-                       alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
-               }
-               delete sound;
-               m_playingSounds->erase(m_playingSounds->begin());
-       }
+       while(!m_playingSounds.empty())
+               m_playingSounds.front()->stop();
+
+       while(!m_pausedSounds.empty())
+               m_pausedSounds.front()->stop();
 
-       // delete all paused sounds
-       while(!m_pausedSounds->empty())
-       {
-               sound = *(m_pausedSounds->begin());
-               alDeleteSources(1, &sound->source);
-               if(!sound->isBuffered)
-               {
-                       delete sound->reader;
-                       alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
-               }
-               delete sound;
-               m_pausedSounds->erase(m_pausedSounds->begin());
-       }
 
        // delete all buffered factories
-       while(!m_bufferedFactories->empty())
+       /*while(!m_bufferedFactories->empty())
        {
                alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer);
                delete *m_bufferedFactories->begin();
                m_bufferedFactories->erase(m_bufferedFactories->begin());
-       }
+       }*/
 
        alcProcessContext(m_context);
 
@@ -422,9 +1052,7 @@ AUD_OpenALDevice::~AUD_OpenALDevice()
        else
                unlock();
 
-       delete m_playingSounds;
-       delete m_pausedSounds;
-       delete m_bufferedFactories;
+       //delete m_bufferedFactories;
 
        // quit OpenAL
        alcMakeContextCurrent(NULL);
@@ -530,120 +1158,54 @@ 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_IReader* reader, bool keep)
+AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IReader> reader, bool keep)
 {
-       AUD_OpenALHandle* sound = NULL;
-
-       AUD_DeviceSpecs specs = m_specs;
-       specs.specs = reader->getSpecs();
+       AUD_Specs specs = reader->getSpecs();
 
        // check format
-       bool valid = specs.channels != AUD_CHANNELS_INVALID;
+       if(specs.channels == AUD_CHANNELS_INVALID)
+               return NULL;
 
        if(m_specs.format != AUD_FORMAT_FLOAT32)
                reader = new AUD_ConverterReader(reader, m_specs);
 
-       // create the 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);
+       ALenum format;
 
-       if(!valid)
-       {
-               delete sound;
-               delete reader;
+       if(!getFormat(format, specs))
                return NULL;
-       }
 
        lock();
        alcSuspendContext(m_context);
 
-       // OpenAL playback code
+       AUD_Reference<AUD_OpenALDevice::AUD_OpenALHandle> sound;
+
        try
        {
-               alGenBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
-               if(alGetError() != AL_NO_ERROR)
-                       AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error);
-
-               try
-               {
-                       sample_t* buf;
-                       int length;
-
-                       for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++)
-                       {
-                               length = m_buffersize;
-                               reader->read(length, buf);
-                               alBufferData(sound->buffers[i], sound->format, buf,
-                                                        length * AUD_DEVICE_SAMPLE_SIZE(specs),
-                                                        specs.rate);
-                               if(alGetError() != AL_NO_ERROR)
-                                       AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error);
-                       }
-
-                       alGenSources(1, &sound->source);
-                       if(alGetError() != AL_NO_ERROR)
-                               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, queue_error);
-                       }
-                       catch(AUD_Exception&)
-                       {
-                               alDeleteSources(1, &sound->source);
-                               throw;
-                       }
-               }
-               catch(AUD_Exception&)
-               {
-                       alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
-                       throw;
-               }
+               // create the handle
+               sound = new AUD_OpenALDevice::AUD_OpenALHandle(this, format, reader, keep);
        }
        catch(AUD_Exception&)
        {
-               delete sound;
-               delete reader;
                alcProcessContext(m_context);
                unlock();
                throw;
        }
 
+       alcProcessContext(m_context);
+
        // play sound
-       m_playingSounds->push_back(sound);
-       alSourcei(sound->source, AL_SOURCE_RELATIVE, 1);
+       m_playingSounds.push_back(sound);
 
        start();
 
-       alcProcessContext(m_context);
        unlock();
 
-       return sound;
+       return AUD_Reference<AUD_IHandle>(sound);
 }
 
-AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
+AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep)
 {
+       /* AUD_XXX disabled
        AUD_OpenALHandle* sound = NULL;
 
        lock();
@@ -661,7 +1223,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
                                sound->keep = keep;
                                sound->current = -1;
                                sound->isBuffered = true;
-                               sound->data_end = true;
+                               sound->eos = true;
                                sound->loopcount = 0;
                                sound->stop = NULL;
                                sound->stop_data = NULL;
@@ -713,264 +1275,9 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
        unlock();
 
        if(sound)
-               return sound;
-
-       return play(factory->createReader(), keep);
-}
-
-bool AUD_OpenALDevice::pause(AUD_Handle* handle)
-{
-       bool result = false;
-
-       lock();
-
-       // only songs that are played can be paused
-       for(AUD_HandleIterator i = m_playingSounds->begin();
-               i != m_playingSounds->end(); i++)
-       {
-               if(*i == handle)
-               {
-                       m_pausedSounds->push_back(*i);
-                       alSourcePause((*i)->source);
-                       m_playingSounds->erase(i);
-                       result = true;
-                       break;
-               }
-       }
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_OpenALDevice::resume(AUD_Handle* handle)
-{
-       bool result = false;
-
-       lock();
-
-       // only songs that are paused can be resumed
-       for(AUD_HandleIterator i = m_pausedSounds->begin();
-               i != m_pausedSounds->end(); i++)
-       {
-               if(*i == handle)
-               {
-                       m_playingSounds->push_back(*i);
-                       start();
-                       m_pausedSounds->erase(i);
-                       result = true;
-                       break;
-               }
-       }
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_OpenALDevice::stop(AUD_Handle* handle)
-{
-       AUD_OpenALHandle* sound;
-
-       bool result = false;
-
-       lock();
-
-       for(AUD_HandleIterator i = m_playingSounds->begin();
-               i != m_playingSounds->end(); i++)
-       {
-               if(*i == handle)
-               {
-                       sound = *i;
-                       alDeleteSources(1, &sound->source);
-                       if(!sound->isBuffered)
-                       {
-                               delete sound->reader;
-                               alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
-                       }
-                       delete *i;
-                       m_playingSounds->erase(i);
-                       result = true;
-                       break;
-               }
-       }
-       if(!result)
-       {
-               for(AUD_HandleIterator i = m_pausedSounds->begin();
-                       i != m_pausedSounds->end(); i++)
-               {
-                       if(*i == handle)
-                       {
-                               sound = *i;
-                               alDeleteSources(1, &sound->source);
-                               if(!sound->isBuffered)
-                               {
-                                       delete sound->reader;
-                                       alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
-                               }
-                               delete *i;
-                               m_pausedSounds->erase(i);
-                               result = true;
-                               break;
-                       }
-               }
-       }
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_OpenALDevice::getKeep(AUD_Handle* handle)
-{
-       bool result = false;
-
-       lock();
-
-       if(isValid(handle))
-               result = ((AUD_OpenALHandle*)handle)->keep;
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep)
-{
-       bool result = false;
-
-       lock();
-
-       if(isValid(handle))
-       {
-               ((AUD_OpenALHandle*)handle)->keep = keep;
-               result = true;
-       }
-
-       unlock();
-
-       return result;
-}
-
-bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position)
-{
-       bool result = false;
-
-       lock();
-
-       if(isValid(handle))
-       {
-               AUD_OpenALHandle* alhandle = (AUD_OpenALHandle*)handle;
-               if(alhandle->isBuffered)
-                       alSourcef(alhandle->source, AL_SEC_OFFSET, position);
-               else
-               {
-                       alhandle->reader->seek((int)(position *
-                                                                                alhandle->reader->getSpecs().rate));
-                       alhandle->data_end = false;
-
-                       ALint info;
-
-                       alGetSourcei(alhandle->source, AL_SOURCE_STATE, &info);
-
-                       if(info != AL_PLAYING)
-                       {
-                               if(info == AL_PAUSED)
-                                       alSourceStop(alhandle->source);
-
-                               alSourcei(alhandle->source, AL_BUFFER, 0);
-                               alhandle->current = 0;
-
-                               ALenum err;
-                               if((err = alGetError()) == AL_NO_ERROR)
-                               {
-                                       sample_t* buf;
-                                       int length;
-                                       AUD_DeviceSpecs specs = m_specs;
-                                       specs.specs = alhandle->reader->getSpecs();
-
-                                       for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++)
-                                       {
-                                               length = m_buffersize;
-                                               alhandle->reader->read(length, buf);
-                                               alBufferData(alhandle->buffers[i], alhandle->format,
-                                                                        buf,
-                                                                        length * AUD_DEVICE_SAMPLE_SIZE(specs),
-                                                                        specs.rate);
-
-                                               if(alGetError() != AL_NO_ERROR)
-                                                       break;
-                                       }
-
-                                       alSourceQueueBuffers(alhandle->source,
-                                                                                AUD_OPENAL_CYCLE_BUFFERS,
-                                                                                alhandle->buffers);
-                               }
-
-                               alSourceRewind(alhandle->source);
-                       }
-               }
-               result = true;
-       }
-
-       unlock();
-       return result;
-}
-
-float AUD_OpenALDevice::getPosition(AUD_Handle* handle)
-{
-       float position = 0.0f;
-
-       lock();
-
-       if(isValid(handle))
-       {
-               AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle;
-               alGetSourcef(h->source, AL_SEC_OFFSET, &position);
-               if(!h->isBuffered)
-               {
-                       AUD_Specs specs = h->reader->getSpecs();
-                       position += (h->reader->getPosition() - m_buffersize *
-                                                                       AUD_OPENAL_CYCLE_BUFFERS) /
-                                          (float)specs.rate;
-               }
-       }
-
-       unlock();
-       return position;
-}
-
-AUD_Status AUD_OpenALDevice::getStatus(AUD_Handle* handle)
-{
-       AUD_Status status = AUD_STATUS_INVALID;
-
-       lock();
-
-       for(AUD_HandleIterator i = m_playingSounds->begin();
-               i != m_playingSounds->end(); i++)
-       {
-               if(*i == handle)
-               {
-                       status = AUD_STATUS_PLAYING;
-                       break;
-               }
-       }
-       if(status == AUD_STATUS_INVALID)
-       {
-               for(AUD_HandleIterator i = m_pausedSounds->begin();
-                       i != m_pausedSounds->end(); i++)
-               {
-                       if(*i == handle)
-                       {
-                               status = AUD_STATUS_PAUSED;
-                               break;
-                       }
-               }
-       }
-
-       unlock();
+               return sound;*/
 
-       return status;
+       return play(factory->createReader(), keep);
 }
 
 void AUD_OpenALDevice::lock()
@@ -995,80 +1302,6 @@ void AUD_OpenALDevice::setVolume(float volume)
        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::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)
@@ -1109,7 +1342,6 @@ bool AUD_OpenALDevice::bufferFactory(void *value)
 
                if(!getFormat(format, specs.specs))
                {
-                       delete reader;
                        return false;
                }
 
@@ -1147,7 +1379,6 @@ bool AUD_OpenALDevice::bufferFactory(void *value)
                catch(AUD_Exception&)
                {
                        delete bf;
-                       delete reader;
                        alcProcessContext(m_context);
                        unlock();
                        return false;
@@ -1308,333 +1539,3 @@ void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model)
                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;
-}
-
-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());
-
-       unlock();
-       return result;
-}
-
-AUD_Vector3 AUD_OpenALDevice::getSourceVelocity(AUD_Handle* 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::setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-               alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY,
-                                  (ALfloat*)velocity.get());
-
-       unlock();
-       return result;
-}
-
-AUD_Quaternion AUD_OpenALDevice::getSourceOrientation(AUD_Handle* handle)
-{
-       // AUD_XXX not implemented yet
-       return AUD_Quaternion(0, 0, 0, 0);
-}
-
-bool AUD_OpenALDevice::setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation)
-{
-       lock();
-       bool result = isValid(handle);
-
-       if(result)
-       {
-               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::isRelative(AUD_Handle* handle)
-{
-       int result = std::numeric_limits<float>::quiet_NaN();;
-
-       lock();
-
-       if(isValid(handle))
-               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;
-}
-
-float AUD_OpenALDevice::getVolumeMaximum(AUD_Handle* handle)
-{
-       float result = std::numeric_limits<float>::quiet_NaN();;
-
-       lock();
-
-       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))
-               alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN,
-                                        &result);
-
-       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::getDistanceMaximum(AUD_Handle* handle)
-{
-       float result = std::numeric_limits<float>::quiet_NaN();;
-
-       lock();
-
-       if(isValid(handle))
-               alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE,
-                                        &result);
-
-       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 3bbbe85d7e6480930f6e3b11a0723f2621c68a8c..ea4f9ca1ea818667ec058d567c82db12add38886 100644 (file)
 #define AUD_OPENALDEVICE
 
 #include "AUD_IDevice.h"
+#include "AUD_IHandle.h"
 #include "AUD_I3DDevice.h"
-struct AUD_OpenALHandle;
-struct AUD_OpenALBufferedFactory;
+#include "AUD_I3DHandle.h"
+#include "AUD_Buffer.h"
+//struct AUD_OpenALBufferedFactory;
 
 #include <AL/al.h>
 #include <AL/alc.h>
@@ -48,6 +50,100 @@ struct AUD_OpenALBufferedFactory;
 class AUD_OpenALDevice : public AUD_IDevice, public AUD_I3DDevice
 {
 private:
+       /// Saves the data for playback.
+       class AUD_OpenALHandle : public AUD_IHandle, public AUD_I3DHandle
+       {
+       public:
+               static const int CYCLE_BUFFERS = 3;
+
+               /// Whether it's a buffered or a streamed source.
+               bool m_isBuffered;
+
+               /// The reader source.
+               AUD_Reference<AUD_IReader> m_reader;
+
+               /// Whether to keep the source if end of it is reached.
+               bool m_keep;
+
+               /// OpenAL sample format.
+               ALenum m_format;
+
+               /// OpenAL source.
+               ALuint m_source;
+
+               /// OpenAL buffers.
+               ALuint m_buffers[CYCLE_BUFFERS];
+
+               /// The first buffer to be read next.
+               int m_current;
+
+               /// Whether the stream doesn't return any more data.
+               bool m_eos;
+
+               /// The loop count of the source.
+               int m_loopcount;
+
+               /// The stop callback.
+               stopCallback m_stop;
+
+               /// Stop callback data.
+               void* m_stop_data;
+
+               /// Current status of the handle
+               AUD_Status m_status;
+
+               /// Own device.
+               AUD_OpenALDevice* m_device;
+
+       public:
+
+               AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference<AUD_IReader> reader, bool keep);
+
+               virtual ~AUD_OpenALHandle() {}
+               virtual bool pause();
+               virtual bool resume();
+               virtual bool stop();
+               virtual bool getKeep();
+               virtual bool setKeep(bool keep);
+               virtual bool seek(float position);
+               virtual float getPosition();
+               virtual AUD_Status getStatus();
+               virtual float getVolume();
+               virtual bool setVolume(float volume);
+               virtual float getPitch();
+               virtual bool setPitch(float pitch);
+               virtual int getLoopCount();
+               virtual bool setLoopCount(int count);
+               virtual bool setStopCallback(stopCallback callback = 0, void* data = 0);
+
+               virtual AUD_Vector3 getSourceLocation();
+               virtual bool setSourceLocation(const AUD_Vector3& location);
+               virtual AUD_Vector3 getSourceVelocity();
+               virtual bool setSourceVelocity(const AUD_Vector3& velocity);
+               virtual AUD_Quaternion getSourceOrientation();
+               virtual bool setSourceOrientation(const AUD_Quaternion& orientation);
+               virtual bool isRelative();
+               virtual bool setRelative(bool relative);
+               virtual float getVolumeMaximum();
+               virtual bool setVolumeMaximum(float volume);
+               virtual float getVolumeMinimum();
+               virtual bool setVolumeMinimum(float volume);
+               virtual float getDistanceMaximum();
+               virtual bool setDistanceMaximum(float distance);
+               virtual float getDistanceReference();
+               virtual bool setDistanceReference(float distance);
+               virtual float getAttenuation();
+               virtual bool setAttenuation(float factor);
+               virtual float getConeAngleOuter();
+               virtual bool setConeAngleOuter(float angle);
+               virtual float getConeAngleInner();
+               virtual bool setConeAngleInner(float angle);
+               virtual float getConeVolumeOuter();
+               virtual bool setConeVolumeOuter(float volume);
+       };
+
+       typedef std::list<AUD_Reference<AUD_OpenALHandle> >::iterator AUD_HandleIterator;
+
        /**
         * The OpenAL device handle.
         */
@@ -71,17 +167,17 @@ private:
        /**
         * The list of sounds that are currently playing.
         */
-       std::list<AUD_OpenALHandle*>* m_playingSounds;
+       std::list<AUD_Reference<AUD_OpenALHandle> > m_playingSounds;
 
        /**
         * The list of sounds that are currently paused.
         */
-       std::list<AUD_OpenALHandle*>* m_pausedSounds;
+       std::list<AUD_Reference<AUD_OpenALHandle> > m_pausedSounds;
 
        /**
         * The list of buffered factories.
         */
-       std::list<AUD_OpenALBufferedFactory*>* m_bufferedFactories;
+       //std::list<AUD_OpenALBufferedFactory*>* m_bufferedFactories;
 
        /**
         * The mutex for locking.
@@ -104,16 +200,14 @@ private:
        int m_buffersize;
 
        /**
-        * Starts the streaming thread.
+        * Device buffer.
         */
-       void start();
+       AUD_Buffer m_buffer;
 
        /**
-        * Checks if a handle is valid.
-        * \param handle The handle to check.
-        * \return Whether the handle is valid.
+        * Starts the streaming thread.
         */
-       bool isValid(AUD_Handle* handle);
+       void start();
 
        /**
         * Gets the format according to the specs.
@@ -147,27 +241,12 @@ public:
        virtual ~AUD_OpenALDevice();
 
        virtual AUD_DeviceSpecs getSpecs() const;
-       virtual AUD_Handle* play(AUD_IReader* reader, bool keep = false);
-       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 seek(AUD_Handle* handle, float position);
-       virtual float getPosition(AUD_Handle* handle);
-       virtual AUD_Status getStatus(AUD_Handle* handle);
+       virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false);
+       virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false);
        virtual void lock();
        virtual void unlock();
        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);
@@ -181,30 +260,6 @@ public:
        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
index 22376a2fcd147dd1e78ff2fbedb3bb9f1b1b6c77..12bb19644f0ef9be0058de07d8a10d239f419b20 100644 (file)
@@ -33,6 +33,7 @@
 #include "structmember.h"
 
 #include "AUD_I3DDevice.h"
+#include "AUD_I3DHandle.h"
 #include "AUD_NULLDevice.h"
 #include "AUD_DelayFactory.h"
 #include "AUD_DoubleFactory.h"
@@ -91,7 +92,7 @@ static void
 Factory_dealloc(Factory* self)
 {
        if(self->factory)
-               delete self->factory;
+               delete reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory);
        Py_XDECREF(self->child_list);
        Py_TYPE(self)->tp_free((PyObject*)self);
 }
@@ -115,7 +116,7 @@ Factory_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
                try
                {
-                       self->factory = new AUD_FileFactory(filename);
+                       self->factory = new AUD_Reference<AUD_IFactory>(new AUD_FileFactory(filename));
                }
                catch(AUD_Exception& e)
                {
@@ -155,7 +156,7 @@ Factory_sine(PyTypeObject* type, PyObject* args)
        {
                try
                {
-                       self->factory = new AUD_SinusFactory(frequency, (AUD_SampleRate)rate);
+                       self->factory = new AUD_Reference<AUD_IFactory>(new AUD_SinusFactory(frequency, (AUD_SampleRate)rate));
                }
                catch(AUD_Exception& e)
                {
@@ -194,7 +195,7 @@ Factory_file(PyTypeObject* type, PyObject* args)
        {
                try
                {
-                       self->factory = new AUD_FileFactory(filename);
+                       self->factory = new AUD_Reference<AUD_IFactory>(new AUD_FileFactory(filename));
                }
                catch(AUD_Exception& e)
                {
@@ -237,7 +238,7 @@ Factory_lowpass(Factory* self, PyObject* args)
 
                try
                {
-                       parent->factory = new AUD_LowpassFactory(self->factory, frequency, Q);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LowpassFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), frequency, Q));
                }
                catch(AUD_Exception& e)
                {
@@ -278,7 +279,7 @@ Factory_delay(Factory* self, PyObject* args)
 
                try
                {
-                       parent->factory = new AUD_DelayFactory(self->factory, delay);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_DelayFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), delay));
                }
                catch(AUD_Exception& e)
                {
@@ -322,7 +323,7 @@ Factory_join(Factory* self, PyObject* object)
 
                try
                {
-                       parent->factory = new AUD_DoubleFactory(self->factory, child->factory);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_DoubleFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), *reinterpret_cast<AUD_Reference<AUD_IFactory>*>(child->factory)));
                }
                catch(AUD_Exception& e)
                {
@@ -365,7 +366,7 @@ Factory_highpass(Factory* self, PyObject* args)
 
                try
                {
-                       parent->factory = new AUD_HighpassFactory(self->factory, frequency, Q);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_HighpassFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), frequency, Q));
                }
                catch(AUD_Exception& e)
                {
@@ -406,7 +407,7 @@ Factory_limit(Factory* self, PyObject* args)
 
                try
                {
-                       parent->factory = new AUD_LimiterFactory(self->factory, start, end);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LimiterFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), start, end));
                }
                catch(AUD_Exception& e)
                {
@@ -450,7 +451,7 @@ Factory_pitch(Factory* self, PyObject* args)
 
                try
                {
-                       parent->factory = new AUD_PitchFactory(self->factory, factor);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_PitchFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), factor));
                }
                catch(AUD_Exception& e)
                {
@@ -492,7 +493,7 @@ Factory_volume(Factory* self, PyObject* args)
 
                try
                {
-                       parent->factory = new AUD_VolumeFactory(self->factory, volume);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_VolumeFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), volume));
                }
                catch(AUD_Exception& e)
                {
@@ -535,7 +536,7 @@ Factory_fadein(Factory* self, PyObject* args)
 
                try
                {
-                       parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_IN, start, length);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_FaderFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), AUD_FADE_IN, start, length));
                }
                catch(AUD_Exception& e)
                {
@@ -579,7 +580,7 @@ Factory_fadeout(Factory* self, PyObject* args)
 
                try
                {
-                       parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_OUT, start, length);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_FaderFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), AUD_FADE_OUT, start, length));
                }
                catch(AUD_Exception& e)
                {
@@ -621,7 +622,7 @@ Factory_loop(Factory* self, PyObject* args)
 
                try
                {
-                       parent->factory = new AUD_LoopFactory(self->factory, loop);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LoopFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), loop));
                }
                catch(AUD_Exception& e)
                {
@@ -664,7 +665,7 @@ Factory_mix(Factory* self, PyObject* object)
 
                try
                {
-                       parent->factory = new AUD_SuperposeFactory(self->factory, child->factory);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_SuperposeFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), *reinterpret_cast<AUD_Reference<AUD_IFactory>*>(child->factory)));
                }
                catch(AUD_Exception& e)
                {
@@ -697,7 +698,7 @@ Factory_pingpong(Factory* self)
 
                try
                {
-                       parent->factory = new AUD_PingPongFactory(self->factory);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_PingPongFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory)));
                }
                catch(AUD_Exception& e)
                {
@@ -736,7 +737,7 @@ Factory_reverse(Factory* self)
 
                try
                {
-                       parent->factory = new AUD_ReverseFactory(self->factory);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_ReverseFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory)));
                }
                catch(AUD_Exception& e)
                {
@@ -771,7 +772,7 @@ Factory_buffer(Factory* self)
        {
                try
                {
-                       parent->factory = new AUD_StreamBufferFactory(self->factory);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_StreamBufferFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory)));
                }
                catch(AUD_Exception& e)
                {
@@ -813,7 +814,7 @@ Factory_square(Factory* self, PyObject* args)
 
                try
                {
-                       parent->factory = new AUD_SquareFactory(self->factory, threshold);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_SquareFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), threshold));
                }
                catch(AUD_Exception& e)
                {
@@ -910,7 +911,7 @@ Factory_filter(Factory* self, PyObject* args)
 
                try
                {
-                       parent->factory = new AUD_IIRFilterFactory(self->factory, b, a);
+                       parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_IIRFilterFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), b, a));
                }
                catch(AUD_Exception& e)
                {
@@ -1033,7 +1034,8 @@ static PyTypeObject FactoryType = {
 static void
 Handle_dealloc(Handle* self)
 {
-       Py_XDECREF(self->device);
+       if(self->handle)
+               delete reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle);
        Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
@@ -1046,11 +1048,9 @@ PyDoc_STRVAR(M_aud_Handle_pause_doc,
 static PyObject *
 Handle_pause(Handle *self)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return PyBool_FromLong((long)device->device->pause(self->handle));
+               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->pause());
        }
        catch(AUD_Exception& e)
        {
@@ -1068,11 +1068,9 @@ PyDoc_STRVAR(M_aud_Handle_resume_doc,
 static PyObject *
 Handle_resume(Handle *self)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return PyBool_FromLong((long)device->device->resume(self->handle));
+               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->resume());
        }
        catch(AUD_Exception& e)
        {
@@ -1091,11 +1089,9 @@ PyDoc_STRVAR(M_aud_Handle_stop_doc,
 static PyObject *
 Handle_stop(Handle *self)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return PyBool_FromLong((long)device->device->stop(self->handle));
+               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->stop());
        }
        catch(AUD_Exception& e)
        {
@@ -1123,11 +1119,9 @@ PyDoc_STRVAR(M_aud_Handle_position_doc,
 static PyObject *
 Handle_get_position(Handle *self, void* nothing)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return Py_BuildValue("f", device->device->getPosition(self->handle));
+               return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getPosition());
        }
        catch(AUD_Exception& e)
        {
@@ -1144,11 +1138,9 @@ Handle_set_position(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:position", &position))
                return -1;
 
-       Device* device = (Device*)self->device;
-
        try
        {
-               if(device->device->seek(self->handle, position))
+               if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->seek(position))
                        return 0;
                PyErr_SetString(AUDError, "Couldn't seek the sound!");
        }
@@ -1172,11 +1164,9 @@ PyDoc_STRVAR(M_aud_Handle_keep_doc,
 static PyObject *
 Handle_get_keep(Handle *self, void* nothing)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return PyBool_FromLong((long)device->device->getKeep(self->handle));
+               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getKeep());
        }
        catch(AUD_Exception& e)
        {
@@ -1195,11 +1185,10 @@ Handle_set_keep(Handle *self, PyObject* args, void* nothing)
        }
 
        bool keep = args == Py_True;
-       Device* device = (Device*)self->device;
 
        try
        {
-               if(device->device->setKeep(self->handle, keep))
+               if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setKeep(keep))
                        return 0;
                PyErr_SetString(AUDError, "Couldn't set keep of the sound!");
        }
@@ -1217,11 +1206,9 @@ PyDoc_STRVAR(M_aud_Handle_status_doc,
 static PyObject *
 Handle_get_status(Handle *self, void* nothing)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return PyBool_FromLong((long)device->device->getStatus(self->handle));
+               return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getStatus());
        }
        catch(AUD_Exception& e)
        {
@@ -1236,11 +1223,9 @@ PyDoc_STRVAR(M_aud_Handle_volume_doc,
 static PyObject *
 Handle_get_volume(Handle *self, void* nothing)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return Py_BuildValue("f", device->device->getVolume(self->handle));
+               return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getVolume());
        }
        catch(AUD_Exception& e)
        {
@@ -1257,11 +1242,9 @@ Handle_set_volume(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:volume", &volume))
                return -1;
 
-       Device* device = (Device*)self->device;
-
        try
        {
-               if(device->device->setVolume(self->handle, volume))
+               if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setVolume(volume))
                        return 0;
                PyErr_SetString(AUDError, "Couldn't set the sound volume!");
        }
@@ -1279,11 +1262,9 @@ PyDoc_STRVAR(M_aud_Handle_pitch_doc,
 static PyObject *
 Handle_get_pitch(Handle *self, void* nothing)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return Py_BuildValue("f", device->device->getPitch(self->handle));
+               return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getPitch());
        }
        catch(AUD_Exception& e)
        {
@@ -1300,11 +1281,9 @@ Handle_set_pitch(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:pitch", &pitch))
                return -1;
 
-       Device* device = (Device*)self->device;
-
        try
        {
-               if(device->device->setPitch(self->handle, pitch))
+               if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setPitch(pitch))
                        return 0;
                PyErr_SetString(AUDError, "Couldn't set the sound pitch!");
        }
@@ -1322,11 +1301,9 @@ PyDoc_STRVAR(M_aud_Handle_loop_count_doc,
 static PyObject *
 Handle_get_loop_count(Handle *self, void* nothing)
 {
-       Device* device = (Device*)self->device;
-
        try
        {
-               return Py_BuildValue("i", device->device->getLoopCount(self->handle));
+               return Py_BuildValue("i", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getLoopCount());
        }
        catch(AUD_Exception& e)
        {
@@ -1343,11 +1320,9 @@ Handle_set_loop_count(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "i:loop_count", &loops))
                return -1;
 
-       Device* device = (Device*)self->device;
-
        try
        {
-               if(device->device->setLoopCount(self->handle, loops))
+               if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setLoopCount(loops))
                        return 0;
                PyErr_SetString(AUDError, "Couldn't set the loop count!");
        }
@@ -1365,14 +1340,12 @@ PyDoc_STRVAR(M_aud_Handle_location_doc,
 static PyObject *
 Handle_get_location(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       AUD_Vector3 v = device->getSourceLocation(self->handle);
+                       AUD_Vector3 v = handle->getSourceLocation();
                        return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
                }
                else
@@ -1396,15 +1369,13 @@ Handle_set_location(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "(fff):location", &x, &y, &z))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
                        AUD_Vector3 location(x, y, z);
-                       if(device->setSourceLocation(self->handle, location))
+                       if(handle->setSourceLocation(location))
                                return 0;
                        PyErr_SetString(AUDError, "Location couldn't be set!");
                }
@@ -1425,14 +1396,12 @@ PyDoc_STRVAR(M_aud_Handle_velocity_doc,
 static PyObject *
 Handle_get_velocity(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       AUD_Vector3 v = device->getSourceVelocity(self->handle);
+                       AUD_Vector3 v = handle->getSourceVelocity();
                        return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
                }
                else
@@ -1456,15 +1425,13 @@ Handle_set_velocity(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
                        AUD_Vector3 velocity(x, y, z);
-                       if(device->setSourceVelocity(self->handle, velocity))
+                       if(handle->setSourceVelocity(velocity))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the velocity!");
                }
@@ -1485,14 +1452,12 @@ PyDoc_STRVAR(M_aud_Handle_orientation_doc,
 static PyObject *
 Handle_get_orientation(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       AUD_Quaternion o = device->getSourceOrientation(self->handle);
+                       AUD_Quaternion o = handle->getSourceOrientation();
                        return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
                }
                else
@@ -1516,15 +1481,13 @@ Handle_set_orientation(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
                        AUD_Quaternion orientation(w, x, y, z);
-                       if(device->setSourceOrientation(self->handle, orientation))
+                       if(handle->setSourceOrientation(orientation))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the orientation!");
                }
@@ -1545,14 +1508,12 @@ PyDoc_STRVAR(M_aud_Handle_relative_doc,
 static PyObject *
 Handle_get_relative(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return PyBool_FromLong((long)device->isRelative(self->handle));
+                       return PyBool_FromLong((long)handle->isRelative());
                }
                else
                {
@@ -1577,14 +1538,13 @@ Handle_set_relative(Handle *self, PyObject* args, void* nothing)
        }
 
        bool relative = (args == Py_True);
-       Device* dev = (Device*)self->device;
 
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setRelative(self->handle, relative))
+                       if(handle->setRelative(relative))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the relativeness!");
                }
@@ -1606,14 +1566,12 @@ PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc,
 static PyObject *
 Handle_get_volume_minimum(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getVolumeMinimum(self->handle));
+                       return Py_BuildValue("f", handle->getVolumeMinimum());
                }
                else
                {
@@ -1636,14 +1594,12 @@ Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:volume_minimum", &volume))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setVolumeMinimum(self->handle, volume))
+                       if(handle->setVolumeMinimum(volume))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the minimum volume!");
                }
@@ -1665,14 +1621,12 @@ PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc,
 static PyObject *
 Handle_get_volume_maximum(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getVolumeMaximum(self->handle));
+                       return Py_BuildValue("f", handle->getVolumeMaximum());
                }
                else
                {
@@ -1695,14 +1649,12 @@ Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:volume_maximum", &volume))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setVolumeMaximum(self->handle, volume))
+                       if(handle->setVolumeMaximum(volume))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the maximum volume!");
                }
@@ -1725,14 +1677,12 @@ PyDoc_STRVAR(M_aud_Handle_distance_reference_doc,
 static PyObject *
 Handle_get_distance_reference(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getDistanceReference(self->handle));
+                       return Py_BuildValue("f", handle->getDistanceReference());
                }
                else
                {
@@ -1755,14 +1705,12 @@ Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:distance_reference", &distance))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setDistanceReference(self->handle, distance))
+                       if(handle->setDistanceReference(distance))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the reference distance!");
                }
@@ -1785,14 +1733,12 @@ PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc,
 static PyObject *
 Handle_get_distance_maximum(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getDistanceMaximum(self->handle));
+                       return Py_BuildValue("f", handle->getDistanceMaximum());
                }
                else
                {
@@ -1815,14 +1761,12 @@ Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:distance_maximum", &distance))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setDistanceMaximum(self->handle, distance))
+                       if(handle->setDistanceMaximum(distance))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the maximum distance!");
                }
@@ -1845,14 +1789,12 @@ PyDoc_STRVAR(M_aud_Handle_attenuation_doc,
 static PyObject *
 Handle_get_attenuation(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getAttenuation(self->handle));
+                       return Py_BuildValue("f", handle->getAttenuation());
                }
                else
                {
@@ -1875,14 +1817,12 @@ Handle_set_attenuation(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:attenuation", &factor))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setAttenuation(self->handle, factor))
+                       if(handle->setAttenuation(factor))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the attenuation!");
                }
@@ -1910,14 +1850,12 @@ PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc,
 static PyObject *
 Handle_get_cone_angle_inner(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getConeAngleInner(self->handle));
+                       return Py_BuildValue("f", handle->getConeAngleInner());
                }
                else
                {
@@ -1940,14 +1878,12 @@ Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:cone_angle_inner", &angle))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setConeAngleInner(self->handle, angle))
+                       if(handle->setConeAngleInner(angle))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the cone inner angle!");
                }
@@ -1969,14 +1905,12 @@ PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc,
 static PyObject *
 Handle_get_cone_angle_outer(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getConeAngleOuter(self->handle));
+                       return Py_BuildValue("f", handle->getConeAngleOuter());
                }
                else
                {
@@ -1999,14 +1933,12 @@ Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:cone_angle_outer", &angle))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setConeAngleOuter(self->handle, angle))
+                       if(handle->setConeAngleOuter(angle))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the cone outer angle!");
                }
@@ -2028,14 +1960,12 @@ PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc,
 static PyObject *
 Handle_get_cone_volume_outer(Handle *self, void* nothing)
 {
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       return Py_BuildValue("f", device->getConeVolumeOuter(self->handle));
+                       return Py_BuildValue("f", handle->getConeVolumeOuter());
                }
                else
                {
@@ -2058,14 +1988,12 @@ Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing)
        if(!PyArg_Parse(args, "f:cone_volume_outer", &volume))
                return -1;
 
-       Device* dev = (Device*)self->device;
-
        try
        {
-               AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
-               if(device)
+               AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get());
+               if(handle)
                {
-                       if(device->setConeVolumeOuter(self->handle, volume))
+                       if(handle->setConeVolumeOuter(volume))
                                return 0;
                        PyErr_SetString(AUDError, "Couldn't set the cone outer volume!");
                }
@@ -2172,7 +2100,7 @@ static void
 Device_dealloc(Device* self)
 {
        if(self->device)
-               delete self->device;
+               delete reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device);
        Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
@@ -2183,13 +2111,13 @@ Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
        static const char *kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", NULL};
        int device;
-       int rate = AUD_RATE_44100;
+       double rate = AUD_RATE_44100;
        int channels = AUD_CHANNELS_STEREO;
        int format = AUD_FORMAT_FLOAT32;
        int buffersize = AUD_DEFAULT_BUFFER_SIZE;
        const char* name = "Audaspace";
 
-       if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|iiiis:Device", const_cast<char**>(kwlist),
+       if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|diiis:Device", const_cast<char**>(kwlist),
                                                                        &device, &rate, &channels, &format, &buffersize, &name))
                return NULL;
 
@@ -2215,21 +2143,21 @@ Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
                        {
                        case AUD_DEVICE_NULL:
                                (void)specs; /* quiet warning when others disabled */
-                               self->device = new AUD_NULLDevice();
+                               self->device = new AUD_Reference<AUD_IDevice>(new AUD_NULLDevice());
                                break;
                        case AUD_DEVICE_OPENAL:
 #ifdef WITH_OPENAL
-                               self->device = new AUD_OpenALDevice(specs, buffersize);
+                               self->device = new AUD_Reference<AUD_IDevice>(new AUD_OpenALDevice(specs, buffersize));
 #endif
                                break;
                        case AUD_DEVICE_SDL:
 #ifdef WITH_SDL
-                               self->device = new AUD_SDLDevice(specs, buffersize);
+                               self->device = new AUD_Reference<AUD_IDevice>(new AUD_SDLDevice(specs, buffersize));
 #endif
                                break;
                        case AUD_DEVICE_JACK:
 #ifdef WITH_JACK
-                               self->device = new AUD_JackDevice(name, specs, buffersize);
+                               self->device = new AUD_Reference<AUD_IDevice>(new AUD_JackDevice(name, specs, buffersize));
 #endif
                                break;
                        case AUD_DEVICE_READ:
@@ -2302,12 +2230,9 @@ Device_play(Device *self, PyObject *args, PyObject *kwds)
        handle = (Handle*)HandleType.tp_alloc(&HandleType, 0);
        if(handle !=