3D Audio GSoC:
authorJoerg Mueller <nexyon@gmail.com>
Tue, 21 Jun 2011 20:35:09 +0000 (20:35 +0000)
committerJoerg Mueller <nexyon@gmail.com>
Tue, 21 Jun 2011 20:35:09 +0000 (20:35 +0000)
Adapting all readers to maximally support dynamic resampling/rechanneling, introducing a DynamicIIRFilter for example.

21 files changed:
intern/audaspace/CMakeLists.txt
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_DoubleReader.cpp
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_HighpassFactory.cpp
intern/audaspace/FX/AUD_HighpassFactory.h
intern/audaspace/FX/AUD_IIRFilterReader.cpp
intern/audaspace/FX/AUD_IIRFilterReader.h
intern/audaspace/FX/AUD_LimiterReader.cpp
intern/audaspace/FX/AUD_LimiterReader.h
intern/audaspace/FX/AUD_LowpassFactory.cpp
intern/audaspace/FX/AUD_LowpassFactory.h
intern/audaspace/FX/AUD_SuperposeReader.cpp
intern/audaspace/intern/AUD_ConverterReader.cpp
intern/audaspace/intern/AUD_ConverterReader.h

index a8f30bcf35cdb8dfba62753c2c48cc3c93e54364..4b2a3c42ba4cdeb33cd87efcb7a8605969ed0bc9 100644 (file)
@@ -41,6 +41,8 @@ set(SRC
        FX/AUD_DelayReader.cpp
        FX/AUD_DoubleFactory.cpp
        FX/AUD_DoubleReader.cpp
        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
        FX/AUD_EffectFactory.cpp
        FX/AUD_EffectReader.cpp
        FX/AUD_EnvelopeFactory.cpp
@@ -133,6 +135,8 @@ set(SRC
        FX/AUD_DelayReader.h
        FX/AUD_DoubleFactory.h
        FX/AUD_DoubleReader.h
        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
        FX/AUD_EffectFactory.h
        FX/AUD_EffectReader.h
        FX/AUD_EnvelopeFactory.h
index 79039ca605b868808b823b66cd0b2f2f5b9318ed..29ff6d90080b17df533cec5b3432ccecf03037bd 100644 (file)
 
 #include <cstring>
 
 
 #include <cstring>
 
-#define CC m_channels + m_channel
+#define CC m_specs.channels + m_channel
 
 AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in,
                                                                                                 int out) :
                AUD_EffectReader(reader),
 
 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_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()
 }
 
 AUD_BaseIIRFilterReader::~AUD_BaseIIRFilterReader()
@@ -55,11 +55,73 @@ AUD_BaseIIRFilterReader::~AUD_BaseIIRFilterReader()
        delete[] m_y;
 }
 
        delete[] m_y;
 }
 
+void AUD_BaseIIRFilterReader::setLengths(int in, int out)
+{
+       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)
 {
 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;
+
+               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) * m_xlen * m_specs.channels);
+               memset(m_y, 0, sizeof(sample_t) * m_ylen * m_specs.channels);
+       }
+
+       if(specs.rate != m_specs.rate)
+       {
+               m_specs = specs;
+               sampleRateChanged(m_specs.rate);
+       }
+
        m_reader->read(length, eos, buffer);
 
        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++)
                {
        {
                for(int i = 0; i < length; i++)
                {
@@ -71,3 +133,7 @@ void AUD_BaseIIRFilterReader::read(int& length, bool& eos, sample_t* buffer)
                }
        }
 }
                }
        }
 }
