Huge new year audio commit!

* Refactored the whole audaspace library to use float as sample format over all readers.
* Added new Readers like the linear resampler, envelope, lowpass, highpass and butterworth.
* Note: The butterworth filter isn't working correctly, some bug in there... Maybe also true for the envelope.
* Added a sound to f-curve operator that behaves mostly like the soundtracker script of technoestupido.
This commit is contained in:
Joerg Mueller 2010-01-01 05:09:30 +00:00
parent 3fa927a42e
commit 174eccf078
86 changed files with 2162 additions and 1613 deletions

@ -0,0 +1,49 @@
/*
* $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_ButterworthFactory.h"
#include "AUD_ButterworthReader.h"
AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_IFactory* factory,
float frequency) :
AUD_EffectFactory(factory),
m_frequency(frequency) {}
AUD_ButterworthFactory::AUD_ButterworthFactory(float frequency) :
AUD_EffectFactory(0),
m_frequency(frequency) {}
AUD_IReader* AUD_ButterworthFactory::createReader()
{
AUD_IReader* reader = getReader();
if(reader != 0)
{
reader = new AUD_ButterworthReader(reader, m_frequency);
AUD_NEW("reader")
}
return reader;
}

@ -0,0 +1,59 @@
/*
* $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_BUTTERWORTHFACTORY
#define AUD_BUTTERWORTHFACTORY
#include "AUD_EffectFactory.h"
/**
* This factory creates a butterworth filter reader.
*/
class AUD_ButterworthFactory : public AUD_EffectFactory
{
private:
/**
* The attack value in seconds.
*/
float m_frequency;
public:
/**
* Creates a new butterworth factory.
* \param factory The input factory.
* \param frequency The cutoff frequency.
*/
AUD_ButterworthFactory(AUD_IFactory* factory, float frequency);
/**
* Creates a new butterworth factory.
* \param frequency The cutoff frequency.
*/
AUD_ButterworthFactory(float frequency);
virtual AUD_IReader* createReader();
};
#endif //AUD_BUTTERWORTHFACTORY

@ -0,0 +1,120 @@
/*
* $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 "AUD_Buffer.h"
#include <cstring>
#include <cmath>
#define BWPB41 0.76536686473
#define BWPB42 1.84775906502
#define CC channels + channel
AUD_ButterworthReader::AUD_ButterworthReader(AUD_IReader* reader,
float frequency) :
AUD_EffectReader(reader)
{
AUD_Specs specs = reader->getSpecs();
int samplesize = AUD_SAMPLE_SIZE(specs);
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_outvalues = new AUD_Buffer(samplesize * 5); AUD_NEW("buffer")
memset(m_outvalues->getBuffer(), 0, samplesize * 5);
m_invalues = new AUD_Buffer(samplesize * 5); AUD_NEW("buffer")
memset(m_invalues->getBuffer(), 0, samplesize * 5);
m_position = 0;
// 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;
}
AUD_ButterworthReader::~AUD_ButterworthReader()
{
delete m_buffer; AUD_DELETE("buffer")
delete m_outvalues; AUD_DELETE("buffer")
delete m_invalues; AUD_DELETE("buffer");
}
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;
}
}
}

@ -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_BUTTERWORTHREADER
#define AUD_BUTTERWORTHREADER
#include "AUD_EffectReader.h"
class AUD_Buffer;
/**
* 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];
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.
* \exception AUD_Exception Thrown if the reader specified is NULL.
*/
AUD_ButterworthReader(AUD_IReader* reader, float frequency);
/**
* Destroys the reader.
*/
virtual ~AUD_ButterworthReader();
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_BUTTERWORTHREADER

@ -77,31 +77,26 @@ void AUD_DelayReader::read(int & length, sample_t* & buffer)
{
if(m_remdelay > 0)
{
int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs());
AUD_Specs specs = m_reader->getSpecs();
int samplesize = AUD_SAMPLE_SIZE(specs);
if(m_buffer->getSize() < length*samplesize)
m_buffer->resize(length*samplesize);
if(m_buffer->getSize() < length * samplesize)
m_buffer->resize(length * samplesize);
if(length > m_remdelay)
{
if(getSpecs().format == AUD_FORMAT_U8)
memset(m_buffer->getBuffer(), 0x80, m_remdelay*samplesize);
else
memset(m_buffer->getBuffer(), 0, m_remdelay*samplesize);
memset(m_buffer->getBuffer(), 0, m_remdelay * samplesize);
int len = length - m_remdelay;
m_reader->read(len, buffer);
memcpy(m_buffer->getBuffer()+m_remdelay*samplesize,
buffer, len*samplesize);
memcpy(m_buffer->getBuffer() + m_remdelay * specs.channels,
buffer, len * samplesize);
if(len < length-m_remdelay)
length = m_remdelay + len;
m_remdelay = 0;
}
else
{
if(getSpecs().format == AUD_FORMAT_U8)
memset(m_buffer->getBuffer(), 0x80, length*samplesize);
else
memset(m_buffer->getBuffer(), 0, length*samplesize);
memset(m_buffer->getBuffer(), 0, length * samplesize);
m_remdelay -= length;
}
buffer = m_buffer->getBuffer();

@ -137,15 +137,16 @@ void AUD_DoubleReader::read(int & length, sample_t* & buffer)
m_reader1->read(len, buffer);
if(len < length)
{
int samplesize = AUD_SAMPLE_SIZE(m_reader1->getSpecs());
AUD_Specs specs = m_reader1->getSpecs();
int samplesize = AUD_SAMPLE_SIZE(specs);
if(m_buffer->getSize() < length * samplesize)
m_buffer->resize(length * samplesize);
memcpy(m_buffer->getBuffer(), buffer, len*samplesize);
memcpy(m_buffer->getBuffer(), buffer, len * samplesize);
len = length - len;
length -= len;
m_reader2->read(len, buffer);
memcpy(m_buffer->getBuffer() + length*samplesize,
buffer, len*samplesize);
memcpy(m_buffer->getBuffer() + length * specs.channels, buffer,
len * samplesize);
length += len;
buffer = m_buffer->getBuffer();
m_finished1 = true;

@ -0,0 +1,58 @@
/*
* $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_EnvelopeFactory.h"
#include "AUD_EnvelopeReader.h"
AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack,
float release, float threshold,
float arthreshold) :
AUD_EffectFactory(factory),
m_attack(attack),
m_release(release),
m_threshold(threshold),
m_arthreshold(arthreshold) {}
AUD_EnvelopeFactory::AUD_EnvelopeFactory(float attack, float release,
float threshold, float arthreshold) :
AUD_EffectFactory(0),
m_attack(attack),
m_release(release),
m_threshold(threshold),
m_arthreshold(arthreshold) {}
AUD_IReader* AUD_EnvelopeFactory::createReader()
{
AUD_IReader* reader = getReader();
if(reader != 0)
{
reader = new AUD_EnvelopeReader(reader, m_attack, m_release,
m_threshold, m_arthreshold);
AUD_NEW("reader")
}
return reader;
}

@ -0,0 +1,82 @@
/*
* $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_ENVELOPEFACTORY
#define AUD_ENVELOPEFACTORY
#include "AUD_EffectFactory.h"
/**
* This factory creates an envelope follower reader.
*/
class AUD_EnvelopeFactory : public AUD_EffectFactory
{
private:
/**
* The attack value in seconds.
*/
float m_attack;
/**
* The release value in seconds.
*/
float m_release;
/**
* The threshold value.
*/
float m_threshold;
/**
* The attack/release threshold value.
*/
float m_arthreshold;
public:
/**
* Creates a new envelope factory.
* \param factory The input factory.
* \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_EnvelopeFactory(AUD_IFactory* factory, float attack, float release,
float threshold, float arthreshold);
/**
* Creates a new envelope factory.
* \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_EnvelopeFactory(float attack, float release, float threshold,
float arthreshold);
virtual AUD_IReader* createReader();
};
#endif //AUD_ENVELOPEFACTORY

@ -0,0 +1,86 @@
/*
* $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 "AUD_Buffer.h"
#include <cstring>
#include <cmath>
AUD_EnvelopeReader::AUD_EnvelopeReader(AUD_IReader* reader, float attack,
float release, float threshold,
float arthreshold) :
AUD_EffectReader(reader),
m_threshold(threshold)
{
AUD_Specs specs = reader->getSpecs();
int samplesize = AUD_SAMPLE_SIZE(specs);
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_envelopes = new AUD_Buffer(samplesize);
AUD_NEW("buffer")
memset(m_envelopes->getBuffer(), 0, samplesize);
m_bAttack = pow(arthreshold, 1.0/(specs.rate * attack));
m_bRelease = pow(arthreshold, 1.0/(specs.rate * release));
}
AUD_EnvelopeReader::~AUD_EnvelopeReader()
{
delete m_buffer; AUD_DELETE("buffer")
delete m_envelopes; AUD_DELETE("buffer")
}
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;
}
}
}

@ -0,0 +1,84 @@
/*
* $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"
class AUD_Buffer;
/**
* This class represents an envelope follower.
*/
class AUD_EnvelopeReader : public AUD_EffectReader
{
private:
/**
* The playback buffer.
*/
AUD_Buffer *m_buffer;
/**
* The last envelopes buffer.
*/
AUD_Buffer *m_envelopes;
/**
* Attack b value.
*/
float m_bAttack;
/**
* Release b value.
*/
float m_bRelease;
/**
* Threshold value.
*/
float m_threshold;
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.
* \exception AUD_Exception Thrown if the reader specified is NULL.
*/
AUD_EnvelopeReader(AUD_IReader* reader, float attack, float release,
float threshold, float arthreshold);
/**
* Destroys the reader.
*/
virtual ~AUD_EnvelopeReader();
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_ENVELOPEREADER

@ -35,35 +35,6 @@ AUD_FaderReader::AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type,
m_start(start),
m_length(length)
{
int bigendian = 1;
bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
switch(m_reader->getSpecs().format)
{
case AUD_FORMAT_S16:
m_adjust = AUD_volume_adjust<int16_t>;
break;
case AUD_FORMAT_S32:
m_adjust = AUD_volume_adjust<int32_t>;
break;
case AUD_FORMAT_FLOAT32:
m_adjust = AUD_volume_adjust<float>;
break;
case AUD_FORMAT_FLOAT64:
m_adjust = AUD_volume_adjust<double>;
break;
case AUD_FORMAT_U8:
m_adjust = AUD_volume_adjust_u8;
break;
case AUD_FORMAT_S24:
m_adjust = bigendian ? AUD_volume_adjust_s24_be :
AUD_volume_adjust_s24_le;
break;
default:
delete m_reader;
AUD_THROW(AUD_ERROR_READER);
}
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
}
@ -93,9 +64,7 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer)
if(m_type != AUD_FADE_OUT)
{
buffer = m_buffer->getBuffer();
memset(buffer,
specs.format == AUD_FORMAT_U8 ? 0x80 : 0,
length * samplesize);
memset(buffer, 0, length * samplesize);
}
}
else if(position / (float)specs.rate >= m_start+m_length)
@ -103,9 +72,7 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer)
if(m_type == AUD_FADE_OUT)
{
buffer = m_buffer->getBuffer();
memset(buffer,
specs.format == AUD_FORMAT_U8 ? 0x80 : 0,
length * samplesize);
memset(buffer, 0, length * samplesize);
}
}
else
@ -113,19 +80,21 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer)
sample_t* buf = m_buffer->getBuffer();
float volume;
for(int i = 0; i < length; i++)
for(int i = 0; i < length * specs.channels; i++)
{
volume = (((position+i)/(float)specs.rate)-m_start) / m_length;
if(volume > 1.0f)
volume = 1.0f;
else if(volume < 0.0f)
volume = 0.0f;
if(i % specs.channels == 0)
{
volume = (((position+i)/(float)specs.rate)-m_start) / m_length;
if(volume > 1.0f)
volume = 1.0f;
else if(volume < 0.0f)
volume = 0.0f;
if(m_type == AUD_FADE_OUT)
volume = 1.0f - volume;
if(m_type == AUD_FADE_OUT)
volume = 1.0f - volume;
}
m_adjust(buf + i * samplesize, buffer + i * samplesize,
specs.channels, volume);
buf[i] = buffer[i] * volume;
}
buffer = buf;

@ -27,7 +27,6 @@
#define AUD_FADERREADER
#include "AUD_EffectReader.h"
#include "AUD_ConverterFunctions.h"
class AUD_Buffer;
/**
@ -58,11 +57,6 @@ private:
*/
float m_length;
/**
* Volume adjustment function.
*/
AUD_volume_adjust_f m_adjust;
public:
/**
* Creates a new fader reader.

@ -0,0 +1,51 @@
/*
* $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_HighpassFactory.h"
#include "AUD_HighpassReader.h"
AUD_HighpassFactory::AUD_HighpassFactory(AUD_IFactory* factory, float frequency,
float Q) :
AUD_EffectFactory(factory),
m_frequency(frequency),
m_Q(Q) {}
AUD_HighpassFactory::AUD_HighpassFactory(float frequency, float Q) :
AUD_EffectFactory(0),
m_frequency(frequency),
m_Q(Q) {}
AUD_IReader* AUD_HighpassFactory::createReader()
{
AUD_IReader* reader = getReader();
if(reader != 0)
{
reader = new AUD_HighpassReader(reader, m_frequency, m_Q);
AUD_NEW("reader")
}
return reader;
}

@ -23,54 +23,44 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_SDLMIXER
#define AUD_SDLMIXER
#ifndef AUD_HIGHPASSFACTORY
#define AUD_HIGHPASSFACTORY
#include "AUD_IMixer.h"
class AUD_SDLMixerFactory;
#include <list>
struct AUD_SDLMixerBuffer
{
sample_t* buffer;
int length;
float volume;
};
#include "AUD_EffectFactory.h"
/**
* This class is able to mix audiosignals with the help of SDL.
* This factory creates a highpass filter reader.
*/
class AUD_SDLMixer : public AUD_IMixer
class AUD_HighpassFactory : public AUD_EffectFactory
{
private:
/**
* The mixer factory that prepares all readers for superposition.
* The attack value in seconds.
*/
AUD_SDLMixerFactory* m_factory;
float m_frequency;
/**
* The list of buffers to superpose.
* The Q factor.
*/
std::list<AUD_SDLMixerBuffer> m_buffers;
/**
* The size of an output sample.
*/
int m_samplesize;
float m_Q;
public:
/**
* Creates the mixer.
* Creates a new highpass factory.
* \param factory The input factory.
* \param frequency The cutoff frequency.
* \param Q The Q factor.
*/
AUD_SDLMixer();
AUD_HighpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0);
virtual ~AUD_SDLMixer();
/**
* Creates a new highpass factory.
* \param frequency The cutoff frequency.
* \param Q The Q factor.
*/
AUD_HighpassFactory(float frequency, float Q = 1.0);
virtual AUD_IReader* prepare(AUD_IReader* reader);
virtual void setSpecs(AUD_Specs specs);
virtual void add(sample_t* buffer, AUD_Specs specs, int length,
float volume);
virtual void superpose(sample_t* buffer, int length, float volume);
virtual AUD_IReader* createReader();
};
#endif //AUD_SDLMIXER
#endif //AUD_HIGHPASSFACTORY

@ -0,0 +1,112 @@
/*
* $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 "AUD_Buffer.h"
#include <cstring>
#include <cmath>
#define CC channels + channel
AUD_HighpassReader::AUD_HighpassReader(AUD_IReader* reader, float frequency,
float Q) :
AUD_EffectReader(reader)
{
AUD_Specs specs = reader->getSpecs();
int samplesize = AUD_SAMPLE_SIZE(specs);
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_outvalues = new AUD_Buffer(samplesize * AUD_HIGHPASS_ORDER);
AUD_NEW("buffer")
memset(m_outvalues->getBuffer(), 0, samplesize * AUD_HIGHPASS_ORDER);
m_invalues = new AUD_Buffer(samplesize * AUD_HIGHPASS_ORDER);
AUD_NEW("buffer")
memset(m_invalues->getBuffer(), 0, samplesize * AUD_HIGHPASS_ORDER);
m_position = 0;
// calculate coefficients
float w0 = 2.0 * 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;
}
AUD_HighpassReader::~AUD_HighpassReader()
{
delete m_buffer; AUD_DELETE("buffer")
delete m_outvalues; AUD_DELETE("buffer")
delete m_invalues; AUD_DELETE("buffer");
}
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;
}
}
}

@ -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_HIGHPASSREADER
#define AUD_HIGHPASSREADER
#include "AUD_EffectReader.h"
class AUD_Buffer;
#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];
public:
/**
* Creates a new highpass reader.
* \param reader The reader to read from.
* \param frequency The cutoff frequency.
* \param Q The Q factor.
* \exception AUD_Exception Thrown if the reader specified is NULL.
*/
AUD_HighpassReader(AUD_IReader* reader, float frequency, float Q);
/**
* Destroys the reader.
*/
virtual ~AUD_HighpassReader();
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_HIGHPASSREADER

