Audaspace:

* Created awesome filter classes :)
* Made all filter effects use the filter classes instead of having the same implementation everywhere.
* Added a Python API for LTI IIR filters.
* Fixed a warning in creator.c that was introduced when adding game autoplay.
This commit is contained in:
Joerg Mueller 2010-08-01 22:33:50 +00:00
parent 5c9cf81cf9
commit 52ef66da4d
32 changed files with 653 additions and 1164 deletions

@ -24,7 +24,27 @@
*/
#include "AUD_AccumulatorFactory.h"
#include "AUD_AccumulatorReader.h"
#include "AUD_CallbackIIRFilterReader.h"
sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless)
{
float in = reader->x(0);
float lastin = reader->x(-1);
float out = reader->y(-1) + in - lastin;
if(in > lastin)
out += in - lastin;
return out;
}
sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
{
float in = reader->x(0);
float lastin = reader->x(-1);
float out = reader->y(-1);
if(in > lastin)
out += in - lastin;
return out;
}
AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_IFactory* factory,
bool additive) :
@ -35,5 +55,6 @@ AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_IFactory* factory,
AUD_IReader* AUD_AccumulatorFactory::createReader() const
{
return new AUD_AccumulatorReader(getReader(), m_additive);
return new AUD_CallbackIIRFilterReader(getReader(), 2, 2,
m_additive ? accumulatorFilterAdditive : accumulatorFilter);
}

@ -1,85 +0,0 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_AccumulatorReader.h"
#include <cstring>
#define CC specs.channels + channel
AUD_AccumulatorReader::AUD_AccumulatorReader(AUD_IReader* reader,
bool additive) :
AUD_EffectReader(reader),
m_additive(additive),
m_sums(AUD_SAMPLE_SIZE(reader->getSpecs())),
m_prevs(AUD_SAMPLE_SIZE(reader->getSpecs()))
{
memset(m_sums.getBuffer(), 0, m_sums.getSize());
memset(m_prevs.getBuffer(), 0, m_prevs.getSize());
}
void AUD_AccumulatorReader::read(int & length, sample_t* & buffer)
{
sample_t* buf;
sample_t* sums;
sample_t* prevs;
sums = m_sums.getBuffer();
prevs = m_prevs.getBuffer();
AUD_Specs specs = m_reader->getSpecs();
m_reader->read(length, buf);
if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(specs))
m_buffer.resize(length * AUD_SAMPLE_SIZE(specs));
buffer = m_buffer.getBuffer();
if(m_additive)
{
for(int channel = 0; channel < specs.channels; channel++)
{
for(int i = 0; i < length; i++)
{
if(buf[i * CC] > prevs[channel])
sums[channel] += buf[i * CC] - prevs[channel];
buffer[i * CC] = sums[channel] + buf[i * CC];
prevs[channel] = buf[i * CC];
}
}
}
else
{
for(int channel = 0; channel < specs.channels; channel++)
{
for(int i = 0; i < length; i++)
{
if(buf[i * CC] > prevs[channel])
sums[channel] += buf[i * CC] - prevs[channel];
buffer[i * CC] = sums[channel];
prevs[channel] = buf[i * CC];
}
}
}
}

@ -1,73 +0,0 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_ACCUMULATORREADER
#define AUD_ACCUMULATORREADER
#include "AUD_EffectReader.h"
#include "AUD_Buffer.h"
/**
* This class represents an accumulator.
*/
class AUD_AccumulatorReader : public AUD_EffectReader
{
private:
/**
* Whether the accumulator is additive.
*/
const bool m_additive;
/**
* The playback buffer.
*/
AUD_Buffer m_buffer;
/**
* The sums of the specific channels.
*/
AUD_Buffer m_sums;
/**
* The previous results of the specific channels.
*/
AUD_Buffer m_prevs;
// hide copy constructor and operator=
AUD_AccumulatorReader(const AUD_AccumulatorReader&);
AUD_AccumulatorReader& operator=(const AUD_AccumulatorReader&);
public:
/**
* Creates a new accumulator reader.
* \param reader The reader to read from.
* \param additive Whether the accumulator is additive.
*/
AUD_AccumulatorReader(AUD_IReader* reader, bool additive);
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_ACCUMULATORREADER

@ -0,0 +1,76 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_BaseIIRFilterReader.h"
#include <cstring>
#define CC m_channels + m_channel
AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_IReader* reader, int in,
int out) :
AUD_EffectReader(reader),
m_channels(reader->getSpecs().channels),
m_xlen(in), m_ylen(out),
m_xpos(0), m_ypos(0), m_channel(0)
{
m_x = new sample_t[in * m_channels];
m_y = new sample_t[out * m_channels];
memset(m_x, 0, sizeof(sample_t) * in * m_channels);
memset(m_y, 0, sizeof(sample_t) * out * m_channels);
}
AUD_BaseIIRFilterReader::~AUD_BaseIIRFilterReader()
{
delete[] m_x;
delete[] m_y;
}
void AUD_BaseIIRFilterReader::read(int & length, sample_t* & buffer)
{
sample_t* buf;
int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs());
m_reader->read(length, buf);
if(m_buffer.getSize() < length * samplesize)
m_buffer.resize(length * samplesize);
buffer = m_buffer.getBuffer();
for(m_channel = 0; m_channel < m_channels; m_channel++)
{
for(int i = 0; i < length; i++)
{
m_x[m_xpos * CC] = buf[i * CC];
m_y[m_ypos * CC] = buffer[i * CC] = filter();
m_xpos = (m_xpos + 1) % m_xlen;
m_ypos = (m_ypos + 1) % m_ylen;
}
}
}