+
+void AUD_BaseIIRFilterReader::sampleRateChanged(AUD_SampleRate rate)
+{
+}
index a300ff9d24137a5a1c21d49dc71f823cbcf2551a..644bcffbfafff80b4463cf5c06c0b99d312f60bd 100644 (file)
@@ -42,19 +42,19 @@ class AUD_BaseIIRFilterReader : public AUD_EffectReader
 {
 private:
        /**
 {
 private:
        /**
-        * Channel count.
+        * Specs.
         */
         */
-       const int m_channels;
+       AUD_Specs m_specs;
 
        /**
         * Length of input samples needed.
         */
 
        /**
         * Length of input samples needed.
         */
-       const int m_xlen;
+       int m_xlen;
 
        /**
         * Length of output samples needed.
         */
 
        /**
         * Length of output samples needed.
         */
-       const int m_ylen;
+       int m_ylen;
 
        /**
         * The last in samples array.
 
        /**
         * The last in samples array.
@@ -94,15 +94,17 @@ protected:
         */
        AUD_BaseIIRFilterReader(AUD_Reference<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)
        {
 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)
        {
        }
 
        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 ~AUD_BaseIIRFilterReader();
@@ -110,6 +112,7 @@ public:
        virtual void read(int& length, bool& eos, sample_t* buffer);
 
        virtual sample_t filter()=0;
        virtual void read(int& length, bool& eos, sample_t* buffer);
 
        virtual sample_t filter()=0;
+       virtual void sampleRateChanged(AUD_SampleRate rate);
 };
 
 #endif //AUD_BASEIIRFILTERREADER
 };
 
 #endif //AUD_BASEIIRFILTERREADER
index 2d6e14a5ef1f51f989ffeb68406f1432c5170ccc..4b45512ffa64c2b3dbb640796703f29a183efce1 100644 (file)
 
 AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory,
                                                                                           float frequency) :
 
 AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory,
                                                                                           float frequency) :
-               AUD_EffectFactory(factory),
+               AUD_DynamicIIRFilterFactory(factory),
                m_frequency(frequency)
 {
 }
 
                m_frequency(frequency)
 {
 }
 
-AUD_Reference<AUD_IReader> AUD_ButterworthFactory::createReader()
+void AUD_ButterworthFactory::recalculateCoefficients(AUD_SampleRate rate,
+                                                                                                        std::vector<float> &b,
+                                                                                                        std::vector<float> &a)
 {
 {
-       AUD_Reference<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;
        float o2 = omega * omega;
        float o4 = o2 * o2;
        float x1 = o2 + 2 * BWPB41 * omega + 4;
@@ -62,7 +61,6 @@ AUD_Reference<AUD_IReader> AUD_ButterworthFactory::createReader()
        float y2 = o2 - 2 * BWPB42 * omega + 4;
        float o228 = 2 * o2 - 8;
        float norm = x1 * x2;
        float y2 = o2 - 2 * BWPB42 * omega + 4;
        float o228 = 2 * o2 - 8;
        float norm = x1 * x2;
-       std::vector<float> a, b;
        a.push_back(1);
        a.push_back((x1 + x2) * o228 / norm);
        a.push_back((x1 * y2 + x2 * y1 + o228 * o228) / norm);
        a.push_back(1);
        a.push_back((x1 + x2) * o228 / norm);
        a.push_back((x1 * y2 + x2 * y1 + o228 * o228) / norm);
@@ -73,6 +71,4 @@ AUD_Reference<AUD_IReader> AUD_ButterworthFactory::createReader()
        b.push_back(6 * o4 / norm);
        b.push_back(b[1]);
        b.push_back(b[0]);
        b.push_back(6 * o4 / norm);
        b.push_back(b[1]);
        b.push_back(b[0]);
-
-       return new AUD_IIRFilterReader(reader, b, a);
 }
 }
index be98fd873802ab29f356310c66330a8df30c351f..16d0b3dbc23a0b4d0cec3a3d79c3dac24ac3170f 100644 (file)
 #ifndef AUD_BUTTERWORTHFACTORY
 #define AUD_BUTTERWORTHFACTORY
 
 #ifndef AUD_BUTTERWORTHFACTORY
 #define AUD_BUTTERWORTHFACTORY
 
-#include "AUD_EffectFactory.h"
+#include "AUD_DynamicIIRFilterFactory.h"
 
 /**
  * This factory creates a butterworth filter reader.
  */
 
 /**
  * This factory creates a butterworth filter reader.
  */
