3D Audio GSoC:

Adapting all readers to maximally support dynamic resampling/rechanneling, introducing a DynamicIIRFilter for example.
This commit is contained in:
Joerg Mueller 2011-06-21 20:35:09 +00:00
parent 6d5b224184
commit 8e6b5598e0
21 changed files with 367 additions and 111 deletions

@ -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

@ -33,20 +33,20 @@
#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),
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)
{
}

@ -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<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();
@ -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

@ -43,17 +43,16 @@
AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory,
float frequency) :
AUD_EffectFactory(factory),
AUD_DynamicIIRFilterFactory(factory),
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;
@ -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;
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_Reference<AUD_IReader> 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);
}

@ -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<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

@ -43,10 +43,6 @@ AUD_DoubleReader::AUD_DoubleReader(AUD_Reference<AUD_IReader> 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
{

@ -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);
}

@ -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

@ -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);
}

@ -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

@ -40,28 +40,24 @@
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_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);
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);
}

@ -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<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

@ -32,8 +32,8 @@
#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++)
@ -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;
}

@ -63,10 +63,13 @@ public:
* \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();
void setCoefficients(const std::vector<float>& b,
const std::vector<float>& a);
};
#endif //AUD_IIRFILTERREADER

@ -37,27 +37,43 @@
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;
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<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, 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;

@ -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&);

@ -40,28 +40,24 @@
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_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);
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);
}

@ -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<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

@ -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_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);

@ -33,14 +33,13 @@
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
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<AUD_IReader> 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);
}

@ -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<AUD_IReader> reader, AUD_DeviceSpecs specs);
virtual AUD_Specs getSpecs() const;
virtual void read(int& length, bool& eos, sample_t* buffer);
};