@ -0,0 +1,114 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_BASEIIRFILTERREADER
#define AUD_BASEIIRFILTERREADER
#include "AUD_EffectReader.h"
#include "AUD_Buffer.h"
/**
* This class is a base class for infinite impulse response filters.
*/
class AUD_BaseIIRFilterReader : public AUD_EffectReader
{
private:
/**
* Channel count.
*/
const int m_channels;
/**
* Length of input samples needed.
*/
const int m_xlen;
/**
* Length of output samples needed.
*/
const int m_ylen;
/**
* The playback buffer.
*/
AUD_Buffer m_buffer;
/**
* The last in samples array.
*/
sample_t* m_x;
/**
* The last out samples array.
*/
sample_t* m_y;
/**
* Position of the current input sample in the input array.
*/
int m_xpos;
/**
* Position of the current output sample in the output array.
*/
int m_ypos;
/**
* Current channel.
*/
int m_channel;
// hide copy constructor and operator=
AUD_BaseIIRFilterReader(const AUD_BaseIIRFilterReader&);
AUD_BaseIIRFilterReader& operator=(const AUD_BaseIIRFilterReader&);
protected:
/**
* Creates a new base IIR filter reader.
* \param reader The reader to read from.
* \param in The count of past input samples needed.
* \param out The count of past output samples needed.
*/
AUD_BaseIIRFilterReader(AUD_IReader* reader, int in, int out);
public:
inline sample_t x(int pos)
{
return m_x[(m_xpos + pos + m_xlen) % m_xlen * m_channels + m_channel];
}
inline sample_t y(int pos)
{
return m_y[(m_ypos + pos + m_ylen) % m_ylen * m_channels + m_channel];
}
virtual ~AUD_BaseIIRFilterReader();
virtual void read(int & length, sample_t* & buffer);
virtual sample_t filter()=0;
};
#endif //AUD_BASEIIRFILTERREADER

@ -24,7 +24,16 @@
*/
#include "AUD_ButterworthFactory.h"
#include "AUD_ButterworthReader.h"
#include "AUD_IIRFilterReader.h"
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define BWPB41 0.76536686473
#define BWPB42 1.84775906502
AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_IFactory* factory,
float frequency) :
@ -35,5 +44,29 @@ AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_IFactory* factory,
AUD_IReader* AUD_ButterworthFactory::createReader() const
{
return new AUD_ButterworthReader(getReader(), m_frequency);
AUD_IReader* reader = getReader();
// calculate coefficients
float omega = 2 * tan(m_frequency * M_PI / reader->getSpecs().rate);
float o2 = omega * omega;
float o4 = o2 * o2;
float x1 = o2 + 2 * BWPB41 * omega + 4;
float x2 = o2 + 2 * BWPB42 * omega + 4;
float y1 = o2 - 2 * BWPB41 * omega + 4;
float y2 = o2 - 2 * BWPB42 * omega + 4;
float o228 = 2 * o2 - 8;
float norm = x1 * x2;
std::vector<float> a, b;
a.push_back(1);
a.push_back((x1 + x2) * o228 / norm);
a.push_back((x1 * y2 + x2 * y1 + o228 * o228) / norm);
a.push_back((y1 + y2) * o228 / norm);
a.push_back(y1 * y2 / norm);
b.push_back(o4 / norm);
b.push_back(4 * o4 / norm);
b.push_back(6 * o4 / norm);
b.push_back(b[1]);
b.push_back(b[0]);
return new AUD_IIRFilterReader(reader, b, a);
}

@ -1,109 +0,0 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_ButterworthReader.h"
#include <cstring>
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define BWPB41 0.76536686473
#define BWPB42 1.84775906502
#define CC channels + channel
AUD_ButterworthReader::AUD_ButterworthReader(AUD_IReader* reader,
float frequency) :
AUD_EffectReader(reader),
m_outvalues(AUD_SAMPLE_SIZE(reader->getSpecs()) * 5),
m_invalues(AUD_SAMPLE_SIZE(reader->getSpecs()) * 5),
m_position(0)
{
AUD_Specs specs = reader->getSpecs();
memset(m_outvalues.getBuffer(), 0, m_outvalues.getSize());
memset(m_invalues.getBuffer(), 0, m_invalues.getSize());
// calculate coefficients
float omega = 2 * tan(frequency * M_PI / specs.rate);
float o2 = omega * omega;
float o4 = o2 * o2;
float x1 = o2 + 2 * BWPB41 * omega + 4;
float x2 = o2 + 2 * BWPB42 * omega + 4;
float y1 = o2 - 2 * BWPB41 * omega + 4;
float y2 = o2 - 2 * BWPB42 * omega + 4;
float o228 = 2 * o2 - 8;
float norm = x1 * x2;
m_coeff[0][0] = 0;
m_coeff[0][1] = (x1 + x2) * o228 / norm;
m_coeff[0][2] = (x1 * y2 + x2 * y1 + o228 * o228) / norm;
m_coeff[0][3] = (y1 + y2) * o228 / norm;
m_coeff[0][4] = y1 * y2 / norm;
m_coeff[1][4] = m_coeff[1][0] = o4 / norm;
m_coeff[1][3] = m_coeff[1][1] = 4 * o4 / norm;
m_coeff[1][2] = 6 * o4 / norm;
}
void AUD_ButterworthReader::read(int & length, sample_t* & buffer)
{
sample_t* buf;
sample_t* outvalues;
sample_t* invalues;
outvalues = m_outvalues.getBuffer();
invalues = m_invalues.getBuffer();
AUD_Specs specs = m_reader->getSpecs();
m_reader->read(length, buf);
if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(specs))
m_buffer.resize(length * AUD_SAMPLE_SIZE(specs));
buffer = m_buffer.getBuffer();
int channels = specs.channels;
for(int channel = 0; channel < channels; channel++)
{
for(int i = 0; i < length; i++)
{
invalues[m_position * CC] = buf[i * CC];
outvalues[m_position * CC] = 0;
for(int j = 0; j < 4; j++)
{
outvalues[m_position * CC] += m_coeff[1][j] *
invalues[((m_position + j) % 5) * CC] -
m_coeff[0][j] *
outvalues[((m_position + j) % 5) * CC];
}
buffer[i * CC] = outvalues[m_position * CC];
m_position = (m_position + 4) % 5;
}
}
}