-class AUD_ButterworthFactory : public AUD_EffectFactory
+class AUD_ButterworthFactory : public AUD_DynamicIIRFilterFactory
 {
 private:
        /**
 {
 private:
        /**
@@ -57,7 +57,9 @@ public:
         */
        AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory, float frequency);
 
         */
        AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory, float frequency);
 
-       virtual AUD_Reference<AUD_IReader> createReader();
+       virtual void recalculateCoefficients(AUD_SampleRate rate,
+                                                                                std::vector<float>& b,
+                                                                                std::vector<float>& a);
 };
 
 #endif //AUD_BUTTERWORTHFACTORY
 };
 
 #endif //AUD_BUTTERWORTHFACTORY
index 2c39d193f67c02dabd767dbbbaa87691d8847aa4..fd2419a86e8d6b0a38e3ec23bba5cb012f3e260d 100644 (file)
@@ -43,10 +43,6 @@ AUD_DoubleReader::AUD_DoubleReader(AUD_Reference<AUD_IReader> reader1,
        AUD_Specs s1, s2;
        s1 = reader1->getSpecs();
        s2 = reader2->getSpecs();
        AUD_Specs s1, s2;
        s1 = reader1->getSpecs();
        s2 = reader2->getSpecs();
-       if(memcmp(&s1, &s2, sizeof(AUD_Specs)) != 0)
-       {
-               AUD_THROW(AUD_ERROR_SPECS, specs_error);
-       }
 }
 
 AUD_DoubleReader::~AUD_DoubleReader()
 }
 
 AUD_DoubleReader::~AUD_DoubleReader()
@@ -86,7 +82,7 @@ int AUD_DoubleReader::getPosition() const
 
 AUD_Specs AUD_DoubleReader::getSpecs() 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, bool& eos, sample_t* buffer)
 }
 
 void AUD_DoubleReader::read(int& length, bool& eos, sample_t* buffer)
@@ -95,20 +91,7 @@ void AUD_DoubleReader::read(int& length, bool& eos, sample_t* buffer)
 
        if(!m_finished1)
        {
 
        if(!m_finished1)
        {
-               int len = length;
-               m_reader1->read(len, m_finished1, buffer);
-
-               if(m_finished1)
-               {
-                       const AUD_Specs specs = m_reader1->getSpecs();
-
-                       len = length - len;
-                       length -= len;
-
-                       m_reader2->read(len, eos, buffer + length * specs.channels);
-
-                       length += len;
-               }
+               m_reader1->read(length, m_finished1, buffer);
        }
        else
        {
        }
        else
        {
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 2104158cdf5fe8245ae09c4c087d681d7137a491..399ec5ca406d8bb3fcfb3bb1dc6f9345d9ff733d 100644 (file)
 
 AUD_HighpassFactory::AUD_HighpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency,
                                                                                 float Q) :
 
 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)
 {
 }
 
                m_frequency(frequency),
                m_Q(Q)
 {
 }
 
-AUD_Reference<AUD_IReader> AUD_HighpassFactory::createReader()
+void AUD_HighpassFactory::recalculateCoefficients(AUD_SampleRate rate,
+                                                                                                 std::vector<float> &b,
+                                                                                                 std::vector<float> &a)
 {
 {
-       AUD_Reference<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);
        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]);
        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 de646e7dd64cb9714b6753642d09f0b339fc3116..51d5f55cb36b775a69d2034e6e426ff1f0018861 100644 (file)
 #ifndef AUD_HIGHPASSFACTORY
 #define AUD_HIGHPASSFACTORY
 
 #ifndef AUD_HIGHPASSFACTORY
 #define AUD_HIGHPASSFACTORY
 
-#include "AUD_EffectFactory.h"
+#include "AUD_DynamicIIRFilterFactory.h"
 
 /**
  * This factory creates a highpass filter reader.
  */
 
 /**
  * This factory creates a highpass filter reader.
  */
-class AUD_HighpassFactory : public AUD_EffectFactory
+class AUD_HighpassFactory : public AUD_DynamicIIRFilterFactory
 {
 private:
        /**
 {
 private:
        /**
@@ -63,7 +63,7 @@ public:
         */
        AUD_HighpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f);
 
         */
        AUD_HighpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f);
 