@ -27,7 +27,6 @@
#include "AUD_Buffer.h"
#include <cstring>
#include <stdio.h>
AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) :
AUD_EffectReader(reader), m_loop(loop)
@ -62,7 +61,8 @@ bool AUD_LoopReader::notify(AUD_Message &message)
void AUD_LoopReader::read(int & length, sample_t* & buffer)
{
int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs());
AUD_Specs specs = m_reader->getSpecs();
int samplesize = AUD_SAMPLE_SIZE(specs);
int len = length;
@ -72,10 +72,10 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer)
{
int pos = 0;
if(m_buffer->getSize() < length*samplesize)
m_buffer->resize(length*samplesize);
if(m_buffer->getSize() < length * samplesize)
m_buffer->resize(length * samplesize);
memcpy(m_buffer->getBuffer() + pos * samplesize,
memcpy(m_buffer->getBuffer() + pos * specs.channels,
buffer, len * samplesize);
pos += len;
@ -93,7 +93,7 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer)
if(!len)
break;
memcpy(m_buffer->getBuffer() + pos * samplesize,
memcpy(m_buffer->getBuffer() + pos * specs.channels,
buffer, len * samplesize);
pos += len;

@ -0,0 +1,51 @@
/*
* $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_LowpassFactory.h"
#include "AUD_LowpassReader.h"
AUD_LowpassFactory::AUD_LowpassFactory(AUD_IFactory* factory, float frequency,
float Q) :
AUD_EffectFactory(factory),
m_frequency(frequency),
m_Q(Q) {}
AUD_LowpassFactory::AUD_LowpassFactory(float frequency, float Q) :
AUD_EffectFactory(0),
m_frequency(frequency),
m_Q(Q) {}
AUD_IReader* AUD_LowpassFactory::createReader()
{
AUD_IReader* reader = getReader();
if(reader != 0)
{
reader = new AUD_LowpassReader(reader, m_frequency, m_Q);
AUD_NEW("reader")
}
return reader;
}

@ -0,0 +1,66 @@
/*
* $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_LOWPASSFACTORY
#define AUD_LOWPASSFACTORY
#include "AUD_EffectFactory.h"
/**
* This factory creates a lowpass filter reader.
*/
class AUD_LowpassFactory : public AUD_EffectFactory
{
private:
/**
* The attack value in seconds.
*/
float m_frequency;
/**
* The Q factor.
*/
float m_Q;
public:
/**
* Creates a new lowpass factory.
* \param factory The input factory.
* \param frequency The cutoff frequency.
* \param Q The Q factor.
*/
AUD_LowpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0);
/**
* Creates a new lowpass factory.
* \param frequency The cutoff frequency.
* \param Q The Q factor.
*/
AUD_LowpassFactory(float frequency, float Q = 1.0);
virtual AUD_IReader* createReader();
};
#endif //AUD_LOWPASSFACTORY

@ -0,0 +1,111 @@
/*
* $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 "AUD_Buffer.h"
#include <cstring>
#include <cmath>
#define CC channels + channel
AUD_LowpassReader::AUD_LowpassReader(AUD_IReader* reader, float frequency,
float Q) :
AUD_EffectReader(reader)
{
AUD_Specs specs = reader->getSpecs();
int samplesize = AUD_SAMPLE_SIZE(specs);
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_outvalues = new AUD_Buffer(samplesize * AUD_LOWPASS_ORDER);
AUD_NEW("buffer")
memset(m_outvalues->getBuffer(), 0, samplesize * AUD_LOWPASS_ORDER);
m_invalues = new AUD_Buffer(samplesize * AUD_LOWPASS_ORDER);
AUD_NEW("buffer")
memset(m_invalues->getBuffer(), 0, samplesize * AUD_LOWPASS_ORDER);
m_position = 0;
// calculate coefficients
float w0 = 2.0 * 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;
}
AUD_LowpassReader::~AUD_LowpassReader()
{
delete m_buffer; AUD_DELETE("buffer")
delete m_outvalues; AUD_DELETE("buffer")
delete m_invalues; AUD_DELETE("buffer");
}
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;
}
}
}

@ -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_LOWPASSREADER
#define AUD_LOWPASSREADER
#include "AUD_EffectReader.h"
class AUD_Buffer;
#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];
public:
/**
* Creates a new lowpass reader.
* \param reader The reader to read from.
* \param frequency The cutoff frequency.
* \param Q The Q factor.
* \exception AUD_Exception Thrown if the reader specified is NULL.
*/
AUD_LowpassReader(AUD_IReader* reader, float frequency, float Q);
/**
* Destroys the reader.
*/
virtual ~AUD_LowpassReader();
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_LOWPASSREADER

@ -26,39 +26,11 @@
#include "AUD_RectifyReader.h"
#include "AUD_Buffer.h"
#include <cstring>
#include <cmath>
AUD_RectifyReader::AUD_RectifyReader(AUD_IReader* reader) :
AUD_EffectReader(reader)
{
int bigendian = 1;
bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
switch(m_reader->getSpecs().format)
{
case AUD_FORMAT_S16:
m_rectify = AUD_rectify<int16_t>;
break;
case AUD_FORMAT_S32:
m_rectify = AUD_rectify<int32_t>;
break;
case AUD_FORMAT_FLOAT32:
m_rectify = AUD_rectify<float>;
break;
case AUD_FORMAT_FLOAT64:
m_rectify = AUD_rectify<double>;
break;
case AUD_FORMAT_U8:
m_rectify = AUD_rectify_u8;
break;
case AUD_FORMAT_S24:
m_rectify = bigendian ? AUD_rectify_s24_be : AUD_rectify_s24_le;
break;
default:
delete m_reader;
AUD_THROW(AUD_ERROR_READER);
}
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
}
@ -73,10 +45,11 @@ void AUD_RectifyReader::read(int & length, sample_t* & buffer)
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));
if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs))
m_buffer->resize(length * AUD_SAMPLE_SIZE(specs));
buffer = m_buffer->getBuffer();
m_rectify(buffer, buf, length * specs.channels);
for(int i = 0; i < length * specs.channels; i++)
buffer[i] = fabs(buf[i]);
}

@ -27,7 +27,6 @@
#define AUD_RECTIFYREADER
#include "AUD_EffectReader.h"
#include "AUD_ConverterFunctions.h"
class AUD_Buffer;
/**
@ -41,11 +40,6 @@ private:
*/
AUD_Buffer *m_buffer;
/**
* Rectifying function.
*/
AUD_rectify_f m_rectify;
public:
/**
* Creates a new rectify reader.

@ -65,7 +65,7 @@ int AUD_ReverseReader::getPosition()
void AUD_ReverseReader::read(int & length, sample_t* & buffer)
{
// first correct the length
if(m_position+length > m_length)
if(m_position + length > m_length)
length = m_length-m_position;
if(length <= 0)
@ -74,7 +74,8 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer)
return;
}
int samplesize = AUD_SAMPLE_SIZE(getSpecs());
AUD_Specs specs = getSpecs();
int samplesize = AUD_SAMPLE_SIZE(specs);
// resize buffer if needed
if(m_buffer->getSize() < length * samplesize)
@ -86,23 +87,20 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer)
int len = length;
// read from reader
m_reader->seek(m_length-m_position-len);
m_reader->seek(m_length - m_position - len);
m_reader->read(len, buf);
// set null if reader didn't give enough data
if(len < length)
{
if(getSpecs().format == AUD_FORMAT_U8)
memset(buffer, 0x80, (length-len)*samplesize);
else
memset(buffer, 0, (length-len)*samplesize);
buffer += length-len;
memset(buffer, 0, (length - len) * samplesize);
buffer += (length - len) * specs.channels;
}
// copy the samples reverted
for(int i = 0; i < len; i++)
memcpy(buffer + i * samplesize,
buf + (len - 1 - i) * samplesize,
memcpy(buffer + i * specs.channels,
buf + (len - 1 - i) * specs.channels,
samplesize);
m_position += length;

@ -32,35 +32,6 @@ AUD_VolumeReader::AUD_VolumeReader(AUD_IReader* reader, float volume) :
AUD_EffectReader(reader),
m_volume(volume)
{
int bigendian = 1;
bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
switch(m_reader->getSpecs().format)
{
case AUD_FORMAT_S16:
m_adjust = AUD_volume_adjust<int16_t>;
break;
case AUD_FORMAT_S32:
m_adjust = AUD_volume_adjust<int32_t>;
break;
case AUD_FORMAT_FLOAT32:
m_adjust = AUD_volume_adjust<float>;
break;
case AUD_FORMAT_FLOAT64:
m_adjust = AUD_volume_adjust<double>;
break;
case AUD_FORMAT_U8:
m_adjust = AUD_volume_adjust_u8;
break;
case AUD_FORMAT_S24:
m_adjust = bigendian ? AUD_volume_adjust_s24_be :
AUD_volume_adjust_s24_le;
break;
default:
delete m_reader;
AUD_THROW(AUD_ERROR_READER);
}
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
}
@ -93,5 +64,6 @@ void AUD_VolumeReader::read(int & length, sample_t* & buffer)
buffer = m_buffer->getBuffer();
m_adjust(buffer, buf, length * specs.channels, m_volume);
for(int i = 0; i < length * specs.channels; i++)
buffer[i] = buf[i] * m_volume;
}

@ -27,7 +27,6 @@
#define AUD_VOLUMEREADER
#include "AUD_EffectReader.h"
#include "AUD_ConverterFunctions.h"
class AUD_Buffer;
/**
@ -46,11 +45,6 @@ private:
*/
float m_volume;
/**
* Volume adjustment function.
*/
AUD_volume_adjust_f m_adjust;
public:
/**
* Creates a new volume reader.

@ -25,7 +25,6 @@
#include "AUD_OpenALDevice.h"
#include "AUD_IReader.h"
#include "AUD_IMixer.h"
#include "AUD_ConverterFactory.h"
#include "AUD_SourceCaps.h"
@ -119,7 +118,7 @@ void AUD_OpenALDevice::updateStreams()
sample_t* buffer;
ALint info;
AUD_Specs specs;
AUD_DeviceSpecs specs = m_specs;
while(1)
{
@ -145,7 +144,7 @@ void AUD_OpenALDevice::updateStreams()
if(info)
{
specs = sound->reader->getSpecs();
specs.specs = sound->reader->getSpecs();
// for all empty buffers
while(info--)
@ -177,8 +176,8 @@ void AUD_OpenALDevice::updateStreams()
// fill with new data
alBufferData(sound->buffers[sound->current],
sound->format,
buffer,
length * AUD_SAMPLE_SIZE(specs),
buffer, length *
AUD_DEVICE_SAMPLE_SIZE(specs),
specs.rate);
if(alGetError() != AL_NO_ERROR)
@ -264,7 +263,7 @@ bool AUD_OpenALDevice::isValid(AUD_Handle* handle)
return false;
}
AUD_OpenALDevice::AUD_OpenALDevice(AUD_Specs specs, int buffersize)
AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
{
// cannot determine how many channels or which format OpenAL uses, but
// it at least is able to play 16 bit stereo audio
@ -289,14 +288,17 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_Specs specs, int buffersize)
// check for specific formats and channel counts to be played back
if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE)
{
specs.format = AUD_FORMAT_FLOAT32;
m_converter = NULL;
}
else
m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory")
m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE;
alGetError();
m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory")
m_specs = specs;
m_buffersize = buffersize;
m_playing = false;
@ -378,12 +380,13 @@ AUD_OpenALDevice::~AUD_OpenALDevice()
alcDestroyContext(m_context);
alcCloseDevice(m_device);
delete m_converter; AUD_DELETE("factory")
if(m_converter)
delete m_converter; AUD_DELETE("factory")
pthread_mutex_destroy(&m_mutex);
}
AUD_Specs AUD_OpenALDevice::getSpecs()
AUD_DeviceSpecs AUD_OpenALDevice::getSpecs()
{
return m_specs;
}
@ -393,45 +396,8 @@ bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs)
bool valid = true;
format = 0;
switch(specs.format)
switch(m_specs.format)
{
case AUD_FORMAT_U8:
switch(specs.channels)
{
case AUD_CHANNELS_MONO:
format = AL_FORMAT_MONO8;
break;
case AUD_CHANNELS_STEREO:
format = AL_FORMAT_STEREO8;
break;
case AUD_CHANNELS_SURROUND4:
if(m_useMC)
{
format = alGetEnumValue("AL_FORMAT_QUAD8");
break;
}
case AUD_CHANNELS_SURROUND51:
if(m_useMC)
{
format = alGetEnumValue("AL_FORMAT_51CHN8");
break;
}
case AUD_CHANNELS_SURROUND61:
if(m_useMC)
{
format = alGetEnumValue("AL_FORMAT_61CHN8");
break;
}
case AUD_CHANNELS_SURROUND71:
if(m_useMC)
{
format = alGetEnumValue("AL_FORMAT_71CHN8");
break;
}
default:
valid = false;
}
break;
case AUD_FORMAT_S16:
switch(specs.channels)
{
@ -591,23 +557,16 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
if(reader == NULL)
AUD_THROW(AUD_ERROR_READER);
AUD_Specs specs;
specs = reader->getSpecs();
AUD_DeviceSpecs specs = m_specs;
specs.specs = reader->getSpecs();
// check format
bool valid = true;
bool valid = specs.channels != AUD_CHANNELS_INVALID;
if(specs.format == AUD_FORMAT_INVALID)
valid = false;
else if(specs.format == AUD_FORMAT_S24 ||
specs.format == AUD_FORMAT_S32 ||
specs.format == AUD_FORMAT_FLOAT32 ||
specs.format == AUD_FORMAT_FLOAT64)
if(m_converter)
{
m_converter->setReader(reader);
reader = m_converter->createReader();
specs = reader->getSpecs();
}
// create the handle
@ -618,7 +577,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
sound->isBuffered = false;
sound->data_end = false;
valid &= getFormat(sound->format, specs);
valid &= getFormat(sound->format, specs.specs);
if(!valid)
{
@ -647,7 +606,8 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
length = m_buffersize;
reader->read(length, buf);
alBufferData(sound->buffers[i], sound->format, buf,
length * AUD_SAMPLE_SIZE(specs), specs.rate);
length * AUD_DEVICE_SAMPLE_SIZE(specs),
specs.rate);
if(alGetError() != AL_NO_ERROR)
AUD_THROW(AUD_ERROR_OPENAL);
}
@ -875,14 +835,16 @@ bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position)
{
sample_t* buf;
int length;
AUD_Specs specs = alhandle->reader->getSpecs();
AUD_DeviceSpecs specs = m_specs;
specs.specs = alhandle->reader->getSpecs();
for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++)
{
length = m_buffersize;
alhandle->reader->read(length, buf);
alBufferData(alhandle->buffers[i], alhandle->format,
buf, length * AUD_SAMPLE_SIZE(specs),
buf,
length * AUD_DEVICE_SAMPLE_SIZE(specs),
specs.rate);
if(alGetError() != AL_NO_ERROR)
@ -1021,6 +983,7 @@ bool AUD_OpenALDevice::setCapability(int capability, void *value)
// load the factory into an OpenAL buffer
if(factory)
{
// check if the factory is already buffered
lock();
for(AUD_BFIterator i = m_bufferedFactories->begin();
i != m_bufferedFactories->end(); i++)
@ -1040,32 +1003,25 @@ bool AUD_OpenALDevice::setCapability(int capability, void *value)
if(reader == NULL)
return false;
AUD_Specs specs;
specs = reader->getSpecs();
AUD_DeviceSpecs specs = m_specs;
specs.specs = reader->getSpecs();
// determine format
bool valid = reader->getType() == AUD_TYPE_BUFFER;
if(valid)
{
if(specs.format == AUD_FORMAT_INVALID)
valid = false;
else if(specs.format == AUD_FORMAT_S24 ||
specs.format == AUD_FORMAT_S32 ||
specs.format == AUD_FORMAT_FLOAT32 ||
specs.format == AUD_FORMAT_FLOAT64)
if(m_converter)
{
m_converter->setReader(reader);
reader = m_converter->createReader();
specs = reader->getSpecs();
}
}
ALenum format;
if(valid)
valid = getFormat(format, specs);
valid = getFormat(format, specs.specs);
if(!valid)
{
@ -1094,7 +1050,7 @@ bool AUD_OpenALDevice::setCapability(int capability, void *value)
reader->read(length, buf);
alBufferData(bf->buffer, format, buf,
length * AUD_SAMPLE_SIZE(specs),
length * AUD_DEVICE_SAMPLE_SIZE(specs),
specs.rate);
if(alGetError() != AL_NO_ERROR)
AUD_THROW(AUD_ERROR_OPENAL);

@ -56,7 +56,7 @@ private:
/**
* The specification of the device.
*/
AUD_Specs m_specs;
AUD_DeviceSpecs m_specs;
/**
* Whether the device has the AL_EXT_MCFORMATS extension.
@ -64,8 +64,8 @@ private:
bool m_useMC;
/**
* The converter factory for readers with wrong input format.
*/
* The converter factory for readers with wrong input format.
*/
AUD_ConverterFactory* m_converter;
/**
@ -118,7 +118,7 @@ private:
/**
* Gets the format according to the specs.
* \param format The variable to put the format into.
* \param specs The specs to read the format from.
* \param specs The specs to read the channel count from.
* \return Whether the format is valid or not.
*/
bool getFormat(ALenum &format, AUD_Specs specs);
@ -132,7 +132,8 @@ public:
* \note The buffersize will be multiplicated by three for this device.
* \exception AUD_Exception Thrown if the audio device cannot be opened.
*/
AUD_OpenALDevice(AUD_Specs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE);
AUD_OpenALDevice(AUD_DeviceSpecs specs,
int buffersize = AUD_DEFAULT_BUFFER_SIZE);
/**
* Streaming thread main function.
@ -141,7 +142,7 @@ public:
virtual ~AUD_OpenALDevice();
virtual AUD_Specs getSpecs();
virtual AUD_DeviceSpecs getSpecs();
virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false);
virtual bool pause(AUD_Handle* handle);
virtual bool resume(AUD_Handle* handle);

@ -23,7 +23,6 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_SDLMixer.h"
#include "AUD_SDLDevice.h"
#include "AUD_IReader.h"
@ -31,10 +30,10 @@ void AUD_SDLDevice::SDL_mix(void *data, Uint8* buffer, int length)
{
AUD_SDLDevice* device = (AUD_SDLDevice*)data;
device->mix((sample_t*)buffer, length/AUD_SAMPLE_SIZE(device->m_specs));
device->mix((data_t*)buffer,length/AUD_DEVICE_SAMPLE_SIZE(device->m_specs));
}
AUD_SDLDevice::AUD_SDLDevice(AUD_Specs specs, int buffersize)
AUD_SDLDevice::AUD_SDLDevice(AUD_DeviceSpecs specs, int buffersize)
{
if(specs.channels == AUD_CHANNELS_INVALID)
specs.channels = AUD_CHANNELS_STEREO;
@ -69,9 +68,6 @@ AUD_SDLDevice::AUD_SDLDevice(AUD_Specs specs, int buffersize)
else
AUD_THROW(AUD_ERROR_SDL);
m_mixer = new AUD_SDLMixer(); AUD_NEW("mixer")
m_mixer->setSpecs(m_specs);
create();
}

@ -55,7 +55,8 @@ public:
* \note The specification really used for opening the device may differ.
* \exception AUD_Exception Thrown if the audio device cannot be opened.
*/
AUD_SDLDevice(AUD_Specs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE);
AUD_SDLDevice(AUD_DeviceSpecs specs,
int buffersize = AUD_DEFAULT_BUFFER_SIZE);
/**
* Closes the SDL audio device.

@ -1,83 +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_SDLMixer.h"
#include "AUD_SDLMixerFactory.h"
#include <SDL.h>
AUD_SDLMixer::AUD_SDLMixer()
{
m_factory = NULL;
}
AUD_SDLMixer::~AUD_SDLMixer()
{
if(m_factory)
{
delete m_factory; AUD_DELETE("factory")
}
}
AUD_IReader* AUD_SDLMixer::prepare(AUD_IReader* reader)
{
m_factory->setReader(reader);
return m_factory->createReader();
}
void AUD_SDLMixer::setSpecs(AUD_Specs specs)
{
m_samplesize = AUD_SAMPLE_SIZE(specs);
if(m_factory)
{
delete m_factory; AUD_DELETE("factory")
}
m_factory = new AUD_SDLMixerFactory(specs); AUD_NEW("factory")
}
void AUD_SDLMixer::add(sample_t* buffer, AUD_Specs specs, int length,
float volume)
{
AUD_SDLMixerBuffer buf;
buf.buffer = buffer;
buf.length = length;
buf.volume = volume;
m_buffers.push_back(buf);
}
void AUD_SDLMixer::superpose(sample_t* buffer, int length, float volume)
{
AUD_SDLMixerBuffer buf;
while(!m_buffers.empty())
{
buf = m_buffers.front();
m_buffers.pop_front();
SDL_MixAudio((Uint8*)buffer,
(Uint8*)buf.buffer,
buf.length * m_samplesize,
(int)(SDL_MIX_MAXVOLUME * volume * buf.volume));
}
}

@ -1,216 +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_SDLMixerReader.h"
#include "AUD_Buffer.h"
#include <cstring>
inline Uint16 AUD_TO_SDL(AUD_SampleFormat format)
{
// SDL only supports 8 and 16 bit audio
switch(format)
{
case AUD_FORMAT_U8:
return AUDIO_U8;
case AUD_FORMAT_S16:
return AUDIO_S16SYS;
default:
AUD_THROW(AUD_ERROR_SDL);
}
}
// greatest common divisor
inline int gcd(int a, int b)
{
int c;
// make sure a is the bigger
if(b > a)
{
c = b;
b = a;
a = c;
}
// greetings from Euclides
while(b != 0)
{
c = a % b;
a = b;
b = c;
}
return a;
}
AUD_SDLMixerReader::AUD_SDLMixerReader(AUD_IReader* reader,
AUD_Specs specs)
{
if(reader == NULL)
AUD_THROW(AUD_ERROR_READER);
m_reader = reader;
m_tspecs = specs;
m_sspecs = reader->getSpecs();
try
{
// SDL only supports 8 and 16 bit sample formats
if(SDL_BuildAudioCVT(&m_cvt,
AUD_TO_SDL(m_sspecs.format),
m_sspecs.channels,
m_sspecs.rate,
AUD_TO_SDL(specs.format),
specs.channels,
specs.rate) == -1)
AUD_THROW(AUD_ERROR_SDL);
}
catch(AUD_Exception)
{
delete m_reader; AUD_DELETE("reader")
throw;
}
m_eor = false;
m_rsposition = 0;
m_rssize = 0;
m_ssize = m_sspecs.rate / gcd(specs.rate, m_sspecs.rate);
m_tsize = m_tspecs.rate * m_ssize / m_sspecs.rate;
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_rsbuffer = new AUD_Buffer(); AUD_NEW("buffer")
}
AUD_SDLMixerReader::~AUD_SDLMixerReader()
{
delete m_reader; AUD_DELETE("reader")
delete m_buffer; AUD_DELETE("buffer")
delete m_rsbuffer; AUD_DELETE("buffer")
}
bool AUD_SDLMixerReader::isSeekable()
{
return m_reader->isSeekable();
}
void AUD_SDLMixerReader::seek(int position)
{
m_reader->seek(position * m_ssize / m_tsize);
m_eor = false;
}
int AUD_SDLMixerReader::getLength()
{
return m_reader->getLength() * m_tsize / m_ssize;
}
int AUD_SDLMixerReader::getPosition()
{
return m_reader->getPosition() * m_tsize / m_ssize;
}
AUD_Specs AUD_SDLMixerReader::getSpecs()
{
return m_tspecs;
}
AUD_ReaderType AUD_SDLMixerReader::getType()
{
return m_reader->getType();
}
bool AUD_SDLMixerReader::notify(AUD_Message &message)
{
return m_reader->notify(message);
}
void AUD_SDLMixerReader::read(int & length, sample_t* & buffer)
{
// sample count for the target buffer without getting a shift
int tns = length + m_tsize - length % m_tsize;
// sample count for the source buffer without getting a shift
int sns = tns * m_ssize / m_tsize;
// target sample size
int tss = AUD_SAMPLE_SIZE(m_tspecs);
// source sample size
int sss = AUD_SAMPLE_SIZE(m_sspecs);
// input is output buffer
int buf_size = AUD_MAX(tns*tss, sns*sss);
// resize if necessary
if(m_rsbuffer->getSize() < buf_size)
m_rsbuffer->resize(buf_size, true);
if(m_buffer->getSize() < length*tss)
m_buffer->resize(length*tss);
buffer = m_buffer->getBuffer();
int size;
int index = 0;
sample_t* buf;
while(index < length)
{
if(m_rsposition == m_rssize)
{
// no more data
if(m_eor)
length = index;
// mix
else
{
// read from source
size = sns;
m_reader->read(size, buf);
// prepare
m_cvt.buf = m_rsbuffer->getBuffer();
m_cvt.len = size*sss;
memcpy(m_cvt.buf, buf, size*sss);
// convert
SDL_ConvertAudio(&m_cvt);
// end of reader
if(size < sns)
m_eor = true;
m_rsposition = 0;
m_rssize = size * m_tsize / m_ssize;
}
}
// size to copy
size = AUD_MIN(m_rssize-m_rsposition, length-index);
// copy
memcpy(m_buffer->getBuffer() + index * tss,
m_rsbuffer->getBuffer() + m_rsposition * tss,
size*tss);
m_rsposition += size;
index += size;
}
}

@ -1,128 +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_SDLMIXERREADER
#define AUD_SDLMIXERREADER
#include "AUD_IReader.h"
class AUD_Buffer;
#include <SDL.h>
/**
* This class mixes a sound source with help of the SDL library.
* Unfortunately SDL is only capable of 8 and 16 bit audio, mono and stereo, as
* well as resampling only 2^n sample rate relationships where n is a natural
* number.
* \warning Although SDL can only resample 2^n sample rate relationships, this
* class doesn't check for compliance, so in case of other factors,
* the behaviour is undefined.
*/
class AUD_SDLMixerReader : public AUD_IReader
{
private:
/**
* The reader that is being mixed.
*/
AUD_IReader* m_reader;
/**
* The current reading position in the resampling buffer.
*/
int m_rsposition;
/**
* The count of mixed samples in the resampling buffer.
*/
int m_rssize;
/**
* The smallest count of source samples to get a fractionless resampling
* factor.
*/
int m_ssize;
/**
* The smallest count of target samples to get a fractionless resampling
* factor.
*/
int m_tsize;
/**
* The sound output buffer.
*/
AUD_Buffer *m_buffer;
/**
* The resampling buffer.
*/
AUD_Buffer *m_rsbuffer;
/**
* The target specification.
*/
AUD_Specs m_tspecs;
/**
* The sample specification of the source.
*/
AUD_Specs m_sspecs;
/**
* Saves whether the end of the source has been reached.
*/
bool m_eor;
/**
* The SDL_AudioCVT structure used for resampling.
*/
SDL_AudioCVT m_cvt;
public:
/**
* Creates a resampling reader.
* \param reader The reader to mix.
* \param specs The target specification.
* \exception AUD_Exception Thrown if the source specification cannot be
* mixed to the target specification or if the reader is
* NULL.
*/
AUD_SDLMixerReader(AUD_IReader* reader, AUD_Specs specs);
/**
* Destroys the reader.
*/
~AUD_SDLMixerReader();
virtual bool isSeekable();
virtual void seek(int position);
virtual int getLength();
virtual int getPosition();
virtual AUD_Specs getSpecs();
virtual AUD_ReaderType getType();
virtual bool notify(AUD_Message &message);
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_SDLMIXERREADER

@ -27,14 +27,14 @@
#include "AUD_SRCResampleReader.h"
AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IReader* reader,
AUD_Specs specs) :
AUD_DeviceSpecs specs) :
AUD_ResampleFactory(reader, specs) {}
AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IFactory* factory,
AUD_Specs specs) :
AUD_DeviceSpecs specs) :
AUD_ResampleFactory(factory, specs) {}
AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_Specs specs) :
AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_DeviceSpecs specs) :
AUD_ResampleFactory(specs) {}
AUD_IReader* AUD_SRCResampleFactory::createReader()
@ -45,7 +45,7 @@ AUD_IReader* AUD_SRCResampleFactory::createReader()
{
if(reader->getSpecs().rate != m_specs.rate)
{
reader = new AUD_SRCResampleReader(reader, m_specs);
reader = new AUD_SRCResampleReader(reader, m_specs.specs);
AUD_NEW("reader")
}
}