@ -1,81 +0,0 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_BUTTERWORTHREADER
#define AUD_BUTTERWORTHREADER
#include "AUD_EffectReader.h"
#include "AUD_Buffer.h"
/**
* This class represents a butterworth filter.
*/
class AUD_ButterworthReader : public AUD_EffectReader
{
private:
/**
* The playback buffer.
*/
AUD_Buffer m_buffer;
/**
* The last out values buffer.
*/
AUD_Buffer m_outvalues;
/**
* The last in values buffer.
*/
AUD_Buffer m_invalues;
/**
* The position for buffer cycling.
*/
int m_position;
/**
* Filter coefficients.
*/
float m_coeff[2][5];
// hide copy constructor and operator=
AUD_ButterworthReader(const AUD_ButterworthReader&);
AUD_ButterworthReader& operator=(const AUD_ButterworthReader&);
public:
/**
* Creates a new butterworth reader.
* \param reader The reader to read from.
* \param attack The attack value in seconds.
* \param release The release value in seconds.
* \param threshold The threshold value.
* \param arthreshold The attack/release threshold value.
*/
AUD_ButterworthReader(AUD_IReader* reader, float frequency);
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_BUTTERWORTHREADER

@ -23,27 +23,25 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_VolumeReader.h"
#include "AUD_CallbackIIRFilterReader.h"
#include <cstring>
AUD_VolumeReader::AUD_VolumeReader(AUD_IReader* reader, float volume) :
AUD_EffectReader(reader),
m_volume(volume)
AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(AUD_IReader* reader,
int in, int out,
doFilterIIR doFilter,
endFilterIIR endFilter,
void* data) :
AUD_BaseIIRFilterReader(reader, in, out),
m_filter(doFilter), m_endFilter(endFilter), m_data(data)
{
}
void AUD_VolumeReader::read(int & length, sample_t* & buffer)
AUD_CallbackIIRFilterReader::~AUD_CallbackIIRFilterReader()
{
sample_t* buf;
AUD_Specs specs = m_reader->getSpecs();
m_reader->read(length, buf);
if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(specs))
m_buffer.resize(length * AUD_SAMPLE_SIZE(specs));
buffer = m_buffer.getBuffer();
for(int i = 0; i < length * specs.channels; i++)
buffer[i] = buf[i] * m_volume;
if(m_endFilter)
m_endFilter(m_data);
}
sample_t AUD_CallbackIIRFilterReader::filter()
{
return m_filter(this, m_data);
}

@ -0,0 +1,83 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_CALLBACKIIRFILTERREADER
#define AUD_CALLBACKIIRFILTERREADER
#include "AUD_BaseIIRFilterReader.h"
#include "AUD_Buffer.h"
class AUD_CallbackIIRFilterReader;
typedef sample_t (*doFilterIIR)(AUD_CallbackIIRFilterReader*, void*);
typedef void (*endFilterIIR)(void*);
/**
* This class provides an interface for infinite impulse response filters via a
* callback filter function.
*/
class AUD_CallbackIIRFilterReader : public AUD_BaseIIRFilterReader
{
private:
/**
* Filter function.
*/
const doFilterIIR m_filter;
/**
* End filter function.
*/
const endFilterIIR m_endFilter;
/**
* Data pointer.
*/
void* m_data;
// hide copy constructor and operator=
AUD_CallbackIIRFilterReader(const AUD_CallbackIIRFilterReader&);
AUD_CallbackIIRFilterReader& operator=(const AUD_CallbackIIRFilterReader&);
public:
/**
* Creates a new callback IIR filter reader.
* \param reader The reader to read from.
* \param in The count of past input samples needed.
* \param out The count of past output samples needed.
* \param doFilter The filter callback.
* \param endFilter The finishing callback.
* \param data Data pointer for the callbacks.
*/
AUD_CallbackIIRFilterReader(AUD_IReader* reader, int in, int out,
doFilterIIR doFilter,
endFilterIIR endFilter = 0,
void* data = 0);
virtual ~AUD_CallbackIIRFilterReader();
virtual sample_t filter();
};
#endif //AUD_CALLBACKIIRFILTERREADER

@ -24,7 +24,31 @@
*/
#include "AUD_EnvelopeFactory.h"
#include "AUD_EnvelopeReader.h"
#include "AUD_CallbackIIRFilterReader.h"
#include <cmath>
struct EnvelopeParameters
{
float attack;
float release;
float threshold;
float arthreshold;
};
sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param)
{
float in = fabs(reader->x(0));
float out = reader->y(-1);
if(in < param->threshold)
in = 0.0f;
return (in > out ? param->attack : param->release) * (out - in) + in;
}
void endEnvelopeFilter(EnvelopeParameters* param)
{
delete param;
}
AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack,
float release, float threshold,
@ -39,6 +63,16 @@ AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack,
AUD_IReader* AUD_EnvelopeFactory::createReader() const
{
return new AUD_EnvelopeReader(getReader(), m_attack, m_release, m_threshold,
m_arthreshold);
AUD_IReader* reader = getReader();
EnvelopeParameters* param = new EnvelopeParameters();
param->arthreshold = m_arthreshold;
param->attack = pow(m_arthreshold, 1.0f/(reader->getSpecs().rate * m_attack));
param->release = pow(m_arthreshold, 1.0f/(reader->getSpecs().rate * m_release));
param->threshold = m_threshold;
return new AUD_CallbackIIRFilterReader(reader, 1, 2,
(doFilterIIR) envelopeFilter,
(endFilterIIR) endEnvelopeFilter,
param);
}