-       virtual AUD_Reference<AUD_IReader> createReader();
+       virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector<float> &b, std::vector<float> &a);
 };
 
 #endif //AUD_HIGHPASSFACTORY
 };
 
 #endif //AUD_HIGHPASSFACTORY
index 80252e68ce8598530e64d1effa88ec4fa3960cb1..1bfb9b97b62a2b4b2a79886d349523bd811f5d6a 100644 (file)
@@ -32,8 +32,8 @@
 #include "AUD_IIRFilterReader.h"
 
 AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_Reference<AUD_IReader> reader,
 #include "AUD_IIRFilterReader.h"
 
 AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_Reference<AUD_IReader> reader,
-                                                                                std::vector<float> b,
-                                                                                std::vector<float> a) :
+                                                                                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++)
        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;
 }
 
        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 db813d6bab6b890c81f5b441b31c79e03e4cf617..41de67d4d27419de773ba8e73162bd0b81463aab 100644 (file)
@@ -63,10 +63,13 @@ public:
         * \param b The input filter coefficients.
         * \param a The output filter coefficients.
         */
         * \param b The input filter coefficients.
         * \param a The output filter coefficients.
         */
-       AUD_IIRFilterReader(AUD_Reference<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();
 
        virtual sample_t filter();
+
+       void setCoefficients(const std::vector<float>& b,
+                                                const std::vector<float>& a);
 };
 
 #endif //AUD_IIRFILTERREADER
 };
 
 #endif //AUD_IIRFILTERREADER
index 52add8635e3b0bbb17ca2f8866bda295d0c1dd13..92feac8a6a38291a7c4d2b675bc3b203f04f98a5 100644 (file)
 AUD_LimiterReader::AUD_LimiterReader(AUD_Reference<AUD_IReader> reader,
                                                                         float start, float end) :
                AUD_EffectReader(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)
        {
 {
        if(m_start > 0)
        {
+               AUD_Specs specs = m_reader->getSpecs();
+               AUD_Specs specs2;
+
                if(m_reader->isSeekable())
                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;
                else
                {
                        // skip first m_start samples by reading them
                        int length = AUD_DEFAULT_BUFFER_SIZE;
-                       AUD_Buffer buffer(AUD_DEFAULT_BUFFER_SIZE * AUD_SAMPLE_SIZE(m_reader->getSpecs()));
+                       AUD_Buffer buffer(AUD_DEFAULT_BUFFER_SIZE * AUD_SAMPLE_SIZE(specs));
                        bool eos = false;
                        bool eos = false;
-                       for(int len = m_start;
-                               length == AUD_DEFAULT_BUFFER_SIZE && !eos;
-                               len -= AUD_DEFAULT_BUFFER_SIZE)
+                       for(int len = m_start * specs.rate;
+                               length > 0 && !eos;
+                               len -= length)
                        {
                                if(len < AUD_DEFAULT_BUFFER_SIZE)
                                        length = len;
 
                                m_reader->read(length, eos, buffer.getBuffer());
                        {
                                if(len < AUD_DEFAULT_BUFFER_SIZE)
                                        length = len;
 
                                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));
+                               }
                        }
                }
        }
                        }
                }
        }
@@ -65,21 +81,23 @@ AUD_LimiterReader::AUD_LimiterReader(AUD_Reference<AUD_IReader> reader,
 
 void AUD_LimiterReader::seek(int position)
 {
 
 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();
 }
 
 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();
 }
 
 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, bool& eos, sample_t* buffer)
 }
 
 void AUD_LimiterReader::read(int& length, bool& eos, sample_t* buffer)
