From 8e6b5598e075932cab09048bff7ef1e54d657bb8 Mon Sep 17 00:00:00 2001 From: Joerg Mueller Date: Tue, 21 Jun 2011 20:35:09 +0000 Subject: [PATCH] 3D Audio GSoC: Adapting all readers to maximally support dynamic resampling/rechanneling, introducing a DynamicIIRFilter for example. --- intern/audaspace/CMakeLists.txt | 4 + .../audaspace/FX/AUD_BaseIIRFilterReader.cpp | 80 +++++++++++++++++-- intern/audaspace/FX/AUD_BaseIIRFilterReader.h | 15 ++-- .../audaspace/FX/AUD_ButterworthFactory.cpp | 14 ++-- intern/audaspace/FX/AUD_ButterworthFactory.h | 8 +- intern/audaspace/FX/AUD_DoubleReader.cpp | 21 +---- .../FX/AUD_DynamicIIRFilterFactory.cpp | 42 ++++++++++ .../FX/AUD_DynamicIIRFilterFactory.h | 49 ++++++++++++ .../FX/AUD_DynamicIIRFilterReader.cpp | 45 +++++++++++ .../audaspace/FX/AUD_DynamicIIRFilterReader.h | 52 ++++++++++++ intern/audaspace/FX/AUD_HighpassFactory.cpp | 14 ++-- intern/audaspace/FX/AUD_HighpassFactory.h | 6 +- intern/audaspace/FX/AUD_IIRFilterReader.cpp | 12 ++- intern/audaspace/FX/AUD_IIRFilterReader.h | 7 +- intern/audaspace/FX/AUD_LimiterReader.cpp | 54 +++++++++---- intern/audaspace/FX/AUD_LimiterReader.h | 4 +- intern/audaspace/FX/AUD_LowpassFactory.cpp | 14 ++-- intern/audaspace/FX/AUD_LowpassFactory.h | 6 +- intern/audaspace/FX/AUD_SuperposeReader.cpp | 9 +-- .../audaspace/intern/AUD_ConverterReader.cpp | 19 ++--- intern/audaspace/intern/AUD_ConverterReader.h | 3 +- 21 files changed, 367 insertions(+), 111 deletions(-) create mode 100644 intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp create mode 100644 intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h create mode 100644 intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp create mode 100644 intern/audaspace/FX/AUD_DynamicIIRFilterReader.h diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt index a8f30bcf35c..4b2a3c42ba4 100644 --- a/intern/audaspace/CMakeLists.txt +++ b/intern/audaspace/CMakeLists.txt @@ -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 @@ -133,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 diff --git a/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp b/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp index 79039ca605b..29ff6d90080 100644 --- a/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp @@ -33,20 +33,20 @@ #include -#define CC m_channels + m_channel +#define CC m_specs.channels + m_channel AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_Reference 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,11 +55,73 @@ AUD_BaseIIRFilterReader::~AUD_BaseIIRFilterReader() 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) { + 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); - 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++) { @@ -71,3 +133,7 @@ void AUD_BaseIIRFilterReader::read(int& length, bool& eos, sample_t* buffer) } } } + +void AUD_BaseIIRFilterReader::sampleRateChanged(AUD_SampleRate rate) +{ +} diff --git a/intern/audaspace/FX/AUD_BaseIIRFilterReader.h b/intern/audaspace/FX/AUD_BaseIIRFilterReader.h index a300ff9d241..644bcffbfaf 100644 --- a/intern/audaspace/FX/AUD_BaseIIRFilterReader.h +++ b/intern/audaspace/FX/AUD_BaseIIRFilterReader.h @@ -42,19 +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; + int m_ylen; /** * The last in samples array. @@ -94,15 +94,17 @@ protected: */ AUD_BaseIIRFilterReader(AUD_Reference 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(); @@ -110,6 +112,7 @@ public: virtual void read(int& length, bool& eos, sample_t* buffer); virtual sample_t filter()=0; + virtual void sampleRateChanged(AUD_SampleRate rate); }; #endif //AUD_BASEIIRFILTERREADER diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.cpp b/intern/audaspace/FX/AUD_ButterworthFactory.cpp index 2d6e14a5ef1..4b45512ffa6 100644 --- a/intern/audaspace/FX/AUD_ButterworthFactory.cpp +++ b/intern/audaspace/FX/AUD_ButterworthFactory.cpp @@ -43,17 +43,16 @@ AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_Reference factory, float frequency) : - AUD_EffectFactory(factory), + AUD_DynamicIIRFilterFactory(factory), m_frequency(frequency) { } -AUD_Reference AUD_ButterworthFactory::createReader() +void AUD_ButterworthFactory::recalculateCoefficients(AUD_SampleRate rate, + std::vector &b, + std::vector &a) { - AUD_Reference 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_Reference AUD_ButterworthFactory::createReader() float y2 = o2 - 2 * BWPB42 * omega + 4; float o228 = 2 * o2 - 8; float norm = x1 * x2; - std::vector 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_Reference AUD_ButterworthFactory::createReader() b.push_back(6 * o4 / norm); b.push_back(b[1]); b.push_back(b[0]); - - return new AUD_IIRFilterReader(reader, b, a); } diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.h b/intern/audaspace/FX/AUD_ButterworthFactory.h index be98fd87380..16d0b3dbc23 100644 --- a/intern/audaspace/FX/AUD_ButterworthFactory.h +++ b/intern/audaspace/FX/AUD_ButterworthFactory.h @@ -32,12 +32,12 @@ #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: /** @@ -57,7 +57,9 @@ public: */ AUD_ButterworthFactory(AUD_Reference factory, float frequency); - virtual AUD_Reference createReader(); + virtual void recalculateCoefficients(AUD_SampleRate rate, + std::vector& b, + std::vector& a); }; #endif //AUD_BUTTERWORTHFACTORY diff --git a/intern/audaspace/FX/AUD_DoubleReader.cpp b/intern/audaspace/FX/AUD_DoubleReader.cpp index 2c39d193f67..fd2419a86e8 100644 --- a/intern/audaspace/FX/AUD_DoubleReader.cpp +++ b/intern/audaspace/FX/AUD_DoubleReader.cpp @@ -43,10 +43,6 @@ AUD_DoubleReader::AUD_DoubleReader(AUD_Reference reader1, 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() @@ -86,7 +82,7 @@ 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, bool& eos, sample_t* buffer) @@ -95,20 +91,7 @@ void AUD_DoubleReader::read(int& length, bool& eos, sample_t* buffer) 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 { diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp new file mode 100644 index 00000000000..3018a2df571 --- /dev/null +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp @@ -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 factory) : + AUD_EffectFactory(factory) +{ +} + +AUD_Reference 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 index 00000000000..19c1a0f0a54 --- /dev/null +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h @@ -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 + +class AUD_DynamicIIRFilterFactory : public AUD_EffectFactory +{ +public: + AUD_DynamicIIRFilterFactory(AUD_Reference factory); + + virtual AUD_Reference createReader(); + + virtual void recalculateCoefficients(AUD_SampleRate rate, + std::vector& b, + std::vector& 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 index 00000000000..ed9b2d3871d --- /dev/null +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp @@ -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 reader, + AUD_Reference factory) : + AUD_IIRFilterReader(reader, std::vector(), std::vector()) +{ + sampleRateChanged(reader->getSpecs().rate); +} + +void AUD_DynamicIIRFilterReader::sampleRateChanged(AUD_SampleRate rate) +{ + std::vector 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 index 00000000000..92f491f04d4 --- /dev/null +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h @@ -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 m_factory; + +public: + AUD_DynamicIIRFilterReader(AUD_Reference reader, + AUD_Reference factory); + + virtual void sampleRateChanged(AUD_SampleRate rate); +}; + +#endif // AUD_DYNAMICIIRFILTERREADER diff --git a/intern/audaspace/FX/AUD_HighpassFactory.cpp b/intern/audaspace/FX/AUD_HighpassFactory.cpp index 2104158cdf5..399ec5ca406 100644 --- a/intern/audaspace/FX/AUD_HighpassFactory.cpp +++ b/intern/audaspace/FX/AUD_HighpassFactory.cpp @@ -40,28 +40,24 @@ AUD_HighpassFactory::AUD_HighpassFactory(AUD_Reference factory, float frequency, float Q) : - AUD_EffectFactory(factory), + AUD_DynamicIIRFilterFactory(factory), m_frequency(frequency), m_Q(Q) { } -AUD_Reference AUD_HighpassFactory::createReader() +void AUD_HighpassFactory::recalculateCoefficients(AUD_SampleRate rate, + std::vector &b, + std::vector &a) { - AUD_Reference 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 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); } diff --git a/intern/audaspace/FX/AUD_HighpassFactory.h b/intern/audaspace/FX/AUD_HighpassFactory.h index de646e7dd64..51d5f55cb36 100644 --- a/intern/audaspace/FX/AUD_HighpassFactory.h +++ b/intern/audaspace/FX/AUD_HighpassFactory.h @@ -32,12 +32,12 @@ #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: /** @@ -63,7 +63,7 @@ public: */ AUD_HighpassFactory(AUD_Reference factory, float frequency, float Q = 1.0f); - virtual AUD_Reference createReader(); + virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector &b, std::vector &a); }; #endif //AUD_HIGHPASSFACTORY diff --git a/intern/audaspace/FX/AUD_IIRFilterReader.cpp b/intern/audaspace/FX/AUD_IIRFilterReader.cpp index 80252e68ce8..1bfb9b97b62 100644 --- a/intern/audaspace/FX/AUD_IIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_IIRFilterReader.cpp @@ -32,8 +32,8 @@ #include "AUD_IIRFilterReader.h" AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_Reference reader, - std::vector b, - std::vector a) : + const std::vector& b, + const std::vector& 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& b, + const std::vector& a) +{ + setLengths(m_b.size(), m_a.size()); + m_a = a; + m_b = b; +} diff --git a/intern/audaspace/FX/AUD_IIRFilterReader.h b/intern/audaspace/FX/AUD_IIRFilterReader.h index db813d6bab6..41de67d4d27 100644 --- a/intern/audaspace/FX/AUD_IIRFilterReader.h +++ b/intern/audaspace/FX/AUD_IIRFilterReader.h @@ -63,10 +63,13 @@ public: * \param b The input filter coefficients. * \param a The output filter coefficients. */ - AUD_IIRFilterReader(AUD_Reference reader, std::vector b, - std::vector a); + AUD_IIRFilterReader(AUD_Reference reader, const std::vector& b, + const std::vector& a); virtual sample_t filter(); + + void setCoefficients(const std::vector& b, + const std::vector& a); }; #endif //AUD_IIRFILTERREADER diff --git a/intern/audaspace/FX/AUD_LimiterReader.cpp b/intern/audaspace/FX/AUD_LimiterReader.cpp index 52add8635e3..92feac8a6a3 100644 --- a/intern/audaspace/FX/AUD_LimiterReader.cpp +++ b/intern/audaspace/FX/AUD_LimiterReader.cpp @@ -37,27 +37,43 @@ AUD_LimiterReader::AUD_LimiterReader(AUD_Reference 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; - 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; - 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()); + + 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 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, 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(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; } - if(position < m_start) + if(position < m_start * rate) { int len2 = length; - for(int len = m_start - position; + for(int len = m_start * rate - position; len2 == length && !eos; len -= length) { @@ -108,7 +128,7 @@ void AUD_LimiterReader::read(int& length, bool& eos, sample_t* buffer) position += len2; } - if(position < m_start) + if(position < m_start * rate) { length = 0; return; diff --git a/intern/audaspace/FX/AUD_LimiterReader.h b/intern/audaspace/FX/AUD_LimiterReader.h index 5a12b990eee..d9bee6f6463 100644 --- a/intern/audaspace/FX/AUD_LimiterReader.h +++ b/intern/audaspace/FX/AUD_LimiterReader.h @@ -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&); diff --git a/intern/audaspace/FX/AUD_LowpassFactory.cpp b/intern/audaspace/FX/AUD_LowpassFactory.cpp index 9bc8d7cfe21..3ef25c3c16e 100644 --- a/intern/audaspace/FX/AUD_LowpassFactory.cpp +++ b/intern/audaspace/FX/AUD_LowpassFactory.cpp @@ -40,28 +40,24 @@ AUD_LowpassFactory::AUD_LowpassFactory(AUD_Reference factory, float frequency, float Q) : - AUD_EffectFactory(factory), + AUD_DynamicIIRFilterFactory(factory), m_frequency(frequency), m_Q(Q) { } -AUD_Reference AUD_LowpassFactory::createReader() +void AUD_LowpassFactory::recalculateCoefficients(AUD_SampleRate rate, + std::vector &b, + std::vector &a) { - AUD_Reference 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 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); } diff --git a/intern/audaspace/FX/AUD_LowpassFactory.h b/intern/audaspace/FX/AUD_LowpassFactory.h index 43d47dc9065..6558663df4e 100644 --- a/intern/audaspace/FX/AUD_LowpassFactory.h +++ b/intern/audaspace/FX/AUD_LowpassFactory.h @@ -32,12 +32,12 @@ #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: /** @@ -63,7 +63,7 @@ public: */ AUD_LowpassFactory(AUD_Reference factory, float frequency, float Q = 1.0f); - virtual AUD_Reference createReader(); + virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector &b, std::vector &a); }; #endif //AUD_LOWPASSFACTORY diff --git a/intern/audaspace/FX/AUD_SuperposeReader.cpp b/intern/audaspace/FX/AUD_SuperposeReader.cpp index fadd064da76..a0dc12fea96 100644 --- a/intern/audaspace/FX/AUD_SuperposeReader.cpp +++ b/intern/audaspace/FX/AUD_SuperposeReader.cpp @@ -39,11 +39,6 @@ static const char* specs_error = "AUD_SuperposeReader: Both readers have to " AUD_SuperposeReader::AUD_SuperposeReader(AUD_Reference reader1, AUD_Reference 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() @@ -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(); + 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); diff --git a/intern/audaspace/intern/AUD_ConverterReader.cpp b/intern/audaspace/intern/AUD_ConverterReader.cpp index 60d8bda5ef6..b3d669379f8 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.cpp +++ b/intern/audaspace/intern/AUD_ConverterReader.cpp @@ -33,14 +33,13 @@ AUD_ConverterReader::AUD_ConverterReader(AUD_Reference 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 - switch(specs.format) + switch(m_format) { case AUD_FORMAT_U8: m_convert = AUD_convert_float_u8; @@ -66,23 +65,17 @@ AUD_ConverterReader::AUD_ConverterReader(AUD_Reference reader, 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) { - 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(), - length * m_specs.channels); + length * specs.channels); } diff --git a/intern/audaspace/intern/AUD_ConverterReader.h b/intern/audaspace/intern/AUD_ConverterReader.h index 6fcfa195098..4a637becbb5 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.h +++ b/intern/audaspace/intern/AUD_ConverterReader.h @@ -50,7 +50,7 @@ private: /** * The target specification. */ - AUD_DeviceSpecs m_specs; + AUD_SampleFormat m_format; /** * Converter function. @@ -69,7 +69,6 @@ public: */ AUD_ConverterReader(AUD_Reference reader, AUD_DeviceSpecs specs); - virtual AUD_Specs getSpecs() const; virtual void read(int& length, bool& eos, sample_t* buffer); };