@ -1,72 +0,0 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_EnvelopeReader.h"
#include <cstring>
#include <cmath>
AUD_EnvelopeReader::AUD_EnvelopeReader(AUD_IReader* reader, float attack,
float release, float threshold,
float arthreshold) :
AUD_EffectReader(reader),
m_bAttack(pow(arthreshold, 1.0f/(reader->getSpecs().rate * attack))),
m_bRelease(pow(arthreshold, 1.0f/(reader->getSpecs().rate * release))),
m_threshold(threshold),
m_envelopes(AUD_SAMPLE_SIZE(reader->getSpecs()))
{
memset(m_envelopes.getBuffer(), 0, m_envelopes.getSize());
}
void AUD_EnvelopeReader::read(int & length, sample_t* & buffer)
{
sample_t* buf;
sample_t* envelopes;
envelopes = m_envelopes.getBuffer();
AUD_Specs specs = m_reader->getSpecs();
m_reader->read(length, buf);
if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(specs))
m_buffer.resize(length * AUD_SAMPLE_SIZE(specs));
buffer = m_buffer.getBuffer();
sample_t value;
for(int channel = 0; channel < specs.channels; channel++)
{
for(int i = 0; i < length; i++)
{
value = fabs(buf[i * specs.channels + channel]);
if(value < m_threshold)
value = 0.0f;
buffer[i * specs.channels + channel] = envelopes[channel] =
((value > envelopes[channel]) ? m_bAttack : m_bRelease) *
(envelopes[channel] - value) + value;
}
}
}