@@ -88,16 +106,18 @@ void AUD_LimiterReader::read(int& length, bool& eos, sample_t* buffer)
        if(m_end >= 0)
        {
                int position = m_reader->getPosition();
        if(m_end >= 0)
        {
                int position = m_reader->getPosition();
-               if(position + length > m_end)
+               AUD_SampleRate rate = m_reader->getSpecs().rate;
+
+               if(position + length > m_end * rate)
                {
                {
-                       length = m_end - position;
+                       length = m_end * rate - position;
                        eos = true;
                }
 
                        eos = true;
                }
 
-               if(position < m_start)
+               if(position < m_start * rate)
                {
                        int len2 = length;
                {
                        int len2 = length;
-                       for(int len = m_start - position;
+                       for(int len = m_start * rate - position;
                                len2 == length && !eos;
                                len -= length)
                        {
                                len2 == length && !eos;
                                len -= length)
                        {
@@ -108,7 +128,7 @@ void AUD_LimiterReader::read(int& length, bool& eos, sample_t* buffer)
                                position += len2;
                        }
 
                                position += len2;
                        }
 
-                       if(position < m_start)
+                       if(position < m_start * rate)
                        {
                                length = 0;
                                return;
                        {
                                length = 0;
                                return;
index 5a12b990eee99070d2bb48355e3c910f1dd75f01..d9bee6f6463b49df620e667d1fa4d6056ac007d2 100644 (file)
@@ -43,12 +43,12 @@ private:
        /**
         * The start sample: inclusive.
         */
        /**
         * The start sample: inclusive.
         */
-       const int m_start;
+       const float m_start;
 
        /**
         * The end sample: exlusive.
         */
 
        /**
         * The end sample: exlusive.
         */
-       const int m_end;
+       const float m_end;
 
        // hide copy constructor and operator=
        AUD_LimiterReader(const AUD_LimiterReader&);
 
        // hide copy constructor and operator=
        AUD_LimiterReader(const AUD_LimiterReader&);
index 9bc8d7cfe219ef55da5a268ef8fad256b68d02e8..3ef25c3c16ed269070007ddc3978798c7401be5d 100644 (file)
 
 AUD_LowpassFactory::AUD_LowpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency,
                                                                           float Q) :
 
 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)
 {
 }
 
                m_frequency(frequency),
                m_Q(Q)
 {
 }
 
-AUD_Reference<AUD_IReader> AUD_LowpassFactory::createReader()
+void AUD_LowpassFactory::recalculateCoefficients(AUD_SampleRate rate,
+                                                                                                std::vector<float> &b,
+                                                                                                std::vector<float> &a)
 {
 {
-       AUD_Reference<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);
        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]);
        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 43d47dc90650edddb4f60d7ddc11f88407ba67a1..6558663df4e874db8c796e867aeb15ddc1bb89ec 100644 (file)
 #ifndef AUD_LOWPASSFACTORY
 #define AUD_LOWPASSFACTORY
 
 #ifndef AUD_LOWPASSFACTORY
 #define AUD_LOWPASSFACTORY
 
-#include "AUD_EffectFactory.h"
+#include "AUD_DynamicIIRFilterFactory.h"
 
 /**
  * This factory creates a lowpass filter reader.
  */
 
 /**
  * This factory creates a lowpass filter reader.
  */
-class AUD_LowpassFactory : public AUD_EffectFactory
+class AUD_LowpassFactory : public AUD_DynamicIIRFilterFactory
 {
 private:
        /**
 {
 private:
        /**
@@ -63,7 +63,7 @@ public:
         */
        AUD_LowpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f);
 
         */
        AUD_LowpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f);
 
-       virtual AUD_Reference<AUD_IReader> createReader();
+       virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector<float> &b, std::vector<float> &a);
 };
 
 #endif //AUD_LOWPASSFACTORY
 };
 
 #endif //AUD_LOWPASSFACTORY
index fadd064da7601b2af7ac9ae255e6703441ecd037..a0dc12fea96e161b783b0f020199edc5e953a1a4 100644 (file)
@@ -39,11 +39,6 @@ static const char* specs_error = "AUD_SuperposeReader: Both readers have to "
 AUD_SuperposeReader::AUD_SuperposeReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2) :
        m_reader1(reader1), m_reader2(reader2)
 {
 AUD_SuperposeReader::AUD_SuperposeReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2) :
        m_reader1(reader1), m_reader2(reader2)
 {
-       AUD_Specs s1, s2;
-       s1 = reader1->getSpecs();
-       s2 = reader2->getSpecs();
-       if(memcmp(&s1, &s2, sizeof(AUD_Specs)))
-               AUD_THROW(AUD_ERROR_SPECS, specs_error);
 }
 
 AUD_SuperposeReader::~AUD_SuperposeReader()
 }
 
 AUD_SuperposeReader::~AUD_SuperposeReader()