@ -31,14 +31,13 @@
/**
* This factory creates a resampling reader that uses libsamplerate for
* resampling.
* \note The format of the input must be float.
*/
class AUD_SRCResampleFactory : public AUD_ResampleFactory
{
public:
AUD_SRCResampleFactory(AUD_IReader* reader, AUD_Specs specs);
AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_Specs specs);
AUD_SRCResampleFactory(AUD_Specs specs);
AUD_SRCResampleFactory(AUD_IReader* reader, AUD_DeviceSpecs specs);
AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
AUD_SRCResampleFactory(AUD_DeviceSpecs specs);
virtual AUD_IReader* createReader();
};

@ -26,9 +26,9 @@
#include "AUD_SRCResampleReader.h"
#include "AUD_Buffer.h"
#include <math.h>
#include <cmath>
#include <cstring>
#include <stdio.h>
#include <cstdio>
static long src_callback(void *cb_data, float **data)
{
@ -41,15 +41,8 @@ AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader,
{
m_sspecs = reader->getSpecs();
if(m_sspecs.format != AUD_FORMAT_FLOAT32)
{
delete m_reader; AUD_DELETE("reader")
AUD_THROW(AUD_ERROR_READER);
}
m_tspecs = specs;
m_tspecs.channels = m_sspecs.channels;
m_tspecs.format = m_sspecs.format;
m_factor = (double)m_tspecs.rate / (double)m_sspecs.rate;
int error;
@ -71,9 +64,9 @@ AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader,
AUD_SRCResampleReader::~AUD_SRCResampleReader()
{
delete m_buffer; AUD_DELETE("buffer")
src_delete(m_src);
delete m_buffer; AUD_DELETE("buffer")
}
long AUD_SRCResampleReader::doCallback(float** data)
@ -83,7 +76,7 @@ long AUD_SRCResampleReader::doCallback(float** data)
m_reader->read(length, buffer);
*data = (float*)buffer;
*data = buffer;
return length;
}
@ -110,10 +103,12 @@ AUD_Specs AUD_SRCResampleReader::getSpecs()
void AUD_SRCResampleReader::read(int & length, sample_t* & buffer)
{
if(m_buffer->getSize() < length * m_tspecs.channels * 4)
m_buffer->resize(length * m_tspecs.channels * 4);
int size = length * AUD_SAMPLE_SIZE(m_tspecs);
if(m_buffer->getSize() < size)
m_buffer->resize(size);
buffer = m_buffer->getBuffer();
length = src_callback_read(m_src, m_factor, length, (float*)buffer);
length = src_callback_read(m_src, m_factor, length, buffer);
}

@ -32,13 +32,7 @@ class AUD_Buffer;
#include <samplerate.h>
/**
* This class mixes a sound source with help of the SDL library.
* Unfortunately SDL is only capable of 8 and 16 bit audio, mono and stereo, as
* well as resampling only 2^n sample rate relationships where n is a natural
* number.
* \warning Although SDL can only resample 2^n sample rate relationships, this
* class doesn't check for compliance, so in case of other factors,
* the behaviour is undefined.
* This resampling reader uses libsamplerate for resampling.
*/
class AUD_SRCResampleReader : public AUD_EffectReader
{

@ -34,26 +34,6 @@ extern "C" {
#include <libavformat/avformat.h>
}
// This function transforms a FFMPEG SampleFormat to our own sample format
static inline AUD_SampleFormat FFMPEG_TO_AUD(SampleFormat fmt)
{
switch(fmt)
{
case SAMPLE_FMT_U8:
return AUD_FORMAT_U8;
case SAMPLE_FMT_S16:
return AUD_FORMAT_S16;
case SAMPLE_FMT_S32:
return AUD_FORMAT_S32;
case SAMPLE_FMT_FLT:
return AUD_FORMAT_FLOAT32;
case SAMPLE_FMT_DBL:
return AUD_FORMAT_FLOAT64;
default:
return AUD_FORMAT_INVALID;
}
}
int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer)
{
// save packet parameters
@ -78,11 +58,11 @@ int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer)
// read samples from the packet
data_size = buf_size - buf_pos;
/*read_length = avcodec_decode_audio3(m_codecCtx,
(int16_t*)(buffer->getBuffer()+buf_pos),
(int16_t*)(((data_t*)buffer->getBuffer())+buf_pos),
&data_size,
packet);*/
read_length = avcodec_decode_audio2(m_codecCtx,
(int16_t*)(buffer->getBuffer()+buf_pos),
(int16_t*)(((data_t*)buffer->getBuffer())+buf_pos),
&data_size,
audio_pkg_data,
audio_pkg_size);
@ -101,10 +81,78 @@ int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer)
return buf_pos;
}
AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename)
void AUD_FFMPEGReader::init()
{
m_position = 0;
m_pkgbuf_left = 0;
if(av_find_stream_info(m_formatCtx)<0)
AUD_THROW(AUD_ERROR_FFMPEG);
// find audio stream and codec
m_stream = -1;
for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
if((m_formatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO)
&& (m_stream < 0))
{
m_stream=i;
break;
}
if(m_stream == -1)
AUD_THROW(AUD_ERROR_FFMPEG);
m_codecCtx = m_formatCtx->streams[m_stream]->codec;
// get a decoder and open it
AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id);
if(!aCodec)
AUD_THROW(AUD_ERROR_FFMPEG);
if(avcodec_open(m_codecCtx, aCodec)<0)
AUD_THROW(AUD_ERROR_FFMPEG);
// XXX this prints file information to stdout:
//dump_format(m_formatCtx, 0, NULL, 0);
m_specs.channels = (AUD_Channels) m_codecCtx->channels;
switch(m_codecCtx->sample_fmt)
{
case SAMPLE_FMT_U8:
m_convert = AUD_convert_u8_float;
m_specs.format = AUD_FORMAT_U8;
break;
case SAMPLE_FMT_S16:
m_convert = AUD_convert_s16_float;
m_specs.format = AUD_FORMAT_S16;
break;
case SAMPLE_FMT_S32:
m_convert = AUD_convert_s32_float;
m_specs.format = AUD_FORMAT_S32;
break;
case SAMPLE_FMT_FLT:
m_convert = AUD_convert_copy<float>;
m_specs.format = AUD_FORMAT_FLOAT32;
break;
case SAMPLE_FMT_DBL:
m_convert = AUD_convert_double_float;
m_specs.format = AUD_FORMAT_FLOAT64;
break;
default:
AUD_THROW(AUD_ERROR_FILE);
}
m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate;
// last but not least if there hasn't been any error, create the buffers
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_pkgbuf = new AUD_Buffer(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1);
AUD_NEW("buffer")
}
AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename)
{
m_byteiocontext = NULL;
// open file
@ -113,66 +161,28 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename)
try
{
if(av_find_stream_info(m_formatCtx)<0)
AUD_THROW(AUD_ERROR_FFMPEG);
// find audio stream and codec
m_stream = -1;
for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
if((m_formatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO)
&& (m_stream < 0))
{
m_stream=i;
break;
}
if(m_stream == -1)
AUD_THROW(AUD_ERROR_FFMPEG);
m_codecCtx = m_formatCtx->streams[m_stream]->codec;
// get a decoder and open it
AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id);
if(!aCodec)
AUD_THROW(AUD_ERROR_FFMPEG);
if(avcodec_open(m_codecCtx, aCodec)<0)
AUD_THROW(AUD_ERROR_FFMPEG);
// XXX this prints file information to stdout:
//dump_format(m_formatCtx, 0, filename, 0);
m_specs.channels = (AUD_Channels) m_codecCtx->channels;
m_specs.format = FFMPEG_TO_AUD(m_codecCtx->sample_fmt);
m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate;
init();
}
catch(AUD_Exception)
{
av_close_input_file(m_formatCtx);
throw;
}
// last but not least if there hasn't been any error, create the buffers
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_pkgbuf = new AUD_Buffer(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1);
AUD_NEW("buffer")
}
AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer)
{
m_position = 0;
m_pkgbuf_left = 0;
m_byteiocontext = (ByteIOContext*)av_mallocz(sizeof(ByteIOContext));
AUD_NEW("byteiocontext")
m_membuffer = buffer;
if(init_put_byte(m_byteiocontext, buffer.get()->getBuffer(), buffer.get()->getSize(), 0,
NULL, NULL, NULL, NULL) != 0)
if(init_put_byte(m_byteiocontext, (data_t*)buffer.get()->getBuffer(),
buffer.get()->getSize(), 0, NULL, NULL, NULL, NULL) != 0)
AUD_THROW(AUD_ERROR_FILE);
AVProbeData probe_data;
probe_data.filename = "";
probe_data.buf = buffer.get()->getBuffer();
probe_data.buf = (data_t*)buffer.get()->getBuffer();
probe_data.buf_size = buffer.get()->getSize();
AVInputFormat* fmt = av_probe_input_format(&probe_data, 1);
@ -182,38 +192,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer)
try
{
if(av_find_stream_info(m_formatCtx)<0)
AUD_THROW(AUD_ERROR_FFMPEG);
// find audio stream and codec
m_stream = -1;
for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
if((m_formatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO)
&& (m_stream < 0))
{
m_stream=i;
break;
}
if(m_stream == -1)
AUD_THROW(AUD_ERROR_FFMPEG);
m_codecCtx = m_formatCtx->streams[m_stream]->codec;
// get a decoder and open it
AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id);
if(!aCodec)
AUD_THROW(AUD_ERROR_FFMPEG);
if(avcodec_open(m_codecCtx, aCodec)<0)
AUD_THROW(AUD_ERROR_FFMPEG);
// XXX this prints stream information to stdout:
//dump_format(m_formatCtx, 0, NULL, 0);
m_specs.channels = (AUD_Channels) m_codecCtx->channels;
m_specs.format = FFMPEG_TO_AUD(m_codecCtx->sample_fmt);
m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate;
init();
}
catch(AUD_Exception)
{
@ -221,11 +200,6 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer)
av_free(m_byteiocontext); AUD_DELETE("byteiocontext")
throw;
}
// last but not least if there hasn't been any error, create the buffers
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_pkgbuf = new AUD_Buffer(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1);
AUD_NEW("buffer")
}
AUD_FFMPEGReader::~AUD_FFMPEGReader()
@ -316,7 +290,7 @@ int AUD_FFMPEGReader::getPosition()
AUD_Specs AUD_FFMPEGReader::getSpecs()
{
return m_specs;
return m_specs.specs;
}
AUD_ReaderType AUD_FFMPEGReader::getType()
@ -336,11 +310,11 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
int data_size = 0;
int pkgbuf_pos;
int left = length;
int sample_size = AUD_SAMPLE_SIZE(m_specs);
int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs);
// resize output buffer if necessary
if(m_buffer->getSize() < length*sample_size)
m_buffer->resize(length*sample_size);
if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(m_specs))
m_buffer->resize(length * AUD_SAMPLE_SIZE(m_specs));
buffer = m_buffer->getBuffer();
pkgbuf_pos = m_pkgbuf_left;
@ -350,8 +324,9 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
if(pkgbuf_pos > 0)
{
data_size = AUD_MIN(pkgbuf_pos, left * sample_size);
memcpy(buffer, m_pkgbuf->getBuffer(), data_size);
buffer += data_size;
m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(),
data_size / AUD_FORMAT_SIZE(m_specs.format));
buffer += data_size / AUD_FORMAT_SIZE(m_specs.format);
left -= data_size/sample_size;
}
@ -366,8 +341,9 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
// copy to output buffer
data_size = AUD_MIN(pkgbuf_pos, left * sample_size);
memcpy(buffer, m_pkgbuf->getBuffer(), data_size);
buffer += data_size;
m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(),
data_size / AUD_FORMAT_SIZE(m_specs.format));
buffer += data_size / AUD_FORMAT_SIZE(m_specs.format);
left -= data_size/sample_size;
}
av_free_packet(&packet);
@ -376,7 +352,8 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
if(pkgbuf_pos > data_size)
{
m_pkgbuf_left = pkgbuf_pos-data_size;
memmove(m_pkgbuf->getBuffer(), m_pkgbuf->getBuffer()+data_size,
memmove(m_pkgbuf->getBuffer(),
((data_t*)m_pkgbuf->getBuffer())+data_size,
pkgbuf_pos-data_size);
}

@ -26,6 +26,7 @@
#ifndef AUD_FFMPEGREADER
#define AUD_FFMPEGREADER
#include "AUD_ConverterFunctions.h"
#include "AUD_IReader.h"
#include "AUD_Reference.h"
class AUD_Buffer;
@ -59,7 +60,7 @@ private:
/**
* The specification of the audio data.
*/
AUD_Specs m_specs;
AUD_DeviceSpecs m_specs;
/**
* The buffer for package reading.
@ -91,6 +92,11 @@ private:
*/
int m_stream;
/**
* Converter function.
*/
AUD_convert_f m_convert;
/**
* The memory file to read from, only saved to keep the buffer alive.
*/
@ -104,6 +110,11 @@ private:
*/
int decode(AVPacket* packet, AUD_Buffer* buffer);
/**
* Initializes the object.
*/
void init();
public:
/**
* Creates a new reader.

@ -63,16 +63,8 @@ AUD_IReader* AUD_BandPassFactory::createReader()
if(reader != 0)
{
if(reader->getSpecs().format == AUD_FORMAT_FLOAT32)
{
reader = new AUD_BandPassReader(reader, m_low, m_high);
AUD_NEW("reader")
}
else
{
delete reader; AUD_DELETE("reader")
return 0;
}
reader = new AUD_BandPassReader(reader, m_low, m_high);
AUD_NEW("reader")
}
return reader;

@ -77,7 +77,6 @@ void AUD_BandPassReader::read(int & length, sample_t* & buffer)
}
m_length = length;
printf("WINDOW: %d\n", m_length);
if(m_length * sizeof(double) > m_in->getSize())
{
@ -95,16 +94,15 @@ void AUD_BandPassReader::read(int & length, sample_t* & buffer)
FFTW_ESTIMATE);
}
float* source = (float*) buffer;
double* target = (double*) m_in->getBuffer();
float* target2 = (float*) m_buffer->getBuffer();
sample_t* target2 = m_buffer->getBuffer();
fftw_complex* complex = (fftw_complex*) m_out->getBuffer();
float frequency;
for(int channel = 0; channel < specs.channels; channel++)
{
for(int i = 0; i < m_length; i++)
target[i] = source[i * specs.channels + channel];
target[i] = buffer[i * specs.channels + channel];
fftw_execute(m_forward);

@ -27,14 +27,14 @@
#include "AUD_Space.h"
#include <cstring>
#include <stdlib.h>
#include <cstdlib>
#define AUD_ALIGN(a) (a + 16 - ((long)a & 15))
AUD_Buffer::AUD_Buffer(int size)
{
m_size = size;
m_buffer = (sample_t*) malloc(size+16); AUD_NEW("buffer")
m_buffer = (data_t*) malloc(size+16); AUD_NEW("buffer")
}
AUD_Buffer::~AUD_Buffer()
@ -44,7 +44,7 @@ AUD_Buffer::~AUD_Buffer()
sample_t* AUD_Buffer::getBuffer()
{
return AUD_ALIGN(m_buffer);
return (sample_t*) AUD_ALIGN(m_buffer);
}
int AUD_Buffer::getSize()
@ -54,7 +54,7 @@ int AUD_Buffer::getSize()
void AUD_Buffer::resize(int size, bool keep)
{
sample_t* buffer = (sample_t*) malloc(size+16); AUD_NEW("buffer")
data_t* buffer = (data_t*) malloc(size+16); AUD_NEW("buffer")
// copy old data over if wanted
if(keep)

@ -39,7 +39,7 @@ private:
int m_size;
/// The pointer to the buffer memory.
sample_t* m_buffer;
data_t* m_buffer;
public:
/**

@ -79,11 +79,11 @@ void AUD_BufferReader::read(int & length, sample_t* & buffer)
{
int sample_size = AUD_SAMPLE_SIZE(m_specs);
buffer = m_buffer.get()->getBuffer()+m_position*sample_size;
buffer = m_buffer.get()->getBuffer() + m_position * m_specs.channels;
// in case the end of the buffer is reached
if(m_buffer.get()->getSize() < (m_position+length)*sample_size)
length = m_buffer.get()->getSize()/sample_size-m_position;
if(m_buffer.get()->getSize() < (m_position + length) * sample_size)
length = m_buffer.get()->getSize() / sample_size - m_position;
if(length < 0)
length = 0;

@ -23,6 +23,9 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#include <cstdlib>
#include <cstring>
#include "AUD_NULLDevice.h"
#include "AUD_I3DDevice.h"
#include "AUD_FileFactory.h"
@ -32,13 +35,18 @@
#include "AUD_PingPongFactory.h"
#include "AUD_LoopFactory.h"
#include "AUD_RectifyFactory.h"
#include "AUD_EnvelopeFactory.h"
#include "AUD_LinearResampleFactory.h"
#include "AUD_LowpassFactory.h"
#include "AUD_HighpassFactory.h"
#include "AUD_ChannelMapperFactory.h"
#include "AUD_Buffer.h"
#include "AUD_ReadDevice.h"
#include "AUD_SourceCaps.h"
#include "AUD_IReader.h"
#ifdef WITH_SDL
#include "AUD_SDLDevice.h"
#include "AUD_FloatMixer.h"
#endif
#ifdef WITH_OPENAL
@ -55,7 +63,7 @@ extern "C" {
}
#endif
#include <assert.h>
#include <cassert>
typedef AUD_IFactory AUD_Sound;
typedef AUD_ReadDevice AUD_Device;
@ -71,7 +79,7 @@ static AUD_IDevice* AUD_device = NULL;
static int AUD_available_devices[4];
static AUD_I3DDevice* AUD_3ddevice = NULL;
int AUD_init(AUD_DeviceType device, AUD_Specs specs, int buffersize)
int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize)
{
#ifdef WITH_FFMPEG
av_register_all();
@ -90,12 +98,8 @@ int AUD_init(AUD_DeviceType device, AUD_Specs specs, int buffersize)
break;
#ifdef WITH_SDL
case AUD_SDL_DEVICE:
{
dev = new AUD_SDLDevice(specs, buffersize);
AUD_FloatMixer* mixer = new AUD_FloatMixer();
((AUD_SDLDevice*)dev)->setMixer(mixer);
break;
}
dev = new AUD_SDLDevice(specs, buffersize);
break;
#endif
#ifdef WITH_OPENAL
case AUD_OPENAL_DEVICE:
@ -177,7 +181,6 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
else
{
info.specs.channels = AUD_CHANNELS_INVALID;
info.specs.format = AUD_FORMAT_INVALID;
info.specs.rate = AUD_RATE_INVALID;
info.length = 0.0;
}
@ -519,7 +522,7 @@ int AUD_setSoundPitch(AUD_Handle* handle, float pitch)
return false;
}
AUD_Device* AUD_openReadDevice(AUD_Specs specs)
AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs)
{
try
{
@ -578,7 +581,7 @@ int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Handle* handle,
return false;
}
int AUD_readDevice(AUD_Device* device, sample_t* buffer, int length)
int AUD_readDevice(AUD_Device* device, data_t* buffer, int length)
{
assert(device);
assert(buffer);
@ -605,3 +608,43 @@ void AUD_closeReadDevice(AUD_Device* device)
{
}
}
float* AUD_readSoundBuffer(const char* filename, float low, float high,
float attack, float release, float threshold,
int samplerate, int* length)
{
AUD_Buffer buffer;
AUD_DeviceSpecs specs;
specs.channels = AUD_CHANNELS_MONO;
specs.rate = (AUD_SampleRate)samplerate;
AUD_FileFactory file(filename);
AUD_ChannelMapperFactory mapper(&file, specs);
AUD_LowpassFactory lowpass(&mapper, high);
AUD_HighpassFactory highpass(&lowpass, low);
AUD_EnvelopeFactory envelope(&highpass, attack, release, threshold, 0.1f);
AUD_LinearResampleFactory resampler(&envelope, specs);
AUD_IReader* reader = resampler.createReader();
if(reader == NULL)
return NULL;
int len;
int position = 0;
sample_t* readbuffer;
do
{
len = samplerate;
buffer.resize((position + len) * sizeof(float), true);
reader->read(len, readbuffer);
memcpy(buffer.getBuffer() + position, readbuffer, len * sizeof(float));
position += len;
} while(len != 0);
delete reader;
float* result = (float*)malloc(position * sizeof(float));
memcpy(result, buffer.getBuffer(), position * sizeof(float));
*length = position;
return result;
}

@ -59,7 +59,7 @@ typedef struct
* \param buffersize The buffersize for the device.
* \return Whether the device has been initialized.
*/
extern int AUD_init(AUD_DeviceType device, AUD_Specs specs, int buffersize);
extern int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize);
/**
* Returns a integer list with available sound devices. The last one is always
@ -304,7 +304,7 @@ extern int AUD_setSoundPitch(AUD_Handle* handle, float pitch);
* \param specs The specification of the audio data.
* \return A device handle.
*/
extern AUD_Device* AUD_openReadDevice(AUD_Specs specs);
extern AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs);
/**
* Sets the main volume of a device.
@ -342,7 +342,7 @@ extern int AUD_setDeviceSoundVolume(AUD_Device* device,
* played back currently, in that case the buffer is filled with
* silence.
*/
extern int AUD_readDevice(AUD_Device* device, sample_t* buffer, int length);
extern int AUD_readDevice(AUD_Device* device, data_t* buffer, int length);
/**
* Closes a read device.
@ -350,6 +350,14 @@ extern int AUD_readDevice(AUD_Device* device, sample_t* buffer, int length);
*/
extern void AUD_closeReadDevice(AUD_Device* device);
/**
* Reads a sound file into a newly created float buffer.
* The sound is therefore bandpassed, rectified and resampled.
*/
extern float* AUD_readSoundBuffer(const char* filename, float low, float high,
float attack, float release, float threshold,
int samplerate, int* length);
#ifdef __cplusplus
}
#endif