@ -1,82 +0,0 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_ENVELOPEREADER
#define AUD_ENVELOPEREADER
#include "AUD_EffectReader.h"
#include "AUD_Buffer.h"
/**
* This class represents an envelope follower.
*/
class AUD_EnvelopeReader : public AUD_EffectReader
{
private:
/**
* Attack b value.
*/
const float m_bAttack;
/**
* Release b value.
*/
const float m_bRelease;
/**
* Threshold value.
*/
const float m_threshold;
/**
* The playback buffer.
*/
AUD_Buffer m_buffer;
/**
* The last envelopes buffer.
*/
AUD_Buffer m_envelopes;
// hide copy constructor and operator=
AUD_EnvelopeReader(const AUD_EnvelopeReader&);
AUD_EnvelopeReader& operator=(const AUD_EnvelopeReader&);
public:
/**
* Creates a new envelope reader.
* \param reader The reader to read from.
* \param attack The attack value in seconds.
* \param release The release value in seconds.
* \param threshold The threshold value.
* \param arthreshold The attack/release threshold value.
*/
AUD_EnvelopeReader(AUD_IReader* reader, float attack, float release,
float threshold, float arthreshold);
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_ENVELOPEREADER

@ -24,7 +24,13 @@
*/
#include "AUD_HighpassFactory.h"
#include "AUD_HighpassReader.h"
#include "AUD_IIRFilterReader.h"
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
AUD_HighpassFactory::AUD_HighpassFactory(AUD_IFactory* factory, float frequency,
float Q) :
@ -36,5 +42,20 @@ AUD_HighpassFactory::AUD_HighpassFactory(AUD_IFactory* factory, float frequency,
AUD_IReader* AUD_HighpassFactory::createReader() const
{
return new AUD_HighpassReader(getReader(), m_frequency, m_Q);
AUD_IReader* reader = getReader();
// calculate coefficients
float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate;
float alpha = sin(w0) / (2 * m_Q);
float norm = 1 + alpha;
float c = cos(w0);
std::vector<float> a, b;
a.push_back(1);
a.push_back(-2 * c / norm);
a.push_back((1 - alpha) / norm);
b.push_back((1 + c) / (2 * norm));
b.push_back((-1 - c) / norm);
b.push_back(b[0]);
return new AUD_IIRFilterReader(reader, b, a);
}

@ -1,100 +0,0 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_HighpassReader.h"
#include <cstring>
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define CC channels + channel
AUD_HighpassReader::AUD_HighpassReader(AUD_IReader* reader, float frequency,
float Q) :
AUD_EffectReader(reader),
m_outvalues(AUD_SAMPLE_SIZE(reader->getSpecs()) * AUD_HIGHPASS_ORDER),
m_invalues(AUD_SAMPLE_SIZE(reader->getSpecs()) * AUD_HIGHPASS_ORDER),
m_position(0)
{
memset(m_outvalues.getBuffer(), 0, m_outvalues.getSize());
memset(m_invalues.getBuffer(), 0, m_invalues.getSize());
AUD_Specs specs = reader->getSpecs();
// calculate coefficients
float w0 = 2 * M_PI * frequency / specs.rate;
float alpha = sin(w0) / (2 * Q);
float norm = 1 + alpha;
m_coeff[0][0] = 0;
m_coeff[0][1] = -2 * cos(w0) / norm;
m_coeff[0][2] = (1 - alpha) / norm;
m_coeff[1][2] = m_coeff[1][0] = (1 + cos(w0)) / (2 * norm);
m_coeff[1][1] = (-1 - cos(w0)) / norm;
}
void AUD_HighpassReader::read(int & length, sample_t* & buffer)
{
sample_t* buf;
sample_t* outvalues;
sample_t* invalues;
outvalues = m_outvalues.getBuffer();
invalues = m_invalues.getBuffer();
AUD_Specs specs = m_reader->getSpecs();
m_reader->read(length, buf);
if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(specs))
m_buffer.resize(length * AUD_SAMPLE_SIZE(specs));
buffer = m_buffer.getBuffer();
int channels = specs.channels;
for(int channel = 0; channel < channels; channel++)
{
for(int i = 0; i < length; i++)
{
invalues[m_position * CC] = buf[i * CC];
outvalues[m_position * CC] = 0;
for(int j = 0; j < AUD_HIGHPASS_ORDER; j++)
{
outvalues[m_position * CC] += m_coeff[1][j] *
invalues[((m_position + j) % AUD_HIGHPASS_ORDER) * CC] -
m_coeff[0][j] *
outvalues[((m_position + j) % AUD_HIGHPASS_ORDER) * CC];
}
buffer[i * CC] = outvalues[m_position * CC];
m_position = (m_position + AUD_HIGHPASS_ORDER-1) %
AUD_HIGHPASS_ORDER;
}
}
}

@ -1,81 +0,0 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_HIGHPASSREADER
#define AUD_HIGHPASSREADER
#include "AUD_EffectReader.h"
#include "AUD_Buffer.h"
#define AUD_HIGHPASS_ORDER 3
/**
* This class represents a highpass filter.
*/
class AUD_HighpassReader : public AUD_EffectReader
{
private:
/**
* The playback buffer.
*/
AUD_Buffer m_buffer;
/**
* The last out values buffer.
*/
AUD_Buffer m_outvalues;
/**
* The last in values buffer.
*/
AUD_Buffer m_invalues;
/**
* The position for buffer cycling.
*/
int m_position;
/**
* Filter coefficients.
*/
float m_coeff[2][AUD_HIGHPASS_ORDER];
// hide copy constructor and operator=
AUD_HighpassReader(const AUD_HighpassReader&);
AUD_HighpassReader& operator=(const AUD_HighpassReader&);
public:
/**
* Creates a new highpass reader.
* \param reader The reader to read from.
* \param frequency The cutoff frequency.
* \param Q The Q factor.
*/
AUD_HighpassReader(AUD_IReader* reader, float frequency, float Q);
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_HIGHPASSREADER

@ -23,26 +23,17 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_RectifyReader.h"
#include "AUD_IIRFilterFactory.h"
#include "AUD_IIRFilterReader.h"
#include <cmath>
AUD_RectifyReader::AUD_RectifyReader(AUD_IReader* reader) :
AUD_EffectReader(reader)
AUD_IIRFilterFactory::AUD_IIRFilterFactory(AUD_IFactory* factory,
std::vector<float> b,
std::vector<float> a) :
AUD_EffectFactory(factory), m_a(a), m_b(b)
{
}
void AUD_RectifyReader::read(int & length, sample_t* & buffer)
AUD_IReader* AUD_IIRFilterFactory::createReader() const
{
sample_t* buf;
AUD_Specs specs = m_reader->getSpecs();
m_reader->read(length, buf);
if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(specs))
m_buffer.resize(length * AUD_SAMPLE_SIZE(specs));
buffer = m_buffer.getBuffer();
for(int i = 0; i < length * specs.channels; i++)
buffer[i] = fabs(buf[i]);
return new AUD_IIRFilterReader(getReader(), m_b, m_a);
}

@ -23,41 +23,44 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_VOLUMEREADER
#define AUD_VOLUMEREADER
#ifndef AUD_IIRFILTERFACTORY
#define AUD_IIRFILTERFACTORY
#include "AUD_EffectReader.h"
#include "AUD_Buffer.h"
#include "AUD_EffectFactory.h"
#include <vector>
/**
* This class reads another reader and changes it's volume.
* This factory creates a IIR filter reader.
*/
class AUD_VolumeReader : public AUD_EffectReader
class AUD_IIRFilterFactory : public AUD_EffectFactory
{
private:
/**
* The playback buffer.
* Output filter coefficients.
*/
AUD_Buffer m_buffer;
std::vector<float> m_a;
/**
* The volume level.
* Input filter coefficients.
*/
const float m_volume;
std::vector<float> m_b;
// hide copy constructor and operator=
AUD_VolumeReader(const AUD_VolumeReader&);
AUD_VolumeReader& operator=(const AUD_VolumeReader&);
AUD_IIRFilterFactory(const AUD_IIRFilterFactory&);
AUD_IIRFilterFactory& operator=(const AUD_IIRFilterFactory&);
public:
/**
* Creates a new volume reader.
* \param reader The reader to read from.
* \param volume The size of the buffer.
* Creates a new IIR filter factory.
* \param factory The input factory.
* \param b The input filter coefficients.
* \param a The output filter coefficients.
*/
AUD_VolumeReader(AUD_IReader* reader, float volume);
AUD_IIRFilterFactory(AUD_IFactory* factory, std::vector<float> b,
std::vector<float> a);
virtual void read(int & length, sample_t* & buffer);
virtual AUD_IReader* createReader() const;
};
#endif //AUD_VOLUMEREADER
#endif //AUD_IIRFILTERFACTORY

@ -23,35 +23,28 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_RECTIFYREADER
#define AUD_RECTIFYREADER
#include "AUD_IIRFilterReader.h"
#include "AUD_EffectReader.h"
#include "AUD_Buffer.h"
/**
* This class reads another reader and rectifies it.
*/
class AUD_RectifyReader : public AUD_EffectReader
AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_IReader* reader,
std::vector<float> b,
std::vector<float> a) :
AUD_BaseIIRFilterReader(reader, b.size(), a.size()), m_a(a), m_b(b)
{
private:
/**
* The playback buffer.
*/
AUD_Buffer m_buffer;
for(int i = 1; i < m_a.size(); i++)
m_a[i] /= m_a[0];
for(int i = 0; i < m_b.size(); i++)
m_b[i] /= m_a[0];
m_a[0] = 1;
}
// hide copy constructor and operator=
AUD_RectifyReader(const AUD_RectifyReader&);
AUD_RectifyReader& operator=(const AUD_RectifyReader&);
sample_t AUD_IIRFilterReader::filter()
{
sample_t out = 0;
public:
/**
* Creates a new rectify reader.
* \param reader The reader to read from.
*/
AUD_RectifyReader(AUD_IReader* reader);
for(int i = 1; i < m_a.size(); i++)
out -= y(-i) * m_a[i];
for(int i = 0; i < m_b.size(); i++)
out += x(-i) * m_b[i];
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_RECTIFYREADER
return out;
}