@@ -85,6 +80,10 @@ AUD_Specs AUD_SuperposeReader::getSpecs() const
 void AUD_SuperposeReader::read(int& length, bool& eos, sample_t* buffer)
 {
        AUD_Specs specs = m_reader1->getSpecs();
 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);
 
        m_buffer.assureSize(length * samplesize);
        int samplesize = AUD_SAMPLE_SIZE(specs);
 
        m_buffer.assureSize(length * samplesize);
index 60d8bda5ef6d031ebb424a6a2bfea5b2b0432724..b3d669379f8c53894f446ecb5c61a34984cf9514 100644 (file)
 
 AUD_ConverterReader::AUD_ConverterReader(AUD_Reference<AUD_IReader> reader,
                                                                                 AUD_DeviceSpecs specs) :
 
 AUD_ConverterReader::AUD_ConverterReader(AUD_Reference<AUD_IReader> reader,
                                                                                 AUD_DeviceSpecs specs) :
-               AUD_EffectReader(reader)
+       AUD_EffectReader(reader),
+       m_format(specs.format)
 {
 {
-       m_specs.specs = reader->getSpecs();
-
        int bigendian = 1;
        bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
 
        int bigendian = 1;
        bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
 
-       switch(specs.format)
+       switch(m_format)
        {
        case AUD_FORMAT_U8:
                m_convert = AUD_convert_float_u8;
        {
        case AUD_FORMAT_U8:
                m_convert = AUD_convert_float_u8;
@@ -66,23 +65,17 @@ AUD_ConverterReader::AUD_ConverterReader(AUD_Reference<AUD_IReader> reader,
        default:
                break;
        }
        default:
                break;
        }
-
-       m_specs.format = specs.format;
-}
-
-AUD_Specs AUD_ConverterReader::getSpecs() const
-{
-       return m_specs.specs;
 }
 
 void AUD_ConverterReader::read(int& length, bool& eos, sample_t* buffer)
 {
 }
 
 void AUD_ConverterReader::read(int& length, bool& eos, sample_t* buffer)
 {
-       int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs());
+       AUD_Specs specs = m_reader->getSpecs();
+       int samplesize = AUD_SAMPLE_SIZE(specs);
 
        m_buffer.assureSize(length * samplesize);
 
        m_reader->read(length, eos, m_buffer.getBuffer());
 
        m_convert((data_t*)buffer, (data_t*)m_buffer.getBuffer(),
 
        m_buffer.assureSize(length * samplesize);
 
        m_reader->read(length, eos, m_buffer.getBuffer());
 
        m_convert((data_t*)buffer, (data_t*)m_buffer.getBuffer(),
-                         length * m_specs.channels);
+                         length * specs.channels);
 }
 }
index 6fcfa195098b130fc92a4815529d6579b448927c..4a637becbb59336117e41fc69aa466f8d10946b1 100644 (file)
@@ -50,7 +50,7 @@ private:
        /**
         * The target specification.
         */
        /**
         * The target specification.
         */
-       AUD_DeviceSpecs m_specs;
+       AUD_SampleFormat m_format;
 
        /**
         * Converter function.
 
        /**
         * Converter function.
@@ -69,7 +69,6 @@ public:
         */
        AUD_ConverterReader(AUD_Reference<AUD_IReader> reader, AUD_DeviceSpecs specs);
 
         */
        AUD_ConverterReader(AUD_Reference<AUD_IReader> reader, AUD_DeviceSpecs specs);
 
-       virtual AUD_Specs getSpecs() const;
        virtual void read(int& length, bool& eos, sample_t* buffer);
 };
 
        virtual void read(int& length, bool& eos, sample_t* buffer);
 };