@ -29,20 +29,20 @@
#include <cstring>
AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IReader* reader,
AUD_Specs specs) :
AUD_DeviceSpecs specs) :
AUD_MixerFactory(reader, specs)
{
memset(m_mapping, 0, sizeof(m_mapping));
}
AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IFactory* factory,
AUD_Specs specs) :
AUD_DeviceSpecs specs) :
AUD_MixerFactory(factory, specs)
{
memset(m_mapping, 0, sizeof(m_mapping));
}
AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_Specs specs) :
AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_DeviceSpecs specs) :
AUD_MixerFactory(specs)
{
memset(m_mapping, 0, sizeof(m_mapping));

@ -41,9 +41,9 @@ private:
float **m_mapping[9];
public:
AUD_ChannelMapperFactory(AUD_IReader* reader, AUD_Specs specs);
AUD_ChannelMapperFactory(AUD_IFactory* factory, AUD_Specs specs);
AUD_ChannelMapperFactory(AUD_Specs specs);
AUD_ChannelMapperFactory(AUD_IReader* reader, AUD_DeviceSpecs specs);
AUD_ChannelMapperFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
AUD_ChannelMapperFactory(AUD_DeviceSpecs specs);
virtual ~AUD_ChannelMapperFactory();

@ -32,12 +32,6 @@ AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader,
{
m_specs = reader->getSpecs();
if(m_specs.format != AUD_FORMAT_FLOAT32)
{
delete m_reader; AUD_DELETE("reader")
AUD_THROW(AUD_ERROR_READER);
}
int channels = -1;
m_rch = m_specs.channels;
while(mapping[++channels] != 0);
@ -89,9 +83,9 @@ void AUD_ChannelMapperReader::read(int & length, sample_t* & buffer)
if(m_buffer->getSize() < length * 4 * channels)
m_buffer->resize(length * 4 * channels);
float* in = (float*)buffer;
float* out = (float*)m_buffer->getBuffer();
float sum;
sample_t* in = buffer;
sample_t* out = m_buffer->getBuffer();
sample_t sum;
for(int i = 0; i < length; i++)
{

@ -27,14 +27,14 @@
#include "AUD_ConverterReader.h"
AUD_ConverterFactory::AUD_ConverterFactory(AUD_IReader* reader,
AUD_Specs specs) :
AUD_DeviceSpecs specs) :
AUD_MixerFactory(reader, specs) {}
AUD_ConverterFactory::AUD_ConverterFactory(AUD_IFactory* factory,
AUD_Specs specs) :
AUD_DeviceSpecs specs) :
AUD_MixerFactory(factory, specs) {}
AUD_ConverterFactory::AUD_ConverterFactory(AUD_Specs specs) :
AUD_ConverterFactory::AUD_ConverterFactory(AUD_DeviceSpecs specs) :
AUD_MixerFactory(specs) {}
AUD_IReader* AUD_ConverterFactory::createReader()
@ -43,7 +43,7 @@ AUD_IReader* AUD_ConverterFactory::createReader()
if(reader != 0)
{
if(reader->getSpecs().format != m_specs.format)
if(m_specs.format != AUD_FORMAT_FLOAT32)
{
reader = new AUD_ConverterReader(reader, m_specs);
AUD_NEW("reader")

@ -35,9 +35,9 @@
class AUD_ConverterFactory : public AUD_MixerFactory
{
public:
AUD_ConverterFactory(AUD_IReader* reader, AUD_Specs specs);
AUD_ConverterFactory(AUD_IFactory* factory, AUD_Specs specs);
AUD_ConverterFactory(AUD_Specs specs);
AUD_ConverterFactory(AUD_IReader* reader, AUD_DeviceSpecs specs);
AUD_ConverterFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
AUD_ConverterFactory(AUD_DeviceSpecs specs);
virtual AUD_IReader* createReader();
};

@ -36,14 +36,14 @@
#define AUD_FLT_MAX 1.0
#define AUD_FLT_MIN -1.0
void AUD_convert_u8_s16(sample_t* target, sample_t* source, int length)
void AUD_convert_u8_s16(data_t* target, data_t* source, int length)
{
int16_t* t = (int16_t*) target;
for(int i = 0; i < length; i++)
t[i] = (((int16_t)source[i]) - AUD_U8_0) << 8;
}
void AUD_convert_u8_s24_be(sample_t* target, sample_t* source, int length)
void AUD_convert_u8_s24_be(data_t* target, data_t* source, int length)
{
for(int i = 0; i < length; i++)
{
@ -53,7 +53,7 @@ void AUD_convert_u8_s24_be(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_u8_s24_le(sample_t* target, sample_t* source, int length)
void AUD_convert_u8_s24_le(data_t* target, data_t* source, int length)
{
for(int i = 0; i < length; i++)
{
@ -63,35 +63,35 @@ void AUD_convert_u8_s24_le(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_u8_s32(sample_t* target, sample_t* source, int length)
void AUD_convert_u8_s32(data_t* target, data_t* source, int length)
{
int32_t* t = (int32_t*) target;
for(int i = 0; i < length; i++)
t[i] = (((int32_t)source[i]) - AUD_U8_0) << 24;
}
void AUD_convert_u8_float(sample_t* target, sample_t* source, int length)
void AUD_convert_u8_float(data_t* target, data_t* source, int length)
{
float* t = (float*) target;
for(int i = 0; i < length; i++)
t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((float)AUD_U8_0);
}
void AUD_convert_u8_double(sample_t* target, sample_t* source, int length)
void AUD_convert_u8_double(data_t* target, data_t* source, int length)
{
double* t = (double*) target;
for(int i = 0; i < length; i++)
t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((double)AUD_U8_0);
}
void AUD_convert_s16_u8(sample_t* target, sample_t* source, int length)
void AUD_convert_s16_u8(data_t* target, data_t* source, int length)
{
int16_t* s = (int16_t*) source;
for(int i = 0; i < length; i++)
target[i] = (unsigned char)((s[i] >> 8) + AUD_U8_0);
}
void AUD_convert_s16_s24_be(sample_t* target, sample_t* source, int length)
void AUD_convert_s16_s24_be(data_t* target, data_t* source, int length)
{
int16_t* s = (int16_t*) source;
for(int i = 0; i < length; i++)
@ -102,7 +102,7 @@ void AUD_convert_s16_s24_be(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_s16_s24_le(sample_t* target, sample_t* source, int length)
void AUD_convert_s16_s24_le(data_t* target, data_t* source, int length)
{
int16_t* s = (int16_t*) source;
for(int i = 0; i < length; i++)
@ -113,7 +113,7 @@ void AUD_convert_s16_s24_le(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_s16_s32(sample_t* target, sample_t* source, int length)
void AUD_convert_s16_s32(data_t* target, data_t* source, int length)
{
int16_t* s = (int16_t*) source;
int32_t* t = (int32_t*) target;
@ -121,7 +121,7 @@ void AUD_convert_s16_s32(sample_t* target, sample_t* source, int length)
t[i] = ((int32_t)s[i]) << 16;
}
void AUD_convert_s16_float(sample_t* target, sample_t* source, int length)
void AUD_convert_s16_float(data_t* target, data_t* source, int length)
{
int16_t* s = (int16_t*) source;
float* t = (float*) target;
@ -129,7 +129,7 @@ void AUD_convert_s16_float(sample_t* target, sample_t* source, int length)
t[i] = s[i] / AUD_S16_FLT;
}
void AUD_convert_s16_double(sample_t* target, sample_t* source, int length)
void AUD_convert_s16_double(data_t* target, data_t* source, int length)
{
int16_t* s = (int16_t*) source;
double* t = (double*) target;
@ -137,52 +137,52 @@ void AUD_convert_s16_double(sample_t* target, sample_t* source, int length)
t[i] = s[i] / AUD_S16_FLT;
}
void AUD_convert_s24_u8_be(sample_t* target, sample_t* source, int length)
void AUD_convert_s24_u8_be(data_t* target, data_t* source, int length)
{
for(int i = 0; i < length; i++)
target[i] = source[i*3] ^ AUD_U8_0;
}
void AUD_convert_s24_u8_le(sample_t* target, sample_t* source, int length)
void AUD_convert_s24_u8_le(data_t* target, data_t* source, int length)
{
for(int i = 0; i < length; i++)
target[i] = source[i*3+2] ^ AUD_U8_0;
}
void AUD_convert_s24_s16_be(sample_t* target, sample_t* source, int length)
void AUD_convert_s24_s16_be(data_t* target, data_t* source, int length)
{
int16_t* t = (int16_t*) target;
for(int i = 0; i < length; i++)
t[i] = source[i*3] << 8 | source[i*3+1];
}
void AUD_convert_s24_s16_le(sample_t* target, sample_t* source, int length)
void AUD_convert_s24_s16_le(data_t* target, data_t* source, int length)
{
int16_t* t = (int16_t*) target;
for(int i = 0; i < length; i++)
t[i] = source[i*3+2] << 8 | source[i*3+1];
}
void AUD_convert_s24_s24(sample_t* target, sample_t* source, int length)
void AUD_convert_s24_s24(data_t* target, data_t* source, int length)
{
memcpy(target, source, length * 3);
}
void AUD_convert_s24_s32_be(sample_t* target, sample_t* source, int length)
void AUD_convert_s24_s32_be(data_t* target, data_t* source, int length)
{
int32_t* t = (int32_t*) target;
for(int i = 0; i < length; i++)
t[i] = source[i*3] << 24 | source[i*3+1] << 16 | source[i*3+2] << 8;
}
void AUD_convert_s24_s32_le(sample_t* target, sample_t* source, int length)
void AUD_convert_s24_s32_le(data_t* target, data_t* source, int length)
{
int32_t* t = (int32_t*) target;
for(int i = 0; i < length; i++)
t[i] = source[i*3+2] << 24 | source[i*3+1] << 16 | source[i*3] << 8;
}
void AUD_convert_s24_float_be(sample_t* target, sample_t* source, int length)
void AUD_convert_s24_float_be(data_t* target, data_t* source, int length)
{
float* t = (float*) target;
int32_t s;
@ -193,7 +193,7 @@ void AUD_convert_s24_float_be(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_s24_float_le(sample_t* target, sample_t* source, int length)
void AUD_convert_s24_float_le(data_t* target, data_t* source, int length)
{
float* t = (float*) target;
int32_t s;
@ -204,7 +204,7 @@ void AUD_convert_s24_float_le(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_s24_double_be(sample_t* target, sample_t* source, int length)
void AUD_convert_s24_double_be(data_t* target, data_t* source, int length)
{
double* t = (double*) target;
int32_t s;
@ -215,7 +215,7 @@ void AUD_convert_s24_double_be(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_s24_double_le(sample_t* target, sample_t* source, int length)
void AUD_convert_s24_double_le(data_t* target, data_t* source, int length)
{
double* t = (double*) target;
int32_t s;
@ -226,14 +226,14 @@ void AUD_convert_s24_double_le(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_s32_u8(sample_t* target, sample_t* source, int length)
void AUD_convert_s32_u8(data_t* target, data_t* source, int length)
{
int16_t* s = (int16_t*) source;
for(int i = 0; i < length; i++)
target[i] = (unsigned char)((s[i] >> 24) + AUD_U8_0);
}
void AUD_convert_s32_s16(sample_t* target, sample_t* source, int length)
void AUD_convert_s32_s16(data_t* target, data_t* source, int length)
{
int16_t* t = (int16_t*) target;
int32_t* s = (int32_t*) source;
@ -241,7 +241,7 @@ void AUD_convert_s32_s16(sample_t* target, sample_t* source, int length)
t[i] = s[i] >> 16;
}
void AUD_convert_s32_s24_be(sample_t* target, sample_t* source, int length)
void AUD_convert_s32_s24_be(data_t* target, data_t* source, int length)
{
int32_t* s = (int32_t*) source;
for(int i = 0; i < length; i++)
@ -252,7 +252,7 @@ void AUD_convert_s32_s24_be(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_s32_s24_le(sample_t* target, sample_t* source, int length)
void AUD_convert_s32_s24_le(data_t* target, data_t* source, int length)
{
int16_t* s = (int16_t*) source;
for(int i = 0; i < length; i++)
@ -263,7 +263,7 @@ void AUD_convert_s32_s24_le(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_s32_float(sample_t* target, sample_t* source, int length)
void AUD_convert_s32_float(data_t* target, data_t* source, int length)
{
int32_t* s = (int32_t*) source;
float* t = (float*) target;
@ -271,7 +271,7 @@ void AUD_convert_s32_float(sample_t* target, sample_t* source, int length)
t[i] = s[i] / AUD_S32_FLT;
}
void AUD_convert_s32_double(sample_t* target, sample_t* source, int length)
void AUD_convert_s32_double(data_t* target, data_t* source, int length)
{
int32_t* s = (int32_t*) source;
double* t = (double*) target;
@ -279,7 +279,7 @@ void AUD_convert_s32_double(sample_t* target, sample_t* source, int length)
t[i] = s[i] / AUD_S32_FLT;
}
void AUD_convert_float_u8(sample_t* target, sample_t* source, int length)
void AUD_convert_float_u8(data_t* target, data_t* source, int length)
{
float* s = (float*) source;
float t;
@ -295,7 +295,7 @@ void AUD_convert_float_u8(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_float_s16(sample_t* target, sample_t* source, int length)
void AUD_convert_float_s16(data_t* target, data_t* source, int length)
{
int16_t* t = (int16_t*) target;
float* s = (float*) source;
@ -310,7 +310,7 @@ void AUD_convert_float_s16(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_float_s24_be(sample_t* target, sample_t* source, int length)
void AUD_convert_float_s24_be(data_t* target, data_t* source, int length)
{
int32_t t;
float* s = (float*) source;
@ -328,7 +328,7 @@ void AUD_convert_float_s24_be(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_float_s24_le(sample_t* target, sample_t* source, int length)
void AUD_convert_float_s24_le(data_t* target, data_t* source, int length)
{
int32_t t;
float* s = (float*) source;
@ -346,7 +346,7 @@ void AUD_convert_float_s24_le(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_float_s32(sample_t* target, sample_t* source, int length)
void AUD_convert_float_s32(data_t* target, data_t* source, int length)
{
int32_t* t = (int32_t*) target;
float* s = (float*) source;
@ -361,7 +361,7 @@ void AUD_convert_float_s32(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_float_double(sample_t* target, sample_t* source, int length)
void AUD_convert_float_double(data_t* target, data_t* source, int length)
{
float* s = (float*) source;
double* t = (double*) target;
@ -369,7 +369,7 @@ void AUD_convert_float_double(sample_t* target, sample_t* source, int length)
t[i] = s[i];
}
void AUD_convert_double_u8(sample_t* target, sample_t* source, int length)
void AUD_convert_double_u8(data_t* target, data_t* source, int length)
{
double* s = (double*) source;
double t;
@ -385,7 +385,7 @@ void AUD_convert_double_u8(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_double_s16(sample_t* target, sample_t* source, int length)
void AUD_convert_double_s16(data_t* target, data_t* source, int length)
{
int16_t* t = (int16_t*) target;
double* s = (double*) source;
@ -400,7 +400,7 @@ void AUD_convert_double_s16(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_double_s24_be(sample_t* target, sample_t* source, int length)
void AUD_convert_double_s24_be(data_t* target, data_t* source, int length)
{
int32_t t;
double* s = (double*) source;
@ -418,7 +418,7 @@ void AUD_convert_double_s24_be(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_double_s24_le(sample_t* target, sample_t* source, int length)
void AUD_convert_double_s24_le(data_t* target, data_t* source, int length)
{
int32_t t;
double* s = (double*) source;
@ -436,7 +436,7 @@ void AUD_convert_double_s24_le(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_double_s32(sample_t* target, sample_t* source, int length)
void AUD_convert_double_s32(data_t* target, data_t* source, int length)
{
int32_t* t = (int32_t*) target;
double* s = (double*) source;
@ -451,92 +451,10 @@ void AUD_convert_double_s32(sample_t* target, sample_t* source, int length)
}
}
void AUD_convert_double_float(sample_t* target, sample_t* source, int length)
void AUD_convert_double_float(data_t* target, data_t* source, int length)
{
double* s = (double*) source;
float* t = (float*) target;
for(int i = 0; i < length; i++)
t[i] = s[i];
}
void AUD_volume_adjust_u8(sample_t* target, sample_t* source,
int count, float volume)
{
for(int i=0; i<count; i++)
target[i] = (unsigned char)((source[i]-0x0080) * volume + 0x80);
}
void AUD_volume_adjust_s24_le(sample_t* target, sample_t* source,
int count, float volume)
{
count *= 3;
int value;
for(int i=0; i<count; i+=3)
{
value = source[i+2] << 16 | source[i+1] << 8 | source[i];
value |= (((value & 0x800000) >> 23) * 255) << 24;
value *= volume;
target[i+2] = value >> 16;
target[i+1] = value >> 8;
target[i] = value;
}
}
void AUD_volume_adjust_s24_be(sample_t* target, sample_t* source,
int count, float volume)
{
count *= 3;
int value;
for(int i=0; i < count; i+=3)
{
value = source[i] << 16 | source[i+1] << 8 | source[i+2];
value |= (((value & 0x800000) >> 23) * 255) << 24;
value *= volume;
target[i] = value >> 16;
target[i+1] = value >> 8;
target[i+2] = value;
}
}
void AUD_rectify_u8(sample_t* target, sample_t* source, int count)
{
for(int i=0; i<count; i++)
target[i] = source[i] < 0x80 ? 0x0100 - source[i] : source[i];
}
void AUD_rectify_s24_le(sample_t* target, sample_t* source, int count)
{
count *= 3;
int value;
for(int i=0; i<count; i+=3)
{
value = source[i+2] << 16 | source[i+1] << 8 | source[i];
value |= (((value & 0x800000) >> 23) * 255) << 24;
if(value < 0)
value = -value;
target[i+2] = value >> 16;
target[i+1] = value >> 8;
target[i] = value;
}
}
void AUD_rectify_s24_be(sample_t* target, sample_t* source, int count)
{
count *= 3;
int value;
for(int i=0; i < count; i+=3)
{
value = source[i] << 16 | source[i+1] << 8 | source[i+2];
value |= (((value & 0x800000) >> 23) * 255) << 24;
if(value < 0)
value = -value;
target[i] = value >> 16;
target[i+1] = value >> 8;
target[i+2] = value;
}
}

@ -41,133 +41,94 @@
#include <stdint.h>
#endif
typedef void (*AUD_convert_f)(sample_t* target, sample_t* source, int length);
typedef void (*AUD_volume_adjust_f)(sample_t* target, sample_t* source,
int count, float volume);
typedef void (*AUD_rectify_f)(sample_t* target, sample_t* source, int count);
typedef void (*AUD_convert_f)(data_t* target, data_t* source, int length);
template <class T>
void AUD_convert_copy(sample_t* target, sample_t* source, int length)
void AUD_convert_copy(data_t* target, data_t* source, int length)
{
memcpy(target, source, length*sizeof(T));
}
void AUD_convert_u8_s16(sample_t* target, sample_t* source, int length);
void AUD_convert_u8_s16(data_t* target, data_t* source, int length);
void AUD_convert_u8_s24_be(sample_t* target, sample_t* source, int length);
void AUD_convert_u8_s24_be(data_t* target, data_t* source, int length);
void AUD_convert_u8_s24_le(sample_t* target, sample_t* source, int length);
void AUD_convert_u8_s24_le(data_t* target, data_t* source, int length);
void AUD_convert_u8_s32(sample_t* target, sample_t* source, int length);
void AUD_convert_u8_s32(data_t* target, data_t* source, int length);
void AUD_convert_u8_float(sample_t* target, sample_t* source, int length);
void AUD_convert_u8_float(data_t* target, data_t* source, int length);
void AUD_convert_u8_double(sample_t* target, sample_t* source, int length);
void AUD_convert_u8_double(data_t* target, data_t* source, int length);
void AUD_convert_s16_u8(sample_t* target, sample_t* source, int length);
void AUD_convert_s16_u8(data_t* target, data_t* source, int length);
void AUD_convert_s16_s24_be(sample_t* target, sample_t* source, int length);
void AUD_convert_s16_s24_be(data_t* target, data_t* source, int length);
void AUD_convert_s16_s24_le(sample_t* target, sample_t* source, int length);
void AUD_convert_s16_s24_le(data_t* target, data_t* source, int length);
void AUD_convert_s16_s32(sample_t* target, sample_t* source, int length);
void AUD_convert_s16_s32(data_t* target, data_t* source, int length);
void AUD_convert_s16_float(sample_t* target, sample_t* source, int length);
void AUD_convert_s16_float(data_t* target, data_t* source, int length);
void AUD_convert_s16_double(sample_t* target, sample_t* source, int length);
void AUD_convert_s16_double(data_t* target, data_t* source, int length);
void AUD_convert_s24_u8_be(sample_t* target, sample_t* source, int length);
void AUD_convert_s24_u8_be(data_t* target, data_t* source, int length);
void AUD_convert_s24_u8_le(sample_t* target, sample_t* source, int length);
void AUD_convert_s24_u8_le(data_t* target, data_t* source, int length);
void AUD_convert_s24_s16_be(sample_t* target, sample_t* source, int length);
void AUD_convert_s24_s16_be(data_t* target, data_t* source, int length);
void AUD_convert_s24_s16_le(sample_t* target, sample_t* source, int length);
void AUD_convert_s24_s16_le(data_t* target, data_t* source, int length);
void AUD_convert_s24_s24(sample_t* target, sample_t* source, int length);
void AUD_convert_s24_s24(data_t* target, data_t* source, int length);
void AUD_convert_s24_s32_be(sample_t* target, sample_t* source, int length);
void AUD_convert_s24_s32_be(data_t* target, data_t* source, int length);
void AUD_convert_s24_s32_le(sample_t* target, sample_t* source, int length);
void AUD_convert_s24_s32_le(data_t* target, data_t* source, int length);
void AUD_convert_s24_float_be(sample_t* target, sample_t* source, int length);
void AUD_convert_s24_float_be(data_t* target, data_t* source, int length);
void AUD_convert_s24_float_le(sample_t* target, sample_t* source, int length);
void AUD_convert_s24_float_le(data_t* target, data_t* source, int length);
void AUD_convert_s24_double_be(sample_t* target, sample_t* source, int length);
void AUD_convert_s24_double_be(data_t* target, data_t* source, int length);
void AUD_convert_s24_double_le(sample_t* target, sample_t* source, int length);
void AUD_convert_s24_double_le(data_t* target, data_t* source, int length);
void AUD_convert_s32_u8(sample_t* target, sample_t* source, int length);
void AUD_convert_s32_u8(data_t* target, data_t* source, int length);
void AUD_convert_s32_s16(sample_t* target, sample_t* source, int length);
void AUD_convert_s32_s16(data_t* target, data_t* source, int length);
void AUD_convert_s32_s24_be(sample_t* target, sample_t* source, int length);
void AUD_convert_s32_s24_be(data_t* target, data_t* source, int length);
void AUD_convert_s32_s24_le(sample_t* target, sample_t* source, int length);
void AUD_convert_s32_s24_le(data_t* target, data_t* source, int length);
void AUD_convert_s32_float(sample_t* target, sample_t* source, int length);
void AUD_convert_s32_float(data_t* target, data_t* source, int length);
void AUD_convert_s32_double(sample_t* target, sample_t* source, int length);
void AUD_convert_s32_double(data_t* target, data_t* source, int length);
void AUD_convert_float_u8(sample_t* target, sample_t* source, int length);
void AUD_convert_float_u8(data_t* target, data_t* source, int length);
void AUD_convert_float_s16(sample_t* target, sample_t* source, int length);
void AUD_convert_float_s16(data_t* target, data_t* source, int length);
void AUD_convert_float_s24_be(sample_t* target, sample_t* source, int length);
void AUD_convert_float_s24_be(data_t* target, data_t* source, int length);
void AUD_convert_float_s24_le(sample_t* target, sample_t* source, int length);
void AUD_convert_float_s24_le(data_t* target, data_t* source, int length);
void AUD_convert_float_s32(sample_t* target, sample_t* source, int length);
void AUD_convert_float_s32(data_t* target, data_t* source, int length);
void AUD_convert_float_double(sample_t* target, sample_t* source, int length);
void AUD_convert_float_double(data_t* target, data_t* source, int length);
void AUD_convert_double_u8(sample_t* target, sample_t* source, int length);
void AUD_convert_double_u8(data_t* target, data_t* source, int length);
void AUD_convert_double_s16(sample_t* target, sample_t* source, int length);
void AUD_convert_double_s16(data_t* target, data_t* source, int length);
void AUD_convert_double_s24_be(sample_t* target, sample_t* source, int length);
void AUD_convert_double_s24_be(data_t* target, data_t* source, int length);
void AUD_convert_double_s24_le(sample_t* target, sample_t* source, int length);
void AUD_convert_double_s24_le(data_t* target, data_t* source, int length);
void AUD_convert_double_s32(sample_t* target, sample_t* source, int length);
void AUD_convert_double_s32(data_t* target, data_t* source, int length);
void AUD_convert_double_float(sample_t* target, sample_t* source, int length);
template <class T>
void AUD_volume_adjust(sample_t* target, sample_t* source,
int count, float volume)
{
T* t = (T*)target;
T* s = (T*)source;
for(int i=0; i < count; i++)
t[i] = (T)(s[i] * volume);
}
void AUD_volume_adjust_u8(sample_t* target, sample_t* source,
int count, float volume);
void AUD_volume_adjust_s24_le(sample_t* target, sample_t* source,
int count, float volume);
void AUD_volume_adjust_s24_be(sample_t* target, sample_t* source,
int count, float volume);
template <class T>
void AUD_rectify(sample_t* target, sample_t* source, int count)
{
T* t = (T*)target;
T* s = (T*)source;
for(int i=0; i < count; i++)
t[i] = s[i] < 0 ? -s[i] : s[i];
}
void AUD_rectify_u8(sample_t* target, sample_t* source, int count);
void AUD_rectify_s24_le(sample_t* target, sample_t* source, int count);
void AUD_rectify_s24_be(sample_t* target, sample_t* source, int count);
void AUD_convert_double_float(data_t* target, data_t* source, int length);
#endif //AUD_CONVERTERFUNCTIONS

@ -26,205 +26,37 @@
#include "AUD_ConverterReader.h"
#include "AUD_Buffer.h"
AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader, AUD_Specs specs) :
AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader,
AUD_DeviceSpecs specs) :
AUD_EffectReader(reader)
{
m_specs = reader->getSpecs();
m_specs.specs = reader->getSpecs();
int bigendian = 1;
bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
switch(m_specs.format)
switch(specs.format)
{
case AUD_FORMAT_U8:
switch(specs.format)
{
case AUD_FORMAT_U8:
m_convert = AUD_convert_copy<unsigned char>;
break;
case AUD_FORMAT_S16:
m_convert = AUD_convert_u8_s16;
break;
case AUD_FORMAT_S24:
if(bigendian)
m_convert = AUD_convert_u8_s24_be;
else
m_convert = AUD_convert_u8_s24_le;
break;
case AUD_FORMAT_S32:
m_convert = AUD_convert_u8_s32;
break;
case AUD_FORMAT_FLOAT32:
m_convert = AUD_convert_u8_float;
break;
case AUD_FORMAT_FLOAT64:
m_convert = AUD_convert_u8_double;
break;
default:
break;
}
m_convert = AUD_convert_float_u8;
break;
case AUD_FORMAT_S16:
switch(specs.format)
{
case AUD_FORMAT_U8:
m_convert = AUD_convert_s16_u8;
break;
case AUD_FORMAT_S16:
m_convert = AUD_convert_copy<int16_t>;
break;
case AUD_FORMAT_S24:
if(bigendian)
m_convert = AUD_convert_s16_s24_be;
else
m_convert = AUD_convert_s16_s24_le;
break;
case AUD_FORMAT_S32:
m_convert = AUD_convert_s16_s32;
break;
case AUD_FORMAT_FLOAT32:
m_convert = AUD_convert_s16_float;
break;
case AUD_FORMAT_FLOAT64:
m_convert = AUD_convert_s16_double;
break;
default:
break;
}
m_convert = AUD_convert_float_s16;
break;
case AUD_FORMAT_S24:
if(bigendian)
switch(specs.format)
{
case AUD_FORMAT_U8:
m_convert = AUD_convert_u8_s24_be;
break;
case AUD_FORMAT_S16:
m_convert = AUD_convert_s16_s24_be;
break;
case AUD_FORMAT_S24:
m_convert = AUD_convert_s24_s24;
break;
case AUD_FORMAT_S32:
m_convert = AUD_convert_s32_s24_be;
break;
case AUD_FORMAT_FLOAT32:
m_convert = AUD_convert_float_s24_be;
break;
case AUD_FORMAT_FLOAT64:
m_convert = AUD_convert_double_s24_be;
break;
default:
break;
}
m_convert = AUD_convert_float_s24_be;
else
switch(specs.format)
{
case AUD_FORMAT_U8:
m_convert = AUD_convert_u8_s24_le;
break;
case AUD_FORMAT_S16:
m_convert = AUD_convert_s16_s24_le;
break;
case AUD_FORMAT_S24:
m_convert = AUD_convert_s24_s24;
break;
case AUD_FORMAT_S32:
m_convert = AUD_convert_s32_s24_le;
break;
case AUD_FORMAT_FLOAT32:
m_convert = AUD_convert_float_s24_le;
break;
case AUD_FORMAT_FLOAT64:
m_convert = AUD_convert_double_s24_le;
break;
default:
break;
}
m_convert = AUD_convert_float_s24_le;
break;
case AUD_FORMAT_S32:
switch(specs.format)
{
case AUD_FORMAT_U8:
m_convert = AUD_convert_s32_u8;
break;
case AUD_FORMAT_S16:
m_convert = AUD_convert_s32_s16;
break;
case AUD_FORMAT_S24:
if(bigendian)
m_convert = AUD_convert_s32_s24_be;
else
m_convert = AUD_convert_s32_s24_le;
break;
case AUD_FORMAT_S32:
m_convert = AUD_convert_copy<int32_t>;
break;
case AUD_FORMAT_FLOAT32:
m_convert = AUD_convert_s32_float;
break;
case AUD_FORMAT_FLOAT64:
m_convert = AUD_convert_s32_double;
break;
default:
break;
}
m_convert = AUD_convert_float_s32;
break;
case AUD_FORMAT_FLOAT32:
switch(specs.format)
{
case AUD_FORMAT_U8:
m_convert = AUD_convert_float_u8;
break;
case AUD_FORMAT_S16:
m_convert = AUD_convert_float_s16;
break;
case AUD_FORMAT_S24:
if(bigendian)
m_convert = AUD_convert_float_s24_be;
else
m_convert = AUD_convert_float_s24_le;
break;
case AUD_FORMAT_S32:
m_convert = AUD_convert_float_s32;
break;
case AUD_FORMAT_FLOAT32:
m_convert = AUD_convert_copy<float>;
break;
case AUD_FORMAT_FLOAT64:
m_convert = AUD_convert_float_double;
break;
default:
break;
}
m_convert = AUD_convert_copy<float>;
break;
case AUD_FORMAT_FLOAT64:
switch(specs.format)
{
case AUD_FORMAT_U8:
m_convert = AUD_convert_double_u8;
break;
case AUD_FORMAT_S16:
m_convert = AUD_convert_double_s16;
break;
case AUD_FORMAT_S24:
if(bigendian)
m_convert = AUD_convert_double_s24_be;
else
m_convert = AUD_convert_double_s24_le;
break;
case AUD_FORMAT_S32:
m_convert = AUD_convert_double_s32;
break;
case AUD_FORMAT_FLOAT32:
m_convert = AUD_convert_double_float;
break;
case AUD_FORMAT_FLOAT64:
m_convert = AUD_convert_copy<double>;
break;
default:
break;
}
m_convert = AUD_convert_float_double;
break;
default:
break;
@ -242,7 +74,7 @@ AUD_ConverterReader::~AUD_ConverterReader()
AUD_Specs AUD_ConverterReader::getSpecs()
{
return m_specs;
return m_specs.specs;
}
void AUD_ConverterReader::read(int & length, sample_t* & buffer)
@ -254,7 +86,8 @@ void AUD_ConverterReader::read(int & length, sample_t* & buffer)
if(m_buffer->getSize() < length*samplesize)
m_buffer->resize(length*samplesize);
m_convert(m_buffer->getBuffer(), buffer, length*m_specs.channels);
m_convert((data_t*)m_buffer->getBuffer(), (data_t*)buffer,
length * m_specs.channels);
buffer = m_buffer->getBuffer();
}

@ -44,7 +44,7 @@ private:
/**
* The target specification.
*/
AUD_Specs m_specs;
AUD_DeviceSpecs m_specs;
/**
* Converter function.
@ -58,7 +58,7 @@ public:
* \param specs The target specification.
* \exception AUD_Exception Thrown if the reader is NULL.
*/
AUD_ConverterReader(AUD_IReader* reader, AUD_Specs specs);
AUD_ConverterReader(AUD_IReader* reader, AUD_DeviceSpecs specs);
/**
* Destroys the reader.
*/

@ -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 *****
*/
#ifndef AUD_FLOATMIXER
#define AUD_FLOATMIXER
#include "AUD_IMixer.h"
#include "AUD_ConverterFunctions.h"
class AUD_ConverterFactory;
class AUD_SRCResampleFactory;
class AUD_ChannelMapperFactory;
class AUD_Buffer;
#include <list>
struct AUD_FloatMixerBuffer
{
sample_t* buffer;
int length;
float volume;
};
/**
* This class is able to mix two audiosignals with floats.
*/
class AUD_FloatMixer : public AUD_IMixer
{
private:
/**
* The converter factory that converts all readers for superposition.
*/
AUD_ConverterFactory* m_converter;
/**
* The resampling factory that resamples all readers for superposition.
*/
AUD_SRCResampleFactory* m_resampler;
/**
* The channel mapper factory that maps all readers for superposition.
*/
AUD_ChannelMapperFactory* m_mapper;
/**
* The list of buffers to superpose.
*/
std::list<AUD_FloatMixerBuffer> m_buffers;
/**
* The output specification.
*/
AUD_Specs m_specs;
/**
* The temporary mixing buffer.
*/
AUD_Buffer* m_buffer;
/**
* Converter function.
*/
AUD_convert_f m_convert;
public:
/**
* Creates the mixer.
*/
AUD_FloatMixer();
virtual ~AUD_FloatMixer();
virtual AUD_IReader* prepare(AUD_IReader* reader);
virtual void setSpecs(AUD_Specs specs);
virtual void add(sample_t* buffer, AUD_Specs specs, int length,
float volume);
virtual void superpose(sample_t* buffer, int length, float volume);
};
#endif //AUD_FLOATMIXER

@ -53,7 +53,7 @@ public:
/**
* Returns the specification of the device.
*/
virtual AUD_Specs getSpecs()=0;
virtual AUD_DeviceSpecs getSpecs()=0;
/**
* Plays a sound source.

@ -23,42 +23,30 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_SDLMixerFactory.h"
#include "AUD_SDLMixerReader.h"
#include "AUD_LinearResampleFactory.h"
#include "AUD_LinearResampleReader.h"
#include <cstring>
AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_IReader* reader,
AUD_DeviceSpecs specs) :
AUD_ResampleFactory(reader, specs) {}
AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_IReader* reader, AUD_Specs specs) :
AUD_MixerFactory(reader, specs) {}
AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_IFactory* factory,
AUD_DeviceSpecs specs) :
AUD_ResampleFactory(factory, specs) {}
AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_IFactory* factory, AUD_Specs specs) :
AUD_MixerFactory(factory, specs) {}
AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_DeviceSpecs specs) :
AUD_ResampleFactory(specs) {}
AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_Specs specs) :
AUD_MixerFactory(specs) {}
AUD_IReader* AUD_SDLMixerFactory::createReader()
AUD_IReader* AUD_LinearResampleFactory::createReader()
{
AUD_IReader* reader = getReader();
if(reader != 0)
{
AUD_Specs specs = reader->getSpecs();
if(memcmp(&m_specs, &specs, sizeof(AUD_Specs)) != 0)
if(reader->getSpecs().rate != m_specs.rate)
{
try
{
reader = new AUD_SDLMixerReader(reader, m_specs);
AUD_NEW("reader")
}
catch(AUD_Exception e)
{
// return 0 in case SDL cannot mix the source
if(e.error != AUD_ERROR_SDL)
throw;
else
reader = NULL;
}
reader = new AUD_LinearResampleReader(reader, m_specs.specs);
AUD_NEW("reader")
}
}
return reader;

@ -23,23 +23,22 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_SDLMIXERFACTORY
#define AUD_SDLMIXERFACTORY
#ifndef AUD_LINEARRESAMPLEFACTORY
#define AUD_LINEARRESAMPLEFACTORY
#include "AUD_MixerFactory.h"
#include "AUD_ResampleFactory.h"
/**
* This factory creates a resampling reader that uses SDL's resampling
* functionality which unfortunately is very very very limited.
* This factory creates a resampling reader that does simple linear resampling.
*/
class AUD_SDLMixerFactory : public AUD_MixerFactory
class AUD_LinearResampleFactory : public AUD_ResampleFactory
{
public:
AUD_SDLMixerFactory(AUD_IReader* reader, AUD_Specs specs);
AUD_SDLMixerFactory(AUD_IFactory* factory, AUD_Specs specs);
AUD_SDLMixerFactory(AUD_Specs specs);
AUD_LinearResampleFactory(AUD_IReader* reader, AUD_DeviceSpecs specs);
AUD_LinearResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
AUD_LinearResampleFactory(AUD_DeviceSpecs specs);
virtual AUD_IReader* createReader();
};
#endif //AUD_SDLMIXERFACTORY
#endif //AUD_LINEARRESAMPLEFACTORY

@ -0,0 +1,138 @@
/*
* $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_LinearResampleReader.h"
#include "AUD_Buffer.h"
#include <cmath>
#include <cstring>
#include <cstdio>
AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_IReader* reader,
AUD_Specs specs) :
AUD_EffectReader(reader)
{
m_sspecs = reader->getSpecs();
m_tspecs = specs;
m_tspecs.channels = m_sspecs.channels;
m_factor = (float)m_tspecs.rate / (float)m_sspecs.rate;
m_position = 0;
m_sposition = 0;
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_cache = new AUD_Buffer(2 * AUD_SAMPLE_SIZE(specs)); AUD_NEW("buffer")
}
AUD_LinearResampleReader::~AUD_LinearResampleReader()
{
delete m_buffer; AUD_DELETE("buffer")
delete m_cache; AUD_DELETE("buffer")
}
void AUD_LinearResampleReader::seek(int position)
{
m_position = position;
m_sposition = floor(position / m_factor);
m_reader->seek(m_sposition);
}
int AUD_LinearResampleReader::getLength()
{
return m_reader->getLength() * m_factor;
}
int AUD_LinearResampleReader::getPosition()
{
return m_position;
}
AUD_Specs AUD_LinearResampleReader::getSpecs()
{
return m_tspecs;
}
void AUD_LinearResampleReader::read(int & length, sample_t* & buffer)
{
int size = length * AUD_SAMPLE_SIZE(m_tspecs);
if(m_buffer->getSize() < size)
m_buffer->resize(size);
int need = ceil((m_position + length) / m_factor) + 1 - m_sposition;
int len = need;
sample_t* buf;
buffer = m_buffer->getBuffer();
m_reader->read(len, buf);
if(len < need)
length = floor((m_sposition + len - 1) * m_factor) - m_position;
float spos;
sample_t low, high;
int channels = m_sspecs.channels;
for(int channel = 0; channel < channels; channel++)
{
for(int i = 0; i < length; i++)
{
spos = (m_position + i) / m_factor - m_sposition;
if((floor(spos) < -2) || (ceil(spos) >= len))
{
fprintf(stderr, "FATAL ERROR: REPORT THIS TO neXyon!\n");
// exit(1);
}
if(floor(spos) < 0)
{
low = m_cache->getBuffer()[(int)(floor(spos) + 2) * channels
+ channel];
if(ceil(spos) < 0)
high = m_cache->getBuffer()[(int)(ceil(spos) + 2)
* channels + channel];
else
high = buf[(int)ceil(spos) * channels + channel];
}
else
{
low = buf[(int)floor(spos) * channels + channel];
high = buf[(int)ceil(spos) * channels + channel];
}
buffer[i * channels + channel] = low + (spos - floor(spos)) *
(high - low);
}
}
if(len > 1)
memcpy(m_cache->getBuffer(), buf + (len - 2) * channels, 2 * channels);
else if(len == 1)
memcpy(m_cache->getBuffer() + 1 * channels, buf, channels);
m_sposition += len;
m_position += length;
}

@ -0,0 +1,94 @@
/*
* $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_LINEARRESAMPLEREADER
#define AUD_LINEARRESAMPLEREADER
#include "AUD_EffectReader.h"
class AUD_Buffer;
/**
* This resampling reader uses libsamplerate for resampling.
*/
class AUD_LinearResampleReader : public AUD_EffectReader
{
private:
/**
* The resampling factor.
*/
float m_factor;
/**
* The current position.
*/
int m_position;
/**
* The current reading source position.
*/
int m_sposition;
/**
* The sound output buffer.
*/
AUD_Buffer *m_buffer;
/**
* The input caching buffer.
*/
AUD_Buffer *m_cache;
/**
* The target specification.
*/
AUD_Specs m_tspecs;
/**
* The sample specification of the source.
*/
AUD_Specs m_sspecs;
public:
/**
* Creates a resampling reader.
* \param reader The reader to mix.
* \param specs The target specification.
* \exception AUD_Exception Thrown if the reader is NULL.
*/
AUD_LinearResampleReader(AUD_IReader* reader, AUD_Specs specs);
/**
* Destroys the reader.
*/
~AUD_LinearResampleReader();
virtual void seek(int position);
virtual int getLength();
virtual int getPosition();
virtual AUD_Specs getSpecs();
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_LINEARRESAMPLEREADER

@ -23,8 +23,7 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_FloatMixer.h"
#include "AUD_ConverterFactory.h"
#include "AUD_Mixer.h"
#include "AUD_SRCResampleFactory.h"
#include "AUD_ChannelMapperFactory.h"
#include "AUD_IReader.h"
@ -32,23 +31,19 @@
#include <cstring>
AUD_FloatMixer::AUD_FloatMixer()
AUD_Mixer::AUD_Mixer()
{
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_converter = NULL;
m_resampler = NULL;
m_mapper = NULL;
}
AUD_FloatMixer::~AUD_FloatMixer()
AUD_Mixer::~AUD_Mixer()
{
delete m_buffer; AUD_DELETE("buffer")
if(m_converter)
{
delete m_converter; AUD_DELETE("factory")
}
if(m_resampler)
{
delete m_resampler; AUD_DELETE("factory")
@ -59,11 +54,8 @@ AUD_FloatMixer::~AUD_FloatMixer()
}
}
AUD_IReader* AUD_FloatMixer::prepare(AUD_IReader* reader)
AUD_IReader* AUD_Mixer::prepare(AUD_IReader* reader)
{
m_converter->setReader(reader);
reader = m_converter->createReader();
m_resampler->setReader(reader);
reader = m_resampler->createReader();
@ -76,14 +68,10 @@ AUD_IReader* AUD_FloatMixer::prepare(AUD_IReader* reader)
return reader;
}
void AUD_FloatMixer::setSpecs(AUD_Specs specs)
void AUD_Mixer::setSpecs(AUD_DeviceSpecs specs)
{
m_specs = specs;
if(m_converter)
{
delete m_converter; AUD_DELETE("factory")
}
if(m_resampler)
{
delete m_resampler; AUD_DELETE("factory")
@ -93,9 +81,6 @@ void AUD_FloatMixer::setSpecs(AUD_Specs specs)
delete m_mapper; AUD_DELETE("factory")
}
specs.format = AUD_FORMAT_FLOAT32;
m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory")
m_resampler = new AUD_SRCResampleFactory(specs); AUD_NEW("factory")
m_mapper = new AUD_ChannelMapperFactory(specs); AUD_NEW("factory")
@ -130,27 +115,26 @@ void AUD_FloatMixer::setSpecs(AUD_Specs specs)
}
}
void AUD_FloatMixer::add(sample_t* buffer, AUD_Specs specs, int length,
float volume)
void AUD_Mixer::add(sample_t* buffer, int length, float volume)
{
AUD_FloatMixerBuffer buf;
AUD_MixerBuffer buf;
buf.buffer = buffer;
buf.length = length;
buf.volume = volume;
m_buffers.push_back(buf);
}
void AUD_FloatMixer::superpose(sample_t* buffer, int length, float volume)
void AUD_Mixer::superpose(data_t* buffer, int length, float volume)
{
AUD_FloatMixerBuffer buf;
AUD_MixerBuffer buf;
int channels = m_specs.channels;
if(m_buffer->getSize() < length * channels * 4)
m_buffer->resize(length * channels * 4);
float* out = (float*)m_buffer->getBuffer();
float* in;
sample_t* out = m_buffer->getBuffer();
sample_t* in;
memset(out, 0, length * channels * 4);
@ -162,11 +146,11 @@ void AUD_FloatMixer::superpose(sample_t* buffer, int length, float volume)
m_buffers.pop_front();
end = buf.length*channels;
in = (float*) buf.buffer;
in = buf.buffer;
for(int i = 0; i < end; i++)
out[i] += in[i]*buf.volume * volume;
}
m_convert(buffer, (sample_t*) out, length * channels);
m_convert(buffer, (data_t*) out, length * channels);
}

@ -23,47 +23,95 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#ifndef AUD_IMIXER
#define AUD_IMIXER
#ifndef AUD_MIXER
#define AUD_MIXER
#include "AUD_Space.h"
#include "AUD_ConverterFunctions.h"
class AUD_ConverterFactory;
class AUD_SRCResampleFactory;
class AUD_ChannelMapperFactory;
class AUD_Buffer;
class AUD_IReader;
#include <list>
struct AUD_MixerBuffer
{
sample_t* buffer;
int length;
float volume;
};
/**
* This class is able to mix audiosignals of different format and channel count.
* \note This class doesn't do resampling!
* This class is able to mix audiosignals of different channel count and sample
* rate and convert it to a specific output format.
* It uses a default ChannelMapperFactory and a SRCResampleFactory for
* the perparation.
*/
class AUD_IMixer
class AUD_Mixer
{
private:
/**
* The resampling factory that resamples all readers for superposition.
*/
AUD_SRCResampleFactory* m_resampler;
/**
* The channel mapper factory that maps all readers for superposition.
*/
AUD_ChannelMapperFactory* m_mapper;
/**
* The list of buffers to superpose.
*/
std::list<AUD_MixerBuffer> m_buffers;
/**
* The output specification.
*/
AUD_DeviceSpecs m_specs;
/**
* The temporary mixing buffer.
*/
AUD_Buffer* m_buffer;
/**
* Converter function.
*/
AUD_convert_f m_convert;
public:
/**
* Creates the mixer.
*/
AUD_Mixer();
/**
* Destroys the mixer.
*/
virtual ~AUD_IMixer(){}
~AUD_Mixer();
/**
* This funuction prepares a reader for playback.
* \param reader The reader to prepare.
* \return The reader that should be used for playback.
*/
virtual AUD_IReader* prepare(AUD_IReader* reader)=0;
AUD_IReader* prepare(AUD_IReader* reader);
/**
* Sets the target specification for superposing.
* \param specs The target specification.
*/
virtual void setSpecs(AUD_Specs specs)=0;
void setSpecs(AUD_DeviceSpecs specs);
/**
* Adds a buffer for superposition.
* \param buffer The buffer to superpose.
* \param specs The specification of the buffer.
* \param start The start sample of the buffer.
* \param length The length of the buffer in samples.
* \param volume The mixing volume. Must be a value between 0.0 and 1.0.
*/
virtual void add(sample_t* buffer, AUD_Specs specs, int length,
float volume)=0;
void add(sample_t* buffer, int length, float volume);
/**
* Superposes all added buffers into an output buffer.
@ -71,7 +119,7 @@ public:
* \param length The length of the buffer in samples.
* \param volume The mixing volume. Must be a value between 0.0 and 1.0.
*/
virtual void superpose(sample_t* buffer, int length, float volume)=0;
void superpose(data_t* buffer, int length, float volume);
};
#endif //AUD_IMIXER
#endif //AUD_MIXER

@ -49,7 +49,7 @@ AUD_IReader* AUD_MixerFactory::getReader()
}
AUD_MixerFactory::AUD_MixerFactory(AUD_IReader* reader,
AUD_Specs specs)
AUD_DeviceSpecs specs)
{
m_specs = specs;
m_reader = reader;
@ -57,14 +57,14 @@ AUD_MixerFactory::AUD_MixerFactory(AUD_IReader* reader,
}
AUD_MixerFactory::AUD_MixerFactory(AUD_IFactory* factory,
AUD_Specs specs)
AUD_DeviceSpecs specs)
{
m_specs = specs;
m_reader = 0;
m_factory = factory;
}
AUD_MixerFactory::AUD_MixerFactory(AUD_Specs specs)
AUD_MixerFactory::AUD_MixerFactory(AUD_DeviceSpecs specs)
{
m_specs = specs;
m_reader = 0;
@ -79,12 +79,12 @@ AUD_MixerFactory::~AUD_MixerFactory()
}
}
AUD_Specs AUD_MixerFactory::getSpecs()
AUD_DeviceSpecs AUD_MixerFactory::getSpecs()
{
return m_specs;
}
void AUD_MixerFactory::setSpecs(AUD_Specs specs)
void AUD_MixerFactory::setSpecs(AUD_DeviceSpecs specs)
{
m_specs = specs;
}

@ -47,7 +47,7 @@ protected:
/**
* The target specification for resampling.
*/
AUD_Specs m_specs;
AUD_DeviceSpecs m_specs;
/**
* Returns the reader created out of the factory or taken from m_reader.
@ -63,20 +63,20 @@ public:
* \param reader The reader to mix.
* \param specs The target specification.
*/
AUD_MixerFactory(AUD_IReader* reader, AUD_Specs specs);
AUD_MixerFactory(AUD_IReader* reader, AUD_DeviceSpecs specs);
/**
* Creates a new factory.
* \param factory The factory to create the readers to mix out of.
* \param specs The target specification.
*/
AUD_MixerFactory(AUD_IFactory* factory, AUD_Specs specs);
AUD_MixerFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
/**
* Creates a new factory.
* \param specs The target specification.
*/
AUD_MixerFactory(AUD_Specs specs);
AUD_MixerFactory(AUD_DeviceSpecs specs);
/**
* Destroys the resampling factory.
@ -86,13 +86,13 @@ public:
/**
* Returns the target specification for resampling.
*/
AUD_Specs getSpecs();
AUD_DeviceSpecs getSpecs();
/**
* Sets the target specification for resampling.
* \param specs The specification.
*/
void setSpecs(AUD_Specs specs);
void setSpecs(AUD_DeviceSpecs specs);
/**
* Sets the reader for resampling.

@ -34,7 +34,7 @@ AUD_NULLDevice::AUD_NULLDevice()
m_specs.rate = AUD_RATE_INVALID;
}
AUD_Specs AUD_NULLDevice::getSpecs()
AUD_DeviceSpecs AUD_NULLDevice::getSpecs()
{
return m_specs;
}

@ -37,7 +37,7 @@ private:
/**
* The specs of the device.
*/
AUD_Specs m_specs;
AUD_DeviceSpecs m_specs;
public:
/**
@ -45,7 +45,7 @@ public:
*/
AUD_NULLDevice();
virtual AUD_Specs getSpecs();
virtual AUD_DeviceSpecs getSpecs();
virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false);
virtual bool pause(AUD_Handle* handle);
virtual bool resume(AUD_Handle* handle);

@ -23,17 +23,17 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_FloatMixer.h"
#include "AUD_Mixer.h"
#include "AUD_ReadDevice.h"
#include "AUD_IReader.h"
#include <cstring>
AUD_ReadDevice::AUD_ReadDevice(AUD_Specs specs)
AUD_ReadDevice::AUD_ReadDevice(AUD_DeviceSpecs specs)
{
m_specs = specs;
m_mixer = new AUD_FloatMixer(); AUD_NEW("mixer")
m_mixer = new AUD_Mixer(); AUD_NEW("mixer")
m_mixer->setSpecs(m_specs);
m_playing = false;
@ -46,15 +46,15 @@ AUD_ReadDevice::~AUD_ReadDevice()
destroy();
}
bool AUD_ReadDevice::read(sample_t* buffer, int length)
bool AUD_ReadDevice::read(data_t* buffer, int length)
{
if(m_playing)
mix(buffer, length);
else
if(m_specs.format == AUD_FORMAT_U8)
memset(buffer, 0x80, length * AUD_SAMPLE_SIZE(m_specs));
memset(buffer, 0x80, length * AUD_DEVICE_SAMPLE_SIZE(m_specs));
else
memset(buffer, 0, length * AUD_SAMPLE_SIZE(m_specs));
memset(buffer, 0, length * AUD_DEVICE_SAMPLE_SIZE(m_specs));
return m_playing;
}

@ -47,7 +47,7 @@ public:
* Creates a new read device.
* \param specs The wanted audio specification.
*/
AUD_ReadDevice(AUD_Specs specs);
AUD_ReadDevice(AUD_DeviceSpecs specs);
/**
* Closes the device.
@ -62,7 +62,7 @@ public:
* played back currently, in that case the buffer is filled with
* silence.
*/
bool read(sample_t* buffer, int length);
bool read(data_t* buffer, int length);
};
#endif //AUD_READDEVICE

@ -26,7 +26,7 @@
#include "AUD_SinusReader.h"
#include "AUD_Buffer.h"
#include <math.h>
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265358979323846
@ -69,8 +69,7 @@ AUD_Specs AUD_SinusReader::getSpecs()
{
AUD_Specs specs;
specs.rate = m_sampleRate;
specs.format = AUD_FORMAT_S16;
specs.channels = AUD_CHANNELS_STEREO;
specs.channels = AUD_CHANNELS_MONO;
return specs;
}
@ -87,18 +86,16 @@ bool AUD_SinusReader::notify(AUD_Message &message)
void AUD_SinusReader::read(int & length, sample_t* & buffer)
{
// resize if necessary
if(m_buffer->getSize() < length*4)
m_buffer->resize(length*4);
if(m_buffer->getSize() < length * sizeof(sample_t))
m_buffer->resize(length * sizeof(sample_t));
// fill with sine data
short* buf = (short*) m_buffer->getBuffer();
for(int i=0; i < length; i++)
buffer = m_buffer->getBuffer();
for(int i = 0; i < length; i++)
{
buf[i*2] = sin((m_position + i) * 2.0 * M_PI * m_frequency /
(float)m_sampleRate) * 32700;
buf[i*2+1] = buf[i*2];
buffer[i] = sin((m_position + i) * 2.0 * M_PI * m_frequency /
(float)m_sampleRate);
}
buffer = (sample_t*)buf;
m_position += length;
}

@ -25,7 +25,7 @@
#include "AUD_SoftwareDevice.h"
#include "AUD_IReader.h"
#include "AUD_IMixer.h"
#include "AUD_Mixer.h"
#include "AUD_IFactory.h"
#include "AUD_SourceCaps.h"
@ -52,6 +52,8 @@ void AUD_SoftwareDevice::create()
m_pausedSounds = new std::list<AUD_SoftwareHandle*>(); AUD_NEW("list")
m_playback = false;
m_volume = 1.0;
m_mixer = new AUD_Mixer(); AUD_NEW("mixer")
m_mixer->setSpecs(m_specs);
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
@ -90,7 +92,7 @@ void AUD_SoftwareDevice::destroy()
pthread_mutex_destroy(&m_mutex);
}
void AUD_SoftwareDevice::mix(sample_t* buffer, int length)
void AUD_SoftwareDevice::mix(data_t* buffer, int length)
{
lock();
@ -98,7 +100,7 @@ void AUD_SoftwareDevice::mix(sample_t* buffer, int length)
AUD_SoftwareHandle* sound;
int len;
sample_t* buf;
int sample_size = AUD_SAMPLE_SIZE(m_specs);
int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs);
std::list<AUD_SoftwareHandle*> stopSounds;
// for all sounds
@ -114,7 +116,7 @@ void AUD_SoftwareDevice::mix(sample_t* buffer, int length)
len = length;
sound->reader->read(len, buf);
m_mixer->add(buf, sound->reader->getSpecs(), len, sound->volume);
m_mixer->add(buf, len, sound->volume);
// in case the end of the sound is reached
if(len < length)
@ -159,14 +161,7 @@ bool AUD_SoftwareDevice::isValid(AUD_Handle* handle)
return false;
}
void AUD_SoftwareDevice::setMixer(AUD_IMixer* mixer)
{
delete m_mixer; AUD_DELETE("mixer")
m_mixer = mixer;
mixer->setSpecs(m_specs);
}
AUD_Specs AUD_SoftwareDevice::getSpecs()
AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs()
{
return m_specs;
}

@ -28,7 +28,7 @@
#include "AUD_IDevice.h"
struct AUD_SoftwareHandle;
class AUD_IMixer;
class AUD_Mixer;
#include <list>
#include <pthread.h>
@ -47,12 +47,12 @@ protected:
/**
* The specification of the device.
*/
AUD_Specs m_specs;
AUD_DeviceSpecs m_specs;
/**
* The mixer. Will be deleted by the destroy function.
* The mixer.
*/
AUD_IMixer* m_mixer;
AUD_Mixer* m_mixer;
/**
* Initializes member variables.
@ -69,7 +69,7 @@ protected:
* \param buffer The target buffer.
* \param length The length in samples to be filled.
*/
void mix(sample_t* buffer, int length);
void mix(data_t* buffer, int length);
/**
* This function tells the device, to start or pause playback.
@ -111,13 +111,7 @@ private:
bool isValid(AUD_Handle* handle);
public:
/**
* Sets a new mixer.
* \param mixer The new mixer.
*/
void setMixer(AUD_IMixer* mixer);
virtual AUD_Specs getSpecs();
virtual AUD_DeviceSpecs getSpecs();
virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false);
virtual bool pause(AUD_Handle* handle);
virtual bool resume(AUD_Handle* handle);

@ -28,8 +28,10 @@
/// The size of a format in bytes.
#define AUD_FORMAT_SIZE(format) (format & 0x0F)
/// The size of a sample in the specified device format in bytes.
#define AUD_DEVICE_SAMPLE_SIZE(specs) (specs.channels * (specs.format & 0x0F))
/// The size of a sample in the specified format in bytes.
#define AUD_SAMPLE_SIZE(specs) (specs.channels * (specs.format & 0x0F))
#define AUD_SAMPLE_SIZE(specs) (specs.channels * sizeof(sample_t))
/// Throws a AUD_Exception with the provided error code.
#define AUD_THROW(exception) { AUD_Exception e; e.error = exception; throw e; }
@ -233,22 +235,42 @@ typedef enum
AUD_3DSS_CONE_OUTER_GAIN /// Cone outer gain.
} AUD_3DSourceSetting;
/// Sample pointer type.
typedef unsigned char sample_t;
/// Sample type.(float samples)
typedef float sample_t;
/// Specification of a sound source or device.
/// Sample data type (format samples)
typedef unsigned char data_t;
/// Specification of a sound source.
typedef struct
{
/// Sample rate in Hz.
AUD_SampleRate rate;
/// Sample format.
AUD_SampleFormat format;
/// Channel count.
AUD_Channels channels;
} AUD_Specs;
/// Specification of a sound device.
typedef struct
{
/// Sample format.
AUD_SampleFormat format;
union
{
struct
{
/// Sample rate in Hz.
AUD_SampleRate rate;
/// Channel count.
AUD_Channels channels;
};
AUD_Specs specs;
};
} AUD_DeviceSpecs;
/// Exception structure.
typedef struct
{

@ -61,9 +61,9 @@ AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory)
// read more
length = size-index;
reader->read(length, buffer);
memcpy(m_buffer.get()->getBuffer()+index*sample_size,
memcpy(m_buffer.get()->getBuffer() + index * m_specs.channels,
buffer,
length*sample_size);
length * sample_size);
size += AUD_BUFFER_RESIZE_BYTES / sample_size;
index += length;
}

@ -23,7 +23,7 @@
* ***** END LGPL LICENSE BLOCK *****
*/
#include "AUD_FloatMixer.h"
#include "AUD_Mixer.h"
#include "AUD_JackDevice.h"
#include "AUD_IReader.h"
#include "AUD_Buffer.h"
@ -38,7 +38,7 @@ int AUD_JackDevice::jack_mix(jack_nframes_t length, void *data)
unsigned int samplesize = AUD_SAMPLE_SIZE(device->m_specs);
if(device->m_buffer->getSize() < samplesize * length)
device->m_buffer->resize(samplesize * length);
device->mix(device->m_buffer->getBuffer(), length);
device->mix((data_t*)device->m_buffer->getBuffer(), length);
float* in = (float*) device->m_buffer->getBuffer();
float* out;
@ -60,7 +60,7 @@ void AUD_JackDevice::jack_shutdown(void *data)
device->m_valid = false;
}
AUD_JackDevice::AUD_JackDevice(AUD_Specs specs)
AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs)
{
if(specs.channels == AUD_CHANNELS_INVALID)
specs.channels = AUD_CHANNELS_STEREO;
@ -123,9 +123,6 @@ AUD_JackDevice::AUD_JackDevice(AUD_Specs specs)
free(ports);
}
m_mixer = new AUD_FloatMixer(); AUD_NEW("mixer")
m_mixer->setSpecs(m_specs);
m_valid = true;
create();

@ -81,7 +81,7 @@ public:
* \param specs The wanted audio specification, where only the channel count is important.
* \exception AUD_Exception Thrown if the audio device cannot be opened.
*/
AUD_JackDevice(AUD_Specs specs);
AUD_JackDevice(AUD_DeviceSpecs specs);
/**
* Closes the Jack client.

@ -28,31 +28,14 @@
#include <cstring>
// This function transforms a SampleFormat to our own sample format
static inline AUD_SampleFormat SNDFILE_TO_AUD(int fmt)
{
switch(fmt & SF_FORMAT_SUBMASK)
{
// only read s16, s32 and double as they are
case SF_FORMAT_PCM_16:
return AUD_FORMAT_S16;
case SF_FORMAT_PCM_32:
return AUD_FORMAT_S32;
case SF_FORMAT_DOUBLE:
return AUD_FORMAT_FLOAT64;
// read all other formats as floats
default:
return AUD_FORMAT_FLOAT32;
}
}
sf_count_t AUD_SndFileReader::vio_get_filelen(void *user_data)
{
AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data;
return reader->m_membuffer.get()->getSize();
}
sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence, void *user_data)
sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence,
void *user_data)
{
AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data;
@ -72,14 +55,16 @@ sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence, void *user
return reader->m_memoffset;
}
sf_count_t AUD_SndFileReader::vio_read(void *ptr, sf_count_t count, void *user_data)
sf_count_t AUD_SndFileReader::vio_read(void *ptr, sf_count_t count,
void *user_data)
{
AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data;
if(reader->m_memoffset + count > reader->m_membuffer.get()->getSize())
count = reader->m_membuffer.get()->getSize() - reader->m_memoffset;
memcpy(ptr, reader->m_membuffer.get()->getBuffer() + reader->m_memoffset, count);
memcpy(ptr, ((data_t*)reader->m_membuffer.get()->getBuffer()) +
reader->m_memoffset, count);
reader->m_memoffset += count;
return count;
@ -103,27 +88,11 @@ AUD_SndFileReader::AUD_SndFileReader(const char* filename)
AUD_THROW(AUD_ERROR_FILE);
m_specs.channels = (AUD_Channels) sfinfo.channels;
m_specs.format = SNDFILE_TO_AUD(sfinfo.format);
m_specs.rate = (AUD_SampleRate) sfinfo.samplerate;
m_length = sfinfo.frames;
m_seekable = sfinfo.seekable;
m_position = 0;
switch(m_specs.format)
{
case AUD_FORMAT_S16:
m_read = (sf_read_f) sf_readf_short;
break;
case AUD_FORMAT_S32:
m_read = (sf_read_f) sf_readf_int;
break;
case AUD_FORMAT_FLOAT64:
m_read = (sf_read_f) sf_readf_double;
break;
default:
m_read = (sf_read_f) sf_readf_float;
}
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
}
@ -147,27 +116,11 @@ AUD_SndFileReader::AUD_SndFileReader(AUD_Reference<AUD_Buffer> buffer)
AUD_THROW(AUD_ERROR_FILE);
m_specs.channels = (AUD_Channels) sfinfo.channels;
m_specs.format = SNDFILE_TO_AUD(sfinfo.format);
m_specs.rate = (AUD_SampleRate) sfinfo.samplerate;
m_length = sfinfo.frames;
m_seekable = sfinfo.seekable;
m_position = 0;
switch(m_specs.format)
{
case AUD_FORMAT_S16:
m_read = (sf_read_f) sf_readf_short;
break;
case AUD_FORMAT_S32:
m_read = (sf_read_f) sf_readf_int;
break;
case AUD_FORMAT_FLOAT64:
m_read = (sf_read_f) sf_readf_double;
break;
default:
m_read = (sf_read_f) sf_readf_float;
}
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
}
@ -227,7 +180,7 @@ void AUD_SndFileReader::read(int & length, sample_t* & buffer)
buffer = m_buffer->getBuffer();
length = m_read(m_sndfile, buffer, length);
length = sf_readf_float(m_sndfile, buffer, length);
m_position += length;
}

@ -70,11 +70,6 @@ private:
*/
SNDFILE* m_sndfile;
/**
* The reading function.
*/
sf_read_f m_read;
/**
* The virtual IO structure for memory file reading.
*/

@ -73,7 +73,7 @@ void sound_update_playing(struct bContext *C);
void sound_scrub(struct bContext *C);
#ifdef AUD_CAPI
AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end, float volume);
AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, int end, float volume);
#endif
void sound_stop_all(struct bContext *C);

@ -3792,7 +3792,7 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
info = AUD_getInfo(sound->handle);
if (info.specs.format == AUD_FORMAT_INVALID) {
if (info.specs.channels == AUD_CHANNELS_INVALID) {
sound_delete(C, sound);
//if(op)
// BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");

@ -40,7 +40,7 @@ void sound_disable()
void sound_init()
{
AUD_Specs specs;
AUD_DeviceSpecs specs;
int device, buffersize;
device = U.audiodevice;
@ -455,7 +455,7 @@ void sound_scrub(struct bContext *C)
}
}
AUD_Device* sound_mixdown(struct Scene *scene, AUD_Specs specs, int start, int end, float volume)
AUD_Device* sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, int end, float volume)
{
AUD_Device* mixdown = AUD_openReadDevice(specs);
SoundHandle *handle;

@ -832,7 +832,7 @@ int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, Repo
if(ffmpeg_multiplex_audio && audio_stream)
{
AVCodecContext* c = get_codec_from_stream(audio_stream);
AUD_Specs specs;
AUD_DeviceSpecs specs;
specs.channels = c->channels;
specs.format = AUD_FORMAT_S16;
specs.rate = rd->ffcodecdata.audio_mixrate;

@ -81,7 +81,7 @@ static int open_exec(bContext *C, wmOperator *op)
info = AUD_getInfo(sound->handle);
if (info.specs.format == AUD_FORMAT_INVALID) {
if (info.specs.channels == AUD_CHANNELS_INVALID) {
sound_delete(C, sound);
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
return OPERATOR_CANCELLED;

@ -36,6 +36,8 @@
#include <config.h>
#endif
#include "AUD_C-API.h"
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
@ -990,6 +992,139 @@ void GRAPH_OT_bake (wmOperatorType *ot)
// todo: add props for start/end frames
}
/* ******************** Sound Bake F-Curve Operator *********************** */
/* This operator bakes the given sound to the selected F-Curves */
/* ------------------- */
/* Custom data storage passed to the F-Sample-ing function,
* which provides the necessary info for baking the sound
*/
typedef struct tSoundBakeInfo {
float* samples;
int length;
int cfra;
} tSoundBakeInfo;
/* ------------------- */
/* Sampling callback used to determine the value from the sound to
* save in the F-Curve at the specified frame
*/
static float fcurve_samplingcb_sound (FCurve *fcu, void *data, float evaltime)
{
tSoundBakeInfo *sbi= (tSoundBakeInfo *)data;
int position = evaltime - sbi->cfra;
if((position < 0) || (position >= sbi->length))
return 0.0f;
return sbi->samples[position];
}
/* ------------------- */
static int graphkeys_sound_bake_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
tSoundBakeInfo sbi;
Scene *scene= NULL;
int start, end;
char path[FILE_MAX];
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
RNA_string_get(op->ptr, "path", path);
scene= ac.scene; /* current scene */
/* store necessary data for the baking steps */
sbi.samples = AUD_readSoundBuffer(path,
RNA_float_get(op->ptr, "low"),
RNA_float_get(op->ptr, "high"),
RNA_float_get(op->ptr, "attack"),
RNA_float_get(op->ptr, "release"),
RNA_float_get(op->ptr, "threshold"),
FPS, &sbi.length);
if (sbi.samples == NULL) {
BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
return OPERATOR_CANCELLED;
}
/* determine extents of the baking */
sbi.cfra = start = CFRA;
end = CFRA + sbi.length - 1;
/* filter anim channels */
filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVEVISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_CURVESONLY);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* loop through all selected F-Curves, replacing its data with the sound samples */
for (ale= anim_data.first; ale; ale= ale->next) {
FCurve *fcu= (FCurve *)ale->key_data;
/* sample the sound */
fcurve_store_samples(fcu, &sbi, start, end, fcurve_samplingcb_sound);
}
/* free sample data */
free(sbi.samples);
/* admin and redraws */
BLI_freelistN(&anim_data);
/* validate keyframes after editing */
ANIM_editkeyframes_refresh(&ac);
/* set notifier that 'keyframes' have changed */
WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL);
return OPERATOR_FINISHED;
}
static int graphkeys_sound_bake_invoke (bContext *C, wmOperator *op, wmEvent *event)
{
bAnimContext ac;
/* verify editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
return WM_operator_filesel(C, op, event);
}
void GRAPH_OT_sound_bake (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Bake Sound to F-Curves";
ot->idname= "GRAPH_OT_sound_bake";
ot->description= "Bakes a sound wave to selected F-Curves.";
/* api callbacks */
ot->invoke= graphkeys_sound_bake_invoke;
ot->exec= graphkeys_sound_bake_exec;
ot->poll= graphop_selected_fcurve_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */
WM_operator_properties_filesel(ot, FOLDERFILE|SOUNDFILE|MOVIEFILE, FILE_SPECIAL);
RNA_def_float(ot->srna, "low", 0.0f, 0.0, 100000.0, "Lowest frequency", "", 0.1, 1000.00);
RNA_def_float(ot->srna, "high", 100000.0, 0.0, 100000.0, "Highest frequency", "", 0.1, 1000.00);
RNA_def_float(ot->srna, "attack", 0.005, 0.0, 2.0, "Attack time", "", 0.01, 0.1);
RNA_def_float(ot->srna, "release", 0.2, 0.0, 5.0, "Release time", "", 0.01, 0.2);
RNA_def_float(ot->srna, "threshold", 0.0, 0.0, 1.0, "Threshold", "", 0.01, 0.1);
}
/* ******************** Sample Keyframes Operator *********************** */
/* This operator 'bakes' the values of the curve into new keyframes between pairs
* of selected keyframes. It is useful for creating keyframes for tweaking overlap.

@ -100,6 +100,7 @@ void GRAPH_OT_delete(struct wmOperatorType *ot);
void GRAPH_OT_clean(struct wmOperatorType *ot);
void GRAPH_OT_sample(struct wmOperatorType *ot);
void GRAPH_OT_bake(struct wmOperatorType *ot);
void GRAPH_OT_sound_bake(struct wmOperatorType *ot);
void GRAPH_OT_smooth(struct wmOperatorType *ot);
void GRAPH_OT_handle_type(struct wmOperatorType *ot);

@ -247,6 +247,7 @@ void graphedit_operatortypes(void)
WM_operatortype_append(GRAPH_OT_extrapolation_type);
WM_operatortype_append(GRAPH_OT_sample);
WM_operatortype_append(GRAPH_OT_bake);
WM_operatortype_append(GRAPH_OT_sound_bake);
WM_operatortype_append(GRAPH_OT_smooth);
WM_operatortype_append(GRAPH_OT_clean);
WM_operatortype_append(GRAPH_OT_delete);