@ -23,40 +23,44 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_SUMREADER
#define AUD_SUMREADER
#ifndef AUD_IIRFILTERREADER
#define AUD_IIRFILTERREADER
#include "AUD_EffectReader.h"
#include "AUD_Buffer.h"
#include "AUD_BaseIIRFilterReader.h"
#include <vector>
/**
* This class represents an summer.
* This class is for infinite impulse response filters with simple coefficients.
*/
class AUD_SumReader : public AUD_EffectReader
class AUD_IIRFilterReader : public AUD_BaseIIRFilterReader
{
private:
/**
* The playback buffer.
* Output filter coefficients.
*/
AUD_Buffer m_buffer;
std::vector<float> m_a;
/**
* The sums of the specific channels.
* Input filter coefficients.
*/
AUD_Buffer m_sums;
std::vector<float> m_b;
// hide copy constructor and operator=
AUD_SumReader(const AUD_SumReader&);
AUD_SumReader& operator=(const AUD_SumReader&);
AUD_IIRFilterReader(const AUD_IIRFilterReader&);
AUD_IIRFilterReader& operator=(const AUD_IIRFilterReader&);
public:
/**
* Creates a new sum reader.
* Creates a new IIR filter reader.
* \param reader The reader to read from.
* \param b The input filter coefficients.
* \param a The output filter coefficients.
*/
AUD_SumReader(AUD_IReader* reader);
AUD_IIRFilterReader(AUD_IReader* reader, std::vector<float> b,
std::vector<float> a);
virtual void read(int & length, sample_t* & buffer);
virtual sample_t filter();
};
#endif //AUD_SUMREADER
#endif //AUD_IIRFILTERREADER

@ -24,7 +24,13 @@
*/
#include "AUD_LowpassFactory.h"
#include "AUD_LowpassReader.h"
#include "AUD_IIRFilterReader.h"
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
AUD_LowpassFactory::AUD_LowpassFactory(AUD_IFactory* factory, float frequency,
float Q) :
@ -36,5 +42,20 @@ AUD_LowpassFactory::AUD_LowpassFactory(AUD_IFactory* factory, float frequency,
AUD_IReader* AUD_LowpassFactory::createReader() const
{
return new AUD_LowpassReader(getReader(), m_frequency, m_Q);
AUD_IReader* reader = getReader();
// calculate coefficients
float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate;
float alpha = sin(w0) / (2 * m_Q);
float norm = 1 + alpha;
float c = cos(w0);
std::vector<float> a, b;
a.push_back(1);
a.push_back(-2 * c / norm);
a.push_back((1 - alpha) / norm);
b.push_back((1 - c) / (2 * norm));
b.push_back((1 - c) / norm);
b.push_back(b[0]);
return new AUD_IIRFilterReader(reader, b, a);
}

@ -1,99 +0,0 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_LowpassReader.h"
#include <cstring>
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define CC channels + channel
AUD_LowpassReader::AUD_LowpassReader(AUD_IReader* reader, float frequency,
float Q) :
AUD_EffectReader(reader),
m_outvalues(AUD_SAMPLE_SIZE(reader->getSpecs()) * AUD_LOWPASS_ORDER),
m_invalues(AUD_SAMPLE_SIZE(reader->getSpecs()) * AUD_LOWPASS_ORDER),
m_position(0)
{
memset(m_outvalues.getBuffer(), 0, m_outvalues.getSize());
memset(m_invalues.getBuffer(), 0, m_invalues.getSize());
AUD_Specs specs = reader->getSpecs();
// calculate coefficients
float w0 = 2 * M_PI * frequency / specs.rate;
float alpha = sin(w0) / (2 * Q);
float norm = 1 + alpha;
m_coeff[0][0] = 0;
m_coeff[0][1] = -2 * cos(w0) / norm;
m_coeff[0][2] = (1 - alpha) / norm;
m_coeff[1][2] = m_coeff[1][0] = (1 - cos(w0)) / (2 * norm);
m_coeff[1][1] = (1 - cos(w0)) / norm;
}
void AUD_LowpassReader::read(int & length, sample_t* & buffer)
{
sample_t* buf;
sample_t* outvalues;
sample_t* invalues;
outvalues = m_outvalues.getBuffer();
invalues = m_invalues.getBuffer();
AUD_Specs specs = m_reader->getSpecs();
m_reader->read(length, buf);
if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(specs))
m_buffer.resize(length * AUD_SAMPLE_SIZE(specs));
buffer = m_buffer.getBuffer();
int channels = specs.channels;
for(int channel = 0; channel < channels; channel++)
{
for(int i = 0; i < length; i++)
{
invalues[m_position * CC] = buf[i * CC];
outvalues[m_position * CC] = 0;
for(int j = 0; j < AUD_LOWPASS_ORDER; j++)
{
outvalues[m_position * CC] += m_coeff[1][j] *
invalues[((m_position + j) % AUD_LOWPASS_ORDER) * CC] -
m_coeff[0][j] *
outvalues[((m_position + j) % AUD_LOWPASS_ORDER) * CC];
}
buffer[i * CC] = outvalues[m_position * CC];
m_position = (m_position + AUD_LOWPASS_ORDER-1) % AUD_LOWPASS_ORDER;
}
}
}

@ -1,81 +0,0 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_LOWPASSREADER
#define AUD_LOWPASSREADER
#include "AUD_EffectReader.h"
#include "AUD_Buffer.h"
#define AUD_LOWPASS_ORDER 3
/**
* This class represents a lowpass filter.
*/
class AUD_LowpassReader : public AUD_EffectReader
{
private:
/**
* The playback buffer.
*/
AUD_Buffer m_buffer;
/**
* The last out values buffer.
*/
AUD_Buffer m_outvalues;
/**
* The last in values buffer.
*/
AUD_Buffer m_invalues;
/**
* The position for buffer cycling.
*/
int m_position;
/**
* Filter coefficients.
*/
float m_coeff[2][AUD_LOWPASS_ORDER];
// hide copy constructor and operator=
AUD_LowpassReader(const AUD_LowpassReader&);
AUD_LowpassReader& operator=(const AUD_LowpassReader&);
public:
/**
* Creates a new lowpass reader.
* \param reader The reader to read from.
* \param frequency The cutoff frequency.
* \param Q The Q factor.
*/
AUD_LowpassReader(AUD_IReader* reader, float frequency, float Q);
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_LOWPASSREADER

@ -24,7 +24,14 @@
*/
#include "AUD_RectifyFactory.h"
#include "AUD_RectifyReader.h"
#include "AUD_CallbackIIRFilterReader.h"
#include <cmath>
sample_t rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
{
return fabs(reader->x(0));
}
AUD_RectifyFactory::AUD_RectifyFactory(AUD_IFactory* factory) :
AUD_EffectFactory(factory)
@ -33,5 +40,5 @@ AUD_RectifyFactory::AUD_RectifyFactory(AUD_IFactory* factory) :
AUD_IReader* AUD_RectifyFactory::createReader() const
{
return new AUD_RectifyReader(getReader());
return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, rectifyFilter);
}

@ -24,7 +24,23 @@
*/
#include "AUD_SquareFactory.h"
#include "AUD_SquareReader.h"
#include "AUD_CallbackIIRFilterReader.h"
sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold)
{
float in = reader->x(0);
if(in >= *threshold)
return 1;
else if(in <= -*threshold)
return -1;
else
return 0;
}
void endSquareFilter(float* threshold)
{
delete threshold;
}
AUD_SquareFactory::AUD_SquareFactory(AUD_IFactory* factory, float threshold) :
AUD_EffectFactory(factory),
@ -39,5 +55,8 @@ float AUD_SquareFactory::getThreshold() const
AUD_IReader* AUD_SquareFactory::createReader() const
{
return new AUD_SquareReader(getReader(), m_threshold);
return new AUD_CallbackIIRFilterReader(getReader(), 1, 1,
(doFilterIIR) squareFilter,
(endFilterIIR) endSquareFilter,
new float(m_threshold));
}

@ -1,57 +0,0 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_SquareReader.h"
#include <cstring>
AUD_SquareReader::AUD_SquareReader(AUD_IReader* reader, float threshold) :
AUD_EffectReader(reader),
m_threshold(threshold)
{
}
void AUD_SquareReader::read(int & length, sample_t* & buffer)
{
sample_t* buf;
AUD_Specs specs = m_reader->getSpecs();
m_reader->read(length, buf);
if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(specs))
m_buffer.resize(length * AUD_SAMPLE_SIZE(specs));
buffer = m_buffer.getBuffer();
for(int i = 0; i < length * specs.channels; i++)
{
if(buf[i] >= m_threshold)
buffer[i] = 1.0f;
else if(buf[i] <= -m_threshold)
buffer[i] = -1.0f;
else
buffer[i] = 0.0f;
}
}

@ -1,63 +0,0 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_SQUAREREADER
#define AUD_SQUAREREADER
#include "AUD_EffectReader.h"
#include "AUD_Buffer.h"
/**
* This class changes another signal into a square signal.
*/
class AUD_SquareReader : public AUD_EffectReader
{
private:
/**
* The playback buffer.
*/
AUD_Buffer m_buffer;
/**
* The threshold level.
*/
const float m_threshold;
// hide copy constructor and operator=
AUD_SquareReader(const AUD_SquareReader&);
AUD_SquareReader& operator=(const AUD_SquareReader&);
public:
/**
* Creates a new square reader.
* \param reader The reader to read from.
* \param threshold The size of the buffer.
*/
AUD_SquareReader(AUD_IReader* reader, float threshold);
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_SQUAREREADER

@ -24,7 +24,7 @@
*/
#include "AUD_SumFactory.h"
#include "AUD_SumReader.h"
#include "AUD_IIRFilterReader.h"
AUD_SumFactory::AUD_SumFactory(AUD_IFactory* factory) :
AUD_EffectFactory(factory)
@ -33,5 +33,9 @@ AUD_SumFactory::AUD_SumFactory(AUD_IFactory* factory) :
AUD_IReader* AUD_SumFactory::createReader() const
{
return new AUD_SumReader(getReader());
std::vector<float> a, b;
a.push_back(1);
a.push_back(-1);
b.push_back(1);
return new AUD_IIRFilterReader(getReader(), b, a);
}

@ -1,57 +0,0 @@
/*
* $Id$
*
* ***** BEGIN LGPL LICENSE BLOCK *****
*
* Copyright 2009 Jörg Hermann Müller
*
* This file is part of AudaSpace.
*
* AudaSpace is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AudaSpace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
*
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_SumReader.h"
#include <cstring>
#define CC specs.channels + channel
AUD_SumReader::AUD_SumReader(AUD_IReader* reader) :
AUD_EffectReader(reader),
m_sums(AUD_SAMPLE_SIZE(reader->getSpecs()))
{
memset(m_sums.getBuffer(), 0, m_sums.getSize());
}
void AUD_SumReader::read(int & length, sample_t* & buffer)
{
sample_t* buf;
sample_t* sums;
sums = m_sums.getBuffer();
AUD_Specs specs = m_reader->getSpecs();
m_reader->read(length, buf);
if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(specs))
m_buffer.resize(length * AUD_SAMPLE_SIZE(specs));
buffer = m_buffer.getBuffer();
for(int channel = 0; channel < specs.channels; channel++)
for(int i = 0; i < length * specs.channels; i++)
buffer[i * CC] = sums[channel] = sums[channel] + buf[i * CC];
}

@ -24,7 +24,7 @@
*/
#include "AUD_VolumeFactory.h"
#include "AUD_VolumeReader.h"
#include "AUD_IIRFilterReader.h"
AUD_VolumeFactory::AUD_VolumeFactory(AUD_IFactory* factory, float volume) :
AUD_EffectFactory(factory),
@ -39,5 +39,8 @@ float AUD_VolumeFactory::getVolume() const
AUD_IReader* AUD_VolumeFactory::createReader() const
{
return new AUD_VolumeReader(getReader(), m_volume);
std::vector<float> a, b;
a.push_back(1);
b.push_back(m_volume);
return new AUD_IIRFilterReader(getReader(), b, a);
}

@ -44,6 +44,7 @@
#include "AUD_StreamBufferFactory.h"
#include "AUD_SuperposeFactory.h"
#include "AUD_VolumeFactory.h"
#include "AUD_IIRFilterFactory.h"
#ifdef WITH_SDL
#include "AUD_SDLDevice.h"
@ -142,10 +143,12 @@ static PyObject *
Sound_file(PyObject* nothing, PyObject* args);
PyDoc_STRVAR(M_aud_Sound_lowpass_doc,
"lowpass(frequency)\n\n"
"Creates a low quality lowpass filter.\n\n"
"lowpass(frequency[, Q])\n\n"
"Creates a second order lowpass filter.\n\n"
":arg frequency: The cut off trequency of the lowpass.\n"
":type frequency: float\n"
":arg Q: Q factor of the lowpass.\n"
":type Q: float\n"
":return: The created aud.Sound object.\n"
":rtype: aud.Sound");
@ -177,10 +180,12 @@ static PyObject *
Sound_join(Sound* self, PyObject* object);
PyDoc_STRVAR(M_aud_Sound_highpass_doc,
"highpass(frequency)\n\n"
"Creates a low quality highpass filter.\n\n"
"highpass(frequency[, Q])\n\n"
"Creates a second order highpass filter.\n\n"
":arg frequency: The cut off trequency of the highpass.\n"
":type frequency: float\n"
":arg Q: Q factor of the lowpass.\n"
":type Q: float\n"
":return: The created aud.Sound object.\n"
":rtype: aud.Sound");
@ -322,6 +327,19 @@ PyDoc_STRVAR(M_aud_Sound_square_doc,
static PyObject *
Sound_square(Sound* self, PyObject* args);
PyDoc_STRVAR(M_aud_Sound_filter_doc,
"filter(b[, a = (1)])\n\n"
"Filters a sound with the supplied IIR filter coefficients.\n\n"
":arg b: The nominator filter coefficients.\n"
":type b: sequence of float\n"
":arg a: The denominator filter coefficients.\n"
":type a: sequence of float\n"
":return: The created aud.Sound object.\n"
":rtype: aud.Sound");
static PyObject *
Sound_filter(Sound* self, PyObject* args);
static PyMethodDef Sound_methods[] = {
{"sine", (PyCFunction)Sound_sine, METH_VARARGS | METH_STATIC,
M_aud_Sound_sine_doc
@ -374,6 +392,9 @@ static PyMethodDef Sound_methods[] = {
{"square", (PyCFunction)Sound_square, METH_VARARGS,
M_aud_Sound_square_doc
},
{"filter", (PyCFunction)Sound_filter, METH_VARARGS,
M_aud_Sound_filter_doc
},
{NULL} /* Sentinel */
};
@ -483,8 +504,9 @@ static PyObject *
Sound_lowpass(Sound* self, PyObject* args)
{
float frequency;
float Q = 0.5;
if(!PyArg_ParseTuple(args, "f", &frequency))
if(!PyArg_ParseTuple(args, "f|f", &frequency, &Q))
return NULL;
Sound *parent = (Sound*)SoundType.tp_alloc(&SoundType, 0);
@ -496,7 +518,7 @@ Sound_lowpass(Sound* self, PyObject* args)
try
{
parent->factory = new AUD_LowpassFactory(self->factory, frequency, 0.9);
parent->factory = new AUD_LowpassFactory(self->factory, frequency, Q);
}
catch(AUD_Exception&)
{
@ -574,8 +596,9 @@ static PyObject *
Sound_highpass(Sound* self, PyObject* args)
{
float frequency;
float Q = 0.5;
if(!PyArg_ParseTuple(args, "f", &frequency))
if(!PyArg_ParseTuple(args, "f|f", &frequency, &Q))
return NULL;
Sound *parent = (Sound*)SoundType.tp_alloc(&SoundType, 0);
@ -587,7 +610,7 @@ Sound_highpass(Sound* self, PyObject* args)
try
{
parent->factory = new AUD_HighpassFactory(self->factory, frequency, 0.9);
parent->factory = new AUD_HighpassFactory(self->factory, frequency, Q);
}
catch(AUD_Exception&)
{
@ -919,6 +942,86 @@ Sound_square(Sound* self, PyObject* args)
return (PyObject *)parent;
}
static PyObject *
Sound_filter(Sound* self, PyObject* args)
{
PyObject* py_b;
PyObject* py_a = NULL;
if(!PyArg_ParseTuple(args, "O|O", &py_b, &py_a))
return NULL;
if(!PySequence_Check(py_b) || (py_a != NULL && !PySequence_Check(py_a)))
{
PyErr_SetString(AUDError, "Supplied parameter is not a sequence!");
return NULL;
}
if(!PySequence_Length(py_b) || (py_a != NULL && !PySequence_Length(py_a)))
{
PyErr_SetString(AUDError, "The sequence has to contain at least one value!");
return NULL;
}
std::vector<float> a, b;
PyObject* py_value;
float value;
int result;
for(int i = 0; i < PySequence_Length(py_b); i++)
{
py_value = PySequence_GetItem(py_b, i);
result = PyArg_Parse(py_value, "f", &value);
Py_DECREF(py_value);
if(!result)
return NULL;
b.push_back(value);
}
if(py_a)
{
for(int i = 0; i < PySequence_Length(py_a); i++)
{
py_value = PySequence_GetItem(py_a, i);
result = PyArg_Parse(py_value, "f", &value);
Py_DECREF(py_value);
if(!result)
return NULL;
a.push_back(value);
}
if(a[0] == 0)
a[0] = 1;
}
else
a.push_back(1);
Sound *parent = (Sound*)SoundType.tp_alloc(&SoundType, 0);
if(parent != NULL)
{
Py_INCREF(self);
parent->child_list = (PyObject*)self;
try
{
parent->factory = new AUD_IIRFilterFactory(self->factory, b, a);
}
catch(AUD_Exception&)
{
Py_DECREF(parent);
PyErr_SetString(AUDError, "IIRFilterFactory couldn't be created!");
return NULL;
}
}
return (PyObject *)parent;
}
// ========== Handle ==================================================
static void

@ -1138,9 +1138,10 @@ int main(int argc, char **argv)
else {
if((G.fileflags & G_FILE_AUTOPLAY) && (G.f & G_SCRIPT_AUTOEXEC))
{
if(WM_init_game(C))
return 0;
}
else if(!G.file_loaded)
WM_init_splash(C);
}