Merged changes in the trunk up to revision 25863.

This commit is contained in:
2010-01-10 15:28:24 +00:00
487 changed files with 14606 additions and 8024 deletions

View File

@@ -412,31 +412,6 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra
// restore // restore
collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape); collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
} }
} else {
if (collisionShape->isSoftBody()) {
btSoftBody* softBody = static_cast<btSoftBody*>(collisionObject);
btSoftBody::sRayCast softResult;
if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
{
btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = 0;
shapeInfo.m_triangleIndex = softResult.index;
// get the normal
btVector3 normal = softBody->m_faces[softResult.index].m_normal;
btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
if (normal.dot(rayDir) > 0) {
// normal always point toward origin of the ray
normal = -normal;
}
btCollisionWorld::LocalRayResult rayResult
(collisionObject,
&shapeInfo,
normal,
softResult.fraction);
bool normalInWorldSpace = true;
resultCallback.addSingleResult(rayResult,normalInWorldSpace);
}
}
} }
} }
} }

View File

@@ -354,7 +354,7 @@ public:
/// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback
/// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
// convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback // convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback
// This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback. // This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback.

View File

@@ -22,6 +22,7 @@ subject to the following restrictions:
#include "btSoftBodyHelpers.h" #include "btSoftBodyHelpers.h"
//#define USE_BRUTEFORCE_RAYBROADPHASE 1
@@ -140,3 +141,140 @@ void btSoftRigidDynamicsWorld::debugDrawWorld()
} }
} }
} }
struct btSoftSingleRayCallback : public btBroadphaseRayCallback
{
btVector3 m_rayFromWorld;
btVector3 m_rayToWorld;
btTransform m_rayFromTrans;
btTransform m_rayToTrans;
btVector3 m_hitNormal;
const btSoftRigidDynamicsWorld* m_world;
btCollisionWorld::RayResultCallback& m_resultCallback;
btSoftSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btSoftRigidDynamicsWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
:m_rayFromWorld(rayFromWorld),
m_rayToWorld(rayToWorld),
m_world(world),
m_resultCallback(resultCallback)
{
m_rayFromTrans.setIdentity();
m_rayFromTrans.setOrigin(m_rayFromWorld);
m_rayToTrans.setIdentity();
m_rayToTrans.setOrigin(m_rayToWorld);
btVector3 rayDir = (rayToWorld-rayFromWorld);
rayDir.normalize ();
///what about division by zero? --> just set rayDirection[i] to INF/1e30
m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
m_signs[0] = m_rayDirectionInverse[0] < 0.0;
m_signs[1] = m_rayDirectionInverse[1] < 0.0;
m_signs[2] = m_rayDirectionInverse[2] < 0.0;
m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld);
}
virtual bool process(const btBroadphaseProxy* proxy)
{
///terminate further ray tests, once the closestHitFraction reached zero
if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
return false;
btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
//only perform raycast if filterMask matches
if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
{
//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
//btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
#if 0
#ifdef RECALCULATE_AABB
btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
#else
//getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
#endif
#endif
//btScalar hitLambda = m_resultCallback.m_closestHitFraction;
//culling already done by broadphase
//if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
{
m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans,
collisionObject,
collisionObject->getCollisionShape(),
collisionObject->getWorldTransform(),
m_resultCallback);
}
}
return true;
}
};
void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
{
BT_PROFILE("rayTest");
/// use the broadphase to accelerate the search for objects, based on their aabb
/// and for each object with ray-aabb overlap, perform an exact ray test
btSoftSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
#ifndef USE_BRUTEFORCE_RAYBROADPHASE
m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
#else
for (int i=0;i<this->getNumCollisionObjects();i++)
{
rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
}
#endif //USE_BRUTEFORCE_RAYBROADPHASE
}
void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback)
{
if (collisionShape->isSoftBody()) {
btSoftBody* softBody = btSoftBody::upcast(collisionObject);
if (softBody) {
btSoftBody::sRayCast softResult;
if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
{
if (softResult.fraction<= resultCallback.m_closestHitFraction)
{
btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = 0;
shapeInfo.m_triangleIndex = softResult.index;
// get the normal
btVector3 normal = softBody->m_faces[softResult.index].m_normal;
btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
if (normal.dot(rayDir) > 0) {
// normal must always point toward origin of the ray
normal = -normal;
}
btCollisionWorld::LocalRayResult rayResult
(collisionObject,
&shapeInfo,
normal,
softResult.fraction);
bool normalInWorldSpace = true;
resultCallback.addSingleResult(rayResult,normalInWorldSpace);
}
}
}
}
else {
btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,collisionObject,collisionShape,colObjWorldTransform,resultCallback);
}
}

View File

@@ -77,6 +77,17 @@ public:
return m_softBodies; return m_softBodies;
} }
virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
/// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
/// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
/// This allows more customization.
static void rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
btCollisionObject* collisionObject,
const btCollisionShape* collisionShape,
const btTransform& colObjWorldTransform,
RayResultCallback& resultCallback);
}; };
#endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H #endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H

View File

@@ -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_AccumulatorFactory.h"
#include "AUD_AccumulatorReader.h"
AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_IFactory* factory,
bool additive) :
AUD_EffectFactory(factory),
m_additive(additive) {}
AUD_AccumulatorFactory::AUD_AccumulatorFactory(bool additive) :
AUD_EffectFactory(0),
m_additive(additive) {}
AUD_IReader* AUD_AccumulatorFactory::createReader()
{
AUD_IReader* reader = getReader();
if(reader != 0)
{
reader = new AUD_AccumulatorReader(reader, m_additive);
AUD_NEW("reader")
}
return reader;
}

View File

@@ -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_ACCUMULATORFACTORY
#define AUD_ACCUMULATORFACTORY
#include "AUD_EffectFactory.h"
/**
* This factory creates an accumulator reader.
*/
class AUD_AccumulatorFactory : public AUD_EffectFactory
{
private:
/**
* Whether the accumulator is additive.
*/
bool m_additive;
public:
/**
* Creates a new accumulator factory.
* \param factory The input factory.
* \param additive Whether the accumulator is additive.
*/
AUD_AccumulatorFactory(AUD_IFactory* factory, bool additive = false);
/**
* Creates a new accumulator factory.
* \param additive Whether the accumulator is additive.
*/
AUD_AccumulatorFactory(bool additive = false);
virtual AUD_IReader* createReader();
};
#endif //AUD_ACCUMULATORFACTORY

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,124 @@
/*
* $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>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define BWPB41 0.76536686473
#define BWPB42 1.84775906502
#define CC channels + channel
AUD_ButterworthReader::AUD_ButterworthReader(AUD_IReader* reader,
float frequency) :
AUD_EffectReader(reader)
{
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;
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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.0f/(specs.rate * attack));
m_bRelease = pow(arthreshold, 1.0f/(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;
}
}
}

View File

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

View File

@@ -35,35 +35,6 @@ AUD_FaderReader::AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type,
m_start(start), m_start(start),
m_length(length) 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") 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) if(m_type != AUD_FADE_OUT)
{ {
buffer = m_buffer->getBuffer(); buffer = m_buffer->getBuffer();
memset(buffer, memset(buffer, 0, length * samplesize);
specs.format == AUD_FORMAT_U8 ? 0x80 : 0,
length * samplesize);
} }
} }
else if(position / (float)specs.rate >= m_start+m_length) 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) if(m_type == AUD_FADE_OUT)
{ {
buffer = m_buffer->getBuffer(); buffer = m_buffer->getBuffer();
memset(buffer, memset(buffer, 0, length * samplesize);
specs.format == AUD_FORMAT_U8 ? 0x80 : 0,
length * samplesize);
} }
} }
else else
@@ -113,19 +80,21 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer)
sample_t* buf = m_buffer->getBuffer(); sample_t* buf = m_buffer->getBuffer();
float volume; 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(i % specs.channels == 0)
if(volume > 1.0f) {
volume = 1.0f; volume = (((position+i)/(float)specs.rate)-m_start) / m_length;
else if(volume < 0.0f) if(volume > 1.0f)
volume = 0.0f; volume = 1.0f;
else if(volume < 0.0f)
volume = 0.0f;
if(m_type == AUD_FADE_OUT) if(m_type == AUD_FADE_OUT)
volume = 1.0f - volume; volume = 1.0f - volume;
}
m_adjust(buf + i * samplesize, buffer + i * samplesize, buf[i] = buffer[i] * volume;
specs.channels, volume);
} }
buffer = buf; buffer = buf;

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,116 @@
/*
* $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>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define CC channels + channel
AUD_HighpassReader::AUD_HighpassReader(AUD_IReader* reader, float frequency,
float Q) :
AUD_EffectReader(reader)
{
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 * 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;
}
}
}

View File

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

View File

@@ -27,7 +27,6 @@
#include "AUD_Buffer.h" #include "AUD_Buffer.h"
#include <cstring> #include <cstring>
#include <stdio.h>
AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) : AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) :
AUD_EffectReader(reader), m_loop(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) 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; int len = length;
@@ -72,10 +72,10 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer)
{ {
int pos = 0; int pos = 0;
if(m_buffer->getSize() < length*samplesize) if(m_buffer->getSize() < length * samplesize)
m_buffer->resize(length*samplesize); m_buffer->resize(length * samplesize);
memcpy(m_buffer->getBuffer() + pos * samplesize, memcpy(m_buffer->getBuffer() + pos * specs.channels,
buffer, len * samplesize); buffer, len * samplesize);
pos += len; pos += len;
@@ -93,7 +93,7 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer)
if(!len) if(!len)
break; break;
memcpy(m_buffer->getBuffer() + pos * samplesize, memcpy(m_buffer->getBuffer() + pos * specs.channels,
buffer, len * samplesize); buffer, len * samplesize);
pos += len; pos += len;

View File

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

View File

@@ -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.0f);
/**
* Creates a new lowpass factory.
* \param frequency The cutoff frequency.
* \param Q The Q factor.
*/
AUD_LowpassFactory(float frequency, float Q = 1.0f);
virtual AUD_IReader* createReader();
};
#endif //AUD_LOWPASSFACTORY

View File

@@ -0,0 +1,115 @@
/*
* $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>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define CC channels + channel
AUD_LowpassReader::AUD_LowpassReader(AUD_IReader* reader, float frequency,
float Q) :
AUD_EffectReader(reader)
{
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 * 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;
}
}
}

View File

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

View File

@@ -45,7 +45,7 @@ public:
* \param factory The input factory. * \param factory The input factory.
* \param pitch The desired pitch. * \param pitch The desired pitch.
*/ */
AUD_PitchFactory(AUD_IFactory* factory = 0, float pitch = 1.0); AUD_PitchFactory(AUD_IFactory* factory = 0, float pitch = 1.0f);
/** /**
* Creates a new pitch factory. * Creates a new pitch factory.

View File

@@ -26,39 +26,11 @@
#include "AUD_RectifyReader.h" #include "AUD_RectifyReader.h"
#include "AUD_Buffer.h" #include "AUD_Buffer.h"
#include <cstring> #include <cmath>
AUD_RectifyReader::AUD_RectifyReader(AUD_IReader* reader) : AUD_RectifyReader::AUD_RectifyReader(AUD_IReader* reader) :
AUD_EffectReader(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") 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(); AUD_Specs specs = m_reader->getSpecs();
m_reader->read(length, buf); m_reader->read(length, buf);
if(m_buffer->getSize() < length*AUD_SAMPLE_SIZE(specs)) if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs))
m_buffer->resize(length*AUD_SAMPLE_SIZE(specs)); m_buffer->resize(length * AUD_SAMPLE_SIZE(specs));
buffer = m_buffer->getBuffer(); 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]);
} }

View File

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

View File

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

View File

@@ -0,0 +1,57 @@
/*
* $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_SquareFactory.h"
#include "AUD_SquareReader.h"
AUD_SquareFactory::AUD_SquareFactory(AUD_IFactory* factory, float threshold) :
AUD_EffectFactory(factory),
m_threshold(threshold) {}
AUD_SquareFactory::AUD_SquareFactory(float threshold) :
AUD_EffectFactory(0),
m_threshold(threshold) {}
float AUD_SquareFactory::getThreshold()
{
return m_threshold;
}
void AUD_SquareFactory::setThreshold(float threshold)
{
m_threshold = threshold;
}
AUD_IReader* AUD_SquareFactory::createReader()
{
AUD_IReader* reader = getReader();
if(reader != 0)
{
reader = new AUD_SquareReader(reader, m_threshold); AUD_NEW("reader")
}
return reader;
}

View File

@@ -23,54 +23,48 @@
* ***** END LGPL LICENSE BLOCK ***** * ***** END LGPL LICENSE BLOCK *****
*/ */
#ifndef AUD_SDLMIXER #ifndef AUD_SQUAREFACTORY
#define AUD_SDLMIXER #define AUD_SQUAREFACTORY
#include "AUD_IMixer.h" #include "AUD_EffectFactory.h"
class AUD_SDLMixerFactory;
#include <list>
struct AUD_SDLMixerBuffer
{
sample_t* buffer;
int length;
float volume;
};
/** /**
* This class is able to mix audiosignals with the help of SDL. * This factory Transforms any signal to a square signal.
*/ */
class AUD_SDLMixer : public AUD_IMixer class AUD_SquareFactory : public AUD_EffectFactory
{ {
private: private:
/** /**
* The mixer factory that prepares all readers for superposition. * The threshold.
*/ */
AUD_SDLMixerFactory* m_factory; float m_threshold;
/**
* The list of buffers to superpose.
*/
std::list<AUD_SDLMixerBuffer> m_buffers;
/**
* The size of an output sample.
*/
int m_samplesize;
public: public:
/** /**
* Creates the mixer. * Creates a new square factory.
* \param factory The input factory.
* \param threshold The threshold.
*/ */
AUD_SDLMixer(); AUD_SquareFactory(AUD_IFactory* factory = 0, float threshold = 0.0f);
virtual ~AUD_SDLMixer(); /**
* Creates a new square factory.
* \param threshold The threshold.
*/
AUD_SquareFactory(float threshold);
virtual AUD_IReader* prepare(AUD_IReader* reader); /**
virtual void setSpecs(AUD_Specs specs); * Returns the threshold.
virtual void add(sample_t* buffer, AUD_Specs specs, int length, */
float volume); float getThreshold();
virtual void superpose(sample_t* buffer, int length, float volume);
/**
* Sets the threshold.
* \param threshold The new threshold value. Should be between 0.0 and 1.0.
*/
void setThreshold(float threshold);
virtual AUD_IReader* createReader();
}; };
#endif //AUD_SDLMIXER #endif //AUD_SQUAREFACTORY

View File

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

View File

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

View File

@@ -0,0 +1,43 @@
/*
* $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_SumFactory.h"
#include "AUD_SumReader.h"
AUD_SumFactory::AUD_SumFactory(AUD_IFactory* factory) :
AUD_EffectFactory(factory) {}
AUD_IReader* AUD_SumFactory::createReader()
{
AUD_IReader* reader = getReader();
if(reader != 0)
{
reader = new AUD_SumReader(reader);
AUD_NEW("reader")
}
return reader;
}

View File

@@ -23,23 +23,24 @@
* ***** END LGPL LICENSE BLOCK ***** * ***** END LGPL LICENSE BLOCK *****
*/ */
#ifndef AUD_SDLMIXERFACTORY #ifndef AUD_SUMFACTORY
#define AUD_SDLMIXERFACTORY #define AUD_SUMFACTORY
#include "AUD_MixerFactory.h" #include "AUD_EffectFactory.h"
/** /**
* This factory creates a resampling reader that uses SDL's resampling * This factory creates a sum reader.
* functionality which unfortunately is very very very limited.
*/ */
class AUD_SDLMixerFactory : public AUD_MixerFactory class AUD_SumFactory : public AUD_EffectFactory
{ {
public: public:
AUD_SDLMixerFactory(AUD_IReader* reader, AUD_Specs specs); /**
AUD_SDLMixerFactory(AUD_IFactory* factory, AUD_Specs specs); * Creates a new sum factory.
AUD_SDLMixerFactory(AUD_Specs specs); * \param factory The input factory.
*/
AUD_SumFactory(AUD_IFactory* factory = 0);
virtual AUD_IReader* createReader(); virtual AUD_IReader* createReader();
}; };
#endif //AUD_SDLMIXERFACTORY #endif //AUD_SUMFACTORY

View File

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

View File

@@ -0,0 +1,64 @@
/*
* $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_SUMREADER
#define AUD_SUMREADER
#include "AUD_EffectReader.h"
class AUD_Buffer;
/**
* This class represents an summer.
*/
class AUD_SumReader : public AUD_EffectReader
{
private:
/**
* The playback buffer.
*/
AUD_Buffer *m_buffer;
/**
* The sums of the specific channels.
*/
AUD_Buffer *m_sums;
public:
/**
* Creates a new sum reader.
* \param reader The reader to read from.
* \exception AUD_Exception Thrown if the reader specified is NULL.
*/
AUD_SumReader(AUD_IReader* reader);
/**
* Destroys the reader.
*/
virtual ~AUD_SumReader();
virtual void read(int & length, sample_t* & buffer);
};
#endif //AUD_SUMREADER

View File

@@ -47,7 +47,7 @@ public:
* \param factory The input factory. * \param factory The input factory.
* \param volume The desired volume. * \param volume The desired volume.
*/ */
AUD_VolumeFactory(AUD_IFactory* factory = 0, float volume = 1.0); AUD_VolumeFactory(AUD_IFactory* factory = 0, float volume = 1.0f);
/** /**
* Creates a new volume factory. * Creates a new volume factory.

View File

@@ -32,35 +32,6 @@ AUD_VolumeReader::AUD_VolumeReader(AUD_IReader* reader, float volume) :
AUD_EffectReader(reader), AUD_EffectReader(reader),
m_volume(volume) 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") 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(); 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;
} }

View File

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

View File

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

View File

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

View File

@@ -36,4 +36,7 @@ if env['WITH_BF_FFTW3']:
incs += ' fftw ' + env['BF_FFTW3_INC'] incs += ' fftw ' + env['BF_FFTW3_INC']
defs.append('WITH_FFTW3') defs.append('WITH_FFTW3')
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
incs += ' ' + env['BF_PTHREADS_INC']
env.BlenderLib ('bf_audaspace', sources, Split(incs), defs, libtype=['intern','player'], priority = [25,215] ) env.BlenderLib ('bf_audaspace', sources, Split(incs), defs, libtype=['intern','player'], priority = [25,215] )

View File

@@ -23,7 +23,6 @@
* ***** END LGPL LICENSE BLOCK ***** * ***** END LGPL LICENSE BLOCK *****
*/ */
#include "AUD_SDLMixer.h"
#include "AUD_SDLDevice.h" #include "AUD_SDLDevice.h"
#include "AUD_IReader.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; 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) if(specs.channels == AUD_CHANNELS_INVALID)
specs.channels = AUD_CHANNELS_STEREO; specs.channels = AUD_CHANNELS_STEREO;
@@ -69,9 +68,6 @@ AUD_SDLDevice::AUD_SDLDevice(AUD_Specs specs, int buffersize)
else else
AUD_THROW(AUD_ERROR_SDL); AUD_THROW(AUD_ERROR_SDL);
m_mixer = new AUD_SDLMixer(); AUD_NEW("mixer")
m_mixer->setSpecs(m_specs);
create(); create();
} }

View File

@@ -55,7 +55,8 @@ public:
* \note The specification really used for opening the device may differ. * \note The specification really used for opening the device may differ.
* \exception AUD_Exception Thrown if the audio device cannot be opened. * \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. * Closes the SDL audio device.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -32,13 +32,7 @@ class AUD_Buffer;
#include <samplerate.h> #include <samplerate.h>
/** /**
* This class mixes a sound source with help of the SDL library. * This resampling reader uses libsamplerate for resampling.
* 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_SRCResampleReader : public AUD_EffectReader class AUD_SRCResampleReader : public AUD_EffectReader
{ {

View File

@@ -34,26 +34,6 @@ extern "C" {
#include <libavformat/avformat.h> #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) int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer)
{ {
// save packet parameters // save packet parameters
@@ -78,11 +58,11 @@ int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer)
// read samples from the packet // read samples from the packet
data_size = buf_size - buf_pos; data_size = buf_size - buf_pos;
/*read_length = avcodec_decode_audio3(m_codecCtx, /*read_length = avcodec_decode_audio3(m_codecCtx,
(int16_t*)(buffer->getBuffer()+buf_pos), (int16_t*)(((data_t*)buffer->getBuffer())+buf_pos),
&data_size, &data_size,
packet);*/ packet);*/
read_length = avcodec_decode_audio2(m_codecCtx, read_length = avcodec_decode_audio2(m_codecCtx,
(int16_t*)(buffer->getBuffer()+buf_pos), (int16_t*)(((data_t*)buffer->getBuffer())+buf_pos),
&data_size, &data_size,
audio_pkg_data, audio_pkg_data,
audio_pkg_size); audio_pkg_size);
@@ -101,10 +81,78 @@ int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer)
return buf_pos; return buf_pos;
} }
AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename) void AUD_FFMPEGReader::init()
{ {
m_position = 0; m_position = 0;
m_pkgbuf_left = 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; m_byteiocontext = NULL;
// open file // open file
@@ -113,66 +161,28 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename)
try try
{ {
if(av_find_stream_info(m_formatCtx)<0) init();
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;
} }
catch(AUD_Exception) catch(AUD_Exception)
{ {
av_close_input_file(m_formatCtx); av_close_input_file(m_formatCtx);
throw; 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) AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer)
{ {
m_position = 0;
m_pkgbuf_left = 0;
m_byteiocontext = (ByteIOContext*)av_mallocz(sizeof(ByteIOContext)); m_byteiocontext = (ByteIOContext*)av_mallocz(sizeof(ByteIOContext));
AUD_NEW("byteiocontext") AUD_NEW("byteiocontext")
m_membuffer = buffer; m_membuffer = buffer;
if(init_put_byte(m_byteiocontext, buffer.get()->getBuffer(), buffer.get()->getSize(), 0, if(init_put_byte(m_byteiocontext, (data_t*)buffer.get()->getBuffer(),
NULL, NULL, NULL, NULL) != 0) buffer.get()->getSize(), 0, NULL, NULL, NULL, NULL) != 0)
AUD_THROW(AUD_ERROR_FILE); AUD_THROW(AUD_ERROR_FILE);
AVProbeData probe_data; AVProbeData probe_data;
probe_data.filename = ""; probe_data.filename = "";
probe_data.buf = buffer.get()->getBuffer(); probe_data.buf = (data_t*)buffer.get()->getBuffer();
probe_data.buf_size = buffer.get()->getSize(); probe_data.buf_size = buffer.get()->getSize();
AVInputFormat* fmt = av_probe_input_format(&probe_data, 1); AVInputFormat* fmt = av_probe_input_format(&probe_data, 1);
@@ -182,38 +192,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer)
try try
{ {
if(av_find_stream_info(m_formatCtx)<0) init();
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;
} }
catch(AUD_Exception) catch(AUD_Exception)
{ {
@@ -221,11 +200,6 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer)
av_free(m_byteiocontext); AUD_DELETE("byteiocontext") av_free(m_byteiocontext); AUD_DELETE("byteiocontext")
throw; 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_FFMPEGReader::~AUD_FFMPEGReader()
@@ -316,7 +290,7 @@ int AUD_FFMPEGReader::getPosition()
AUD_Specs AUD_FFMPEGReader::getSpecs() AUD_Specs AUD_FFMPEGReader::getSpecs()
{ {
return m_specs; return m_specs.specs;
} }
AUD_ReaderType AUD_FFMPEGReader::getType() AUD_ReaderType AUD_FFMPEGReader::getType()
@@ -336,11 +310,11 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
int data_size = 0; int data_size = 0;
int pkgbuf_pos; int pkgbuf_pos;
int left = length; 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 // resize output buffer if necessary
if(m_buffer->getSize() < length*sample_size) if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(m_specs))
m_buffer->resize(length*sample_size); m_buffer->resize(length * AUD_SAMPLE_SIZE(m_specs));
buffer = m_buffer->getBuffer(); buffer = m_buffer->getBuffer();
pkgbuf_pos = m_pkgbuf_left; pkgbuf_pos = m_pkgbuf_left;
@@ -350,8 +324,9 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
if(pkgbuf_pos > 0) if(pkgbuf_pos > 0)
{ {
data_size = AUD_MIN(pkgbuf_pos, left * sample_size); data_size = AUD_MIN(pkgbuf_pos, left * sample_size);
memcpy(buffer, m_pkgbuf->getBuffer(), data_size); m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(),
buffer += data_size; data_size / AUD_FORMAT_SIZE(m_specs.format));
buffer += data_size / AUD_FORMAT_SIZE(m_specs.format);
left -= data_size/sample_size; left -= data_size/sample_size;
} }
@@ -366,8 +341,9 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
// copy to output buffer // copy to output buffer
data_size = AUD_MIN(pkgbuf_pos, left * sample_size); data_size = AUD_MIN(pkgbuf_pos, left * sample_size);
memcpy(buffer, m_pkgbuf->getBuffer(), data_size); m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(),
buffer += data_size; data_size / AUD_FORMAT_SIZE(m_specs.format));
buffer += data_size / AUD_FORMAT_SIZE(m_specs.format);
left -= data_size/sample_size; left -= data_size/sample_size;
} }
av_free_packet(&packet); av_free_packet(&packet);
@@ -376,7 +352,8 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
if(pkgbuf_pos > data_size) if(pkgbuf_pos > data_size)
{ {
m_pkgbuf_left = 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); pkgbuf_pos-data_size);
} }

View File

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

View File

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

View File

@@ -77,7 +77,6 @@ void AUD_BandPassReader::read(int & length, sample_t* & buffer)
} }
m_length = length; m_length = length;
printf("WINDOW: %d\n", m_length);
if(m_length * sizeof(double) > m_in->getSize()) if(m_length * sizeof(double) > m_in->getSize())
{ {
@@ -95,22 +94,21 @@ void AUD_BandPassReader::read(int & length, sample_t* & buffer)
FFTW_ESTIMATE); FFTW_ESTIMATE);
} }
float* source = (float*) buffer;
double* target = (double*) m_in->getBuffer(); 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(); fftw_complex* complex = (fftw_complex*) m_out->getBuffer();
float frequency; float frequency;
for(int channel = 0; channel < specs.channels; channel++) for(int channel = 0; channel < specs.channels; channel++)
{ {
for(int i = 0; i < m_length; i++) 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); fftw_execute(m_forward);
for(int i = 0; i < m_length / 2 + 1; i++) for(int i = 0; i < m_length / 2 + 1; i++)
{ {
frequency = i * specs.rate / (m_length / 2.0 + 1.0); frequency = i * specs.rate / (m_length / 2.0f + 1.0f);
if((frequency < m_low) || (frequency > m_high)) if((frequency < m_low) || (frequency > m_high))
complex[i][0] = complex[i][1] = 0.0; complex[i][0] = complex[i][1] = 0.0;
} }

View File

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

View File

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

View File

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

View File

@@ -23,6 +23,9 @@
* ***** END LGPL LICENSE BLOCK ***** * ***** END LGPL LICENSE BLOCK *****
*/ */
#include <cstdlib>
#include <cstring>
#include "AUD_NULLDevice.h" #include "AUD_NULLDevice.h"
#include "AUD_I3DDevice.h" #include "AUD_I3DDevice.h"
#include "AUD_FileFactory.h" #include "AUD_FileFactory.h"
@@ -32,13 +35,21 @@
#include "AUD_PingPongFactory.h" #include "AUD_PingPongFactory.h"
#include "AUD_LoopFactory.h" #include "AUD_LoopFactory.h"
#include "AUD_RectifyFactory.h" #include "AUD_RectifyFactory.h"
#include "AUD_EnvelopeFactory.h"
#include "AUD_LinearResampleFactory.h"
#include "AUD_LowpassFactory.h"
#include "AUD_HighpassFactory.h"
#include "AUD_AccumulatorFactory.h"
#include "AUD_SumFactory.h"
#include "AUD_SquareFactory.h"
#include "AUD_ChannelMapperFactory.h"
#include "AUD_Buffer.h"
#include "AUD_ReadDevice.h" #include "AUD_ReadDevice.h"
#include "AUD_SourceCaps.h" #include "AUD_SourceCaps.h"
#include "AUD_IReader.h" #include "AUD_IReader.h"
#ifdef WITH_SDL #ifdef WITH_SDL
#include "AUD_SDLDevice.h" #include "AUD_SDLDevice.h"
#include "AUD_FloatMixer.h"
#endif #endif
#ifdef WITH_OPENAL #ifdef WITH_OPENAL
@@ -55,7 +66,7 @@ extern "C" {
} }
#endif #endif
#include <assert.h> #include <cassert>
typedef AUD_IFactory AUD_Sound; typedef AUD_IFactory AUD_Sound;
typedef AUD_ReadDevice AUD_Device; typedef AUD_ReadDevice AUD_Device;
@@ -71,7 +82,7 @@ static AUD_IDevice* AUD_device = NULL;
static int AUD_available_devices[4]; static int AUD_available_devices[4];
static AUD_I3DDevice* AUD_3ddevice = NULL; 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 #ifdef WITH_FFMPEG
av_register_all(); av_register_all();
@@ -90,12 +101,8 @@ int AUD_init(AUD_DeviceType device, AUD_Specs specs, int buffersize)
break; break;
#ifdef WITH_SDL #ifdef WITH_SDL
case AUD_SDL_DEVICE: case AUD_SDL_DEVICE:
{ dev = new AUD_SDLDevice(specs, buffersize);
dev = new AUD_SDLDevice(specs, buffersize); break;
AUD_FloatMixer* mixer = new AUD_FloatMixer();
((AUD_SDLDevice*)dev)->setMixer(mixer);
break;
}
#endif #endif
#ifdef WITH_OPENAL #ifdef WITH_OPENAL
case AUD_OPENAL_DEVICE: case AUD_OPENAL_DEVICE:
@@ -177,9 +184,8 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
else else
{ {
info.specs.channels = AUD_CHANNELS_INVALID; info.specs.channels = AUD_CHANNELS_INVALID;
info.specs.format = AUD_FORMAT_INVALID;
info.specs.rate = AUD_RATE_INVALID; info.specs.rate = AUD_RATE_INVALID;
info.length = 0.0; info.length = 0.0f;
} }
return info; return info;
@@ -424,7 +430,7 @@ float AUD_get3DSetting(AUD_3DSetting setting)
catch(AUD_Exception) catch(AUD_Exception)
{ {
} }
return 0.0; return 0.0f;
} }
int AUD_update3DSource(AUD_Handle* handle, AUD_3DData* data) int AUD_update3DSource(AUD_Handle* handle, AUD_3DData* data)
@@ -480,7 +486,7 @@ float AUD_get3DSourceSetting(AUD_Handle* handle, AUD_3DSourceSetting setting)
{ {
} }
} }
return 0.0; return 0.0f;
} }
int AUD_setSoundVolume(AUD_Handle* handle, float volume) int AUD_setSoundVolume(AUD_Handle* handle, float volume)
@@ -519,7 +525,7 @@ int AUD_setSoundPitch(AUD_Handle* handle, float pitch)
return false; return false;
} }
AUD_Device* AUD_openReadDevice(AUD_Specs specs) AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs)
{ {
try try
{ {
@@ -578,7 +584,7 @@ int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Handle* handle,
return false; 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(device);
assert(buffer); assert(buffer);
@@ -605,3 +611,55 @@ void AUD_closeReadDevice(AUD_Device* device)
{ {
} }
} }
float* AUD_readSoundBuffer(const char* filename, float low, float high,
float attack, float release, float threshold,
int accumulate, int additive, int square,
float sthreshold, int samplerate, int* length)
{
AUD_Buffer buffer;
AUD_DeviceSpecs specs;
specs.channels = AUD_CHANNELS_MONO;
specs.rate = (AUD_SampleRate)samplerate;
AUD_Sound* sound;
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);
sound = &resampler;
AUD_SquareFactory squaref(sound, sthreshold);
if(square)
sound = &squaref;
AUD_AccumulatorFactory accumulator(sound, additive);
AUD_SumFactory sum(sound);
if(accumulate)
sound = &accumulator;
else if(additive)
sound = &sum;
AUD_IReader* reader = sound->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;
}

View File

@@ -59,7 +59,7 @@ typedef struct
* \param buffersize The buffersize for the device. * \param buffersize The buffersize for the device.
* \return Whether the device has been initialized. * \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 * 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. * \param specs The specification of the audio data.
* \return A device handle. * \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. * 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 * played back currently, in that case the buffer is filled with
* silence. * 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. * Closes a read device.
@@ -350,6 +350,16 @@ extern int AUD_readDevice(AUD_Device* device, sample_t* buffer, int length);
*/ */
extern void AUD_closeReadDevice(AUD_Device* device); 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 accumulate, int additive, int square,
float sthreshold, int samplerate,
int* length);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

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

View File

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

View File

@@ -32,12 +32,6 @@ AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader,
{ {
m_specs = reader->getSpecs(); 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; int channels = -1;
m_rch = m_specs.channels; m_rch = m_specs.channels;
while(mapping[++channels] != 0); while(mapping[++channels] != 0);
@@ -55,7 +49,8 @@ AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader,
for(i=0; i < m_rch; i++) for(i=0; i < m_rch; i++)
sum += mapping[channels][i]; sum += mapping[channels][i];
for(i=0; i < m_rch; i++) for(i=0; i < m_rch; i++)
m_mapping[channels][i] = sum > 0.0 ? mapping[channels][i]/sum : 0.0; m_mapping[channels][i] = sum > 0.0f ?
mapping[channels][i]/sum : 0.0f;
} }
m_buffer = new AUD_Buffer(); AUD_NEW("buffer") m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
@@ -89,9 +84,9 @@ void AUD_ChannelMapperReader::read(int & length, sample_t* & buffer)
if(m_buffer->getSize() < length * 4 * channels) if(m_buffer->getSize() < length * 4 * channels)
m_buffer->resize(length * 4 * channels); m_buffer->resize(length * 4 * channels);
float* in = (float*)buffer; sample_t* in = buffer;
float* out = (float*)m_buffer->getBuffer(); sample_t* out = m_buffer->getBuffer();
float sum; sample_t sum;
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
{ {

View File

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

View File

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

View File

@@ -29,21 +29,21 @@
#define AUD_U8_0 0x80 #define AUD_U8_0 0x80
#define AUD_S16_MAX 0x7FFF #define AUD_S16_MAX 0x7FFF
#define AUD_S16_MIN 0x8000 #define AUD_S16_MIN 0x8000
#define AUD_S16_FLT 32768.0 #define AUD_S16_FLT 32768.0f
#define AUD_S32_MAX 0x7FFFFFFF #define AUD_S32_MAX 0x7FFFFFFF
#define AUD_S32_MIN 0x80000000 #define AUD_S32_MIN 0x80000000
#define AUD_S32_FLT 2147483648.0 #define AUD_S32_FLT 2147483648.0f
#define AUD_FLT_MAX 1.0 #define AUD_FLT_MAX 1.0f
#define AUD_FLT_MIN -1.0 #define AUD_FLT_MIN -1.0f
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; int16_t* t = (int16_t*) target;
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
t[i] = (((int16_t)source[i]) - AUD_U8_0) << 8; 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++) 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++) 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; int32_t* t = (int32_t*) target;
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
t[i] = (((int32_t)source[i]) - AUD_U8_0) << 24; 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; float* t = (float*) target;
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((float)AUD_U8_0); 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; double* t = (double*) target;
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((double)AUD_U8_0); 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; int16_t* s = (int16_t*) source;
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
target[i] = (unsigned char)((s[i] >> 8) + AUD_U8_0); 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; int16_t* s = (int16_t*) source;
for(int i = 0; i < length; i++) 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; int16_t* s = (int16_t*) source;
for(int i = 0; i < length; i++) 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; int16_t* s = (int16_t*) source;
int32_t* t = (int32_t*) target; 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; 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; int16_t* s = (int16_t*) source;
float* t = (float*) target; 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; 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; int16_t* s = (int16_t*) source;
double* t = (double*) target; 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; 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++) for(int i = 0; i < length; i++)
target[i] = source[i*3] ^ AUD_U8_0; 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++) for(int i = 0; i < length; i++)
target[i] = source[i*3+2] ^ AUD_U8_0; 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; int16_t* t = (int16_t*) target;
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
t[i] = source[i*3] << 8 | source[i*3+1]; 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; int16_t* t = (int16_t*) target;
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
t[i] = source[i*3+2] << 8 | source[i*3+1]; 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); 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; int32_t* t = (int32_t*) target;
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
t[i] = source[i*3] << 24 | source[i*3+1] << 16 | source[i*3+2] << 8; 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; int32_t* t = (int32_t*) target;
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
t[i] = source[i*3+2] << 24 | source[i*3+1] << 16 | source[i*3] << 8; 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; float* t = (float*) target;
int32_t s; 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; float* t = (float*) target;
int32_t s; 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; double* t = (double*) target;
int32_t s; 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; double* t = (double*) target;
int32_t s; 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; int16_t* s = (int16_t*) source;
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
target[i] = (unsigned char)((s[i] >> 24) + AUD_U8_0); 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; int16_t* t = (int16_t*) target;
int32_t* s = (int32_t*) source; 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; 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; int32_t* s = (int32_t*) source;
for(int i = 0; i < length; i++) 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; int16_t* s = (int16_t*) source;
for(int i = 0; i < length; i++) 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; int32_t* s = (int32_t*) source;
float* t = (float*) target; 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; 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; int32_t* s = (int32_t*) source;
double* t = (double*) target; 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; 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* s = (float*) source;
float t; 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; int16_t* t = (int16_t*) target;
float* s = (float*) source; 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; int32_t t;
float* s = (float*) source; 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; int32_t t;
float* s = (float*) source; 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; int32_t* t = (int32_t*) target;
float* s = (float*) source; 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; float* s = (float*) source;
double* t = (double*) target; 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]; 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* s = (double*) source;
double t; 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; int16_t* t = (int16_t*) target;
double* s = (double*) source; 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; int32_t t;
double* s = (double*) source; 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; int32_t t;
double* s = (double*) source; 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; int32_t* t = (int32_t*) target;
double* s = (double*) source; 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; double* s = (double*) source;
float* t = (float*) target; float* t = (float*) target;
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
t[i] = s[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;
}
}

View File

@@ -41,133 +41,94 @@
#include <stdint.h> #include <stdint.h>
#endif #endif
typedef void (*AUD_convert_f)(sample_t* target, sample_t* source, int length); typedef void (*AUD_convert_f)(data_t* target, data_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);
template <class T> 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)); 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); void AUD_convert_double_float(data_t* target, data_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);
#endif //AUD_CONVERTERFUNCTIONS #endif //AUD_CONVERTERFUNCTIONS

View File

@@ -26,205 +26,37 @@
#include "AUD_ConverterReader.h" #include "AUD_ConverterReader.h"
#include "AUD_Buffer.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) AUD_EffectReader(reader)
{ {
m_specs = reader->getSpecs(); m_specs.specs = reader->getSpecs();
int bigendian = 1; int bigendian = 1;
bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
switch(m_specs.format) switch(specs.format)
{ {
case AUD_FORMAT_U8: case AUD_FORMAT_U8:
switch(specs.format) m_convert = AUD_convert_float_u8;
{
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;
}
break; break;
case AUD_FORMAT_S16: case AUD_FORMAT_S16:
switch(specs.format) m_convert = AUD_convert_float_s16;
{
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;
}
break; break;
case AUD_FORMAT_S24: case AUD_FORMAT_S24:
if(bigendian) if(bigendian)
switch(specs.format) m_convert = AUD_convert_float_s24_be;
{
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;
}
else else
switch(specs.format) m_convert = AUD_convert_float_s24_le;
{
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;
}
break; break;
case AUD_FORMAT_S32: case AUD_FORMAT_S32:
switch(specs.format) m_convert = AUD_convert_float_s32;
{
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;
}
break; break;
case AUD_FORMAT_FLOAT32: case AUD_FORMAT_FLOAT32:
switch(specs.format) m_convert = AUD_convert_copy<float>;
{
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;
}
break; break;
case AUD_FORMAT_FLOAT64: case AUD_FORMAT_FLOAT64:
switch(specs.format) m_convert = AUD_convert_float_double;
{
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;
}
break; break;
default: default:
break; break;
@@ -242,7 +74,7 @@ AUD_ConverterReader::~AUD_ConverterReader()
AUD_Specs AUD_ConverterReader::getSpecs() AUD_Specs AUD_ConverterReader::getSpecs()
{ {
return m_specs; return m_specs.specs;
} }
void AUD_ConverterReader::read(int & length, sample_t* & buffer) 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) if(m_buffer->getSize() < length*samplesize)
m_buffer->resize(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(); buffer = m_buffer->getBuffer();
} }

View File

@@ -44,7 +44,7 @@ private:
/** /**
* The target specification. * The target specification.
*/ */
AUD_Specs m_specs; AUD_DeviceSpecs m_specs;
/** /**
* Converter function. * Converter function.
@@ -58,7 +58,7 @@ public:
* \param specs The target specification. * \param specs The target specification.
* \exception AUD_Exception Thrown if the reader is NULL. * \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. * Destroys the reader.
*/ */

View File

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

View File

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

View File

@@ -23,42 +23,30 @@
* ***** END LGPL LICENSE BLOCK ***** * ***** END LGPL LICENSE BLOCK *****
*/ */
#include "AUD_SDLMixerFactory.h" #include "AUD_LinearResampleFactory.h"
#include "AUD_SDLMixerReader.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_LinearResampleFactory::AUD_LinearResampleFactory(AUD_IFactory* factory,
AUD_MixerFactory(reader, specs) {} AUD_DeviceSpecs specs) :
AUD_ResampleFactory(factory, specs) {}
AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_IFactory* factory, AUD_Specs specs) : AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_DeviceSpecs specs) :
AUD_MixerFactory(factory, specs) {} AUD_ResampleFactory(specs) {}
AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_Specs specs) : AUD_IReader* AUD_LinearResampleFactory::createReader()
AUD_MixerFactory(specs) {}
AUD_IReader* AUD_SDLMixerFactory::createReader()
{ {
AUD_IReader* reader = getReader(); AUD_IReader* reader = getReader();
if(reader != 0) if(reader != 0)
{ {
AUD_Specs specs = reader->getSpecs(); if(reader->getSpecs().rate != m_specs.rate)
if(memcmp(&m_specs, &specs, sizeof(AUD_Specs)) != 0)
{ {
try reader = new AUD_LinearResampleReader(reader, m_specs.specs);
{ AUD_NEW("reader")
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;
}
} }
} }
return reader; return reader;

View File

@@ -0,0 +1,44 @@
/*
* $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_LINEARRESAMPLEFACTORY
#define AUD_LINEARRESAMPLEFACTORY
#include "AUD_ResampleFactory.h"
/**
* This factory creates a resampling reader that does simple linear resampling.
*/
class AUD_LinearResampleFactory : public AUD_ResampleFactory
{
public:
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_LINEARRESAMPLEFACTORY

View File

@@ -0,0 +1,133 @@
/*
* $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>
#define CC channels + channel
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 samplesize = AUD_SAMPLE_SIZE(m_tspecs);
int size = length * samplesize;
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) < 0)
{
low = m_cache->getBuffer()[(int)(floor(spos) + 2) * CC];
if(ceil(spos) < 0)
high = m_cache->getBuffer()[(int)(ceil(spos) + 2) * CC];
else
high = buf[(int)ceil(spos) * CC];
}
else
{
low = buf[(int)floor(spos) * CC];
high = buf[(int)ceil(spos) * CC];
}
buffer[i * CC] = low + (spos - floor(spos)) * (high - low);
}
}
if(len > 1)
memcpy(m_cache->getBuffer(),
buf + (len - 2) * channels,
2 * samplesize);
else if(len == 1)
memcpy(m_cache->getBuffer() + 1 * channels, buf, samplesize);
m_sposition += len;
m_position += length;
}

View File

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

View File

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

View File

@@ -23,47 +23,95 @@
* ***** END LGPL LICENSE BLOCK ***** * ***** END LGPL LICENSE BLOCK *****
*/ */
#ifndef AUD_IMIXER #ifndef AUD_MIXER
#define AUD_IMIXER #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; 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. * This class is able to mix audiosignals of different channel count and sample
* \note This class doesn't do resampling! * 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: public:
/**
* Creates the mixer.
*/
AUD_Mixer();
/** /**
* Destroys the mixer. * Destroys the mixer.
*/ */
virtual ~AUD_IMixer(){} ~AUD_Mixer();
/** /**
* This funuction prepares a reader for playback. * This funuction prepares a reader for playback.
* \param reader The reader to prepare. * \param reader The reader to prepare.
* \return The reader that should be used for playback. * \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. * Sets the target specification for superposing.
* \param specs The target specification. * \param specs The target specification.
*/ */
virtual void setSpecs(AUD_Specs specs)=0; void setSpecs(AUD_DeviceSpecs specs);
/** /**
* Adds a buffer for superposition. * Adds a buffer for superposition.
* \param buffer The buffer to superpose. * \param buffer The buffer to superpose.
* \param specs The specification of the buffer.
* \param start The start sample of the buffer. * \param start The start sample of the buffer.
* \param length The length of the buffer in samples. * \param length The length of the buffer in samples.
* \param volume The mixing volume. Must be a value between 0.0 and 1.0. * \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, void add(sample_t* buffer, int length, float volume);
float volume)=0;
/** /**
* Superposes all added buffers into an output buffer. * Superposes all added buffers into an output buffer.
@@ -71,7 +119,7 @@ public:
* \param length The length of the buffer in samples. * \param length The length of the buffer in samples.
* \param volume The mixing volume. Must be a value between 0.0 and 1.0. * \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

View File

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

View File

@@ -47,7 +47,7 @@ protected:
/** /**
* The target specification for resampling. * 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. * 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 reader The reader to mix.
* \param specs The target specification. * \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. * Creates a new factory.
* \param factory The factory to create the readers to mix out of. * \param factory The factory to create the readers to mix out of.
* \param specs The target specification. * \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. * Creates a new factory.
* \param specs The target specification. * \param specs The target specification.
*/ */
AUD_MixerFactory(AUD_Specs specs); AUD_MixerFactory(AUD_DeviceSpecs specs);
/** /**
* Destroys the resampling factory. * Destroys the resampling factory.
@@ -86,13 +86,13 @@ public:
/** /**
* Returns the target specification for resampling. * Returns the target specification for resampling.
*/ */
AUD_Specs getSpecs(); AUD_DeviceSpecs getSpecs();
/** /**
* Sets the target specification for resampling. * Sets the target specification for resampling.
* \param specs The specification. * \param specs The specification.
*/ */
void setSpecs(AUD_Specs specs); void setSpecs(AUD_DeviceSpecs specs);
/** /**
* Sets the reader for resampling. * Sets the reader for resampling.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -25,7 +25,7 @@
#include "AUD_SoftwareDevice.h" #include "AUD_SoftwareDevice.h"
#include "AUD_IReader.h" #include "AUD_IReader.h"
#include "AUD_IMixer.h" #include "AUD_Mixer.h"
#include "AUD_IFactory.h" #include "AUD_IFactory.h"
#include "AUD_SourceCaps.h" #include "AUD_SourceCaps.h"
@@ -51,7 +51,9 @@ void AUD_SoftwareDevice::create()
m_playingSounds = new std::list<AUD_SoftwareHandle*>(); AUD_NEW("list") m_playingSounds = new std::list<AUD_SoftwareHandle*>(); AUD_NEW("list")
m_pausedSounds = new std::list<AUD_SoftwareHandle*>(); AUD_NEW("list") m_pausedSounds = new std::list<AUD_SoftwareHandle*>(); AUD_NEW("list")
m_playback = false; m_playback = false;
m_volume = 1.0; m_volume = 1.0f;
m_mixer = new AUD_Mixer(); AUD_NEW("mixer")
m_mixer->setSpecs(m_specs);
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); pthread_mutexattr_init(&attr);
@@ -90,7 +92,7 @@ void AUD_SoftwareDevice::destroy()
pthread_mutex_destroy(&m_mutex); pthread_mutex_destroy(&m_mutex);
} }
void AUD_SoftwareDevice::mix(sample_t* buffer, int length) void AUD_SoftwareDevice::mix(data_t* buffer, int length)
{ {
lock(); lock();
@@ -98,7 +100,7 @@ void AUD_SoftwareDevice::mix(sample_t* buffer, int length)
AUD_SoftwareHandle* sound; AUD_SoftwareHandle* sound;
int len; int len;
sample_t* buf; 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; std::list<AUD_SoftwareHandle*> stopSounds;
// for all sounds // for all sounds
@@ -114,7 +116,7 @@ void AUD_SoftwareDevice::mix(sample_t* buffer, int length)
len = length; len = length;
sound->reader->read(len, buf); 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 // in case the end of the sound is reached
if(len < length) if(len < length)
@@ -159,14 +161,7 @@ bool AUD_SoftwareDevice::isValid(AUD_Handle* handle)
return false; return false;
} }
void AUD_SoftwareDevice::setMixer(AUD_IMixer* mixer) AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs()
{
delete m_mixer; AUD_DELETE("mixer")
m_mixer = mixer;
mixer->setSpecs(m_specs);
}
AUD_Specs AUD_SoftwareDevice::getSpecs()
{ {
return m_specs; return m_specs;
} }
@@ -189,7 +184,7 @@ AUD_Handle* AUD_SoftwareDevice::play(AUD_IFactory* factory, bool keep)
AUD_SoftwareHandle* sound = new AUD_SoftwareHandle; AUD_NEW("handle") AUD_SoftwareHandle* sound = new AUD_SoftwareHandle; AUD_NEW("handle")
sound->keep = keep; sound->keep = keep;
sound->reader = reader; sound->reader = reader;
sound->volume = 1.0; sound->volume = 1.0f;
lock(); lock();
m_playingSounds->push_back(sound); m_playingSounds->push_back(sound);
@@ -426,10 +421,10 @@ bool AUD_SoftwareDevice::setCapability(int capability, void *value)
case AUD_CAPS_VOLUME: case AUD_CAPS_VOLUME:
lock(); lock();
m_volume = *((float*)value); m_volume = *((float*)value);
if(m_volume > 1.0) if(m_volume > 1.0f)
m_volume = 1.0; m_volume = 1.0f;
else if(m_volume < 0.0) else if(m_volume < 0.0f)
m_volume = 0.0; m_volume = 0.0f;
unlock(); unlock();
return true; return true;
case AUD_CAPS_SOURCE_VOLUME: case AUD_CAPS_SOURCE_VOLUME:
@@ -440,10 +435,10 @@ bool AUD_SoftwareDevice::setCapability(int capability, void *value)
{ {
AUD_SoftwareHandle* handle = (AUD_SoftwareHandle*)caps->handle; AUD_SoftwareHandle* handle = (AUD_SoftwareHandle*)caps->handle;
handle->volume = caps->value; handle->volume = caps->value;
if(handle->volume > 1.0) if(handle->volume > 1.0f)
handle->volume = 1.0; handle->volume = 1.0f;
else if(handle->volume < 0.0) else if(handle->volume < 0.0f)
handle->volume = 0.0; handle->volume = 0.0f;
result = true; result = true;
} }
unlock(); unlock();

View File

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

View File

@@ -28,8 +28,10 @@
/// The size of a format in bytes. /// The size of a format in bytes.
#define AUD_FORMAT_SIZE(format) (format & 0x0F) #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. /// 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. /// Throws a AUD_Exception with the provided error code.
#define AUD_THROW(exception) { AUD_Exception e; e.error = exception; throw e; } #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_3DSS_CONE_OUTER_GAIN /// Cone outer gain.
} AUD_3DSourceSetting; } AUD_3DSourceSetting;
/// Sample pointer type. /// Sample type.(float samples)
typedef unsigned char sample_t; 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 typedef struct
{ {
/// Sample rate in Hz. /// Sample rate in Hz.
AUD_SampleRate rate; AUD_SampleRate rate;
/// Sample format.
AUD_SampleFormat format;
/// Channel count. /// Channel count.
AUD_Channels channels; AUD_Channels channels;
} AUD_Specs; } 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. /// Exception structure.
typedef struct typedef struct
{ {

View File

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

View File

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

View File

@@ -81,7 +81,7 @@ public:
* \param specs The wanted audio specification, where only the channel count is important. * \param specs The wanted audio specification, where only the channel count is important.
* \exception AUD_Exception Thrown if the audio device cannot be opened. * \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. * Closes the Jack client.

View File

@@ -393,14 +393,6 @@
RelativePath="..\..\intern\AUD_FileFactory.h" RelativePath="..\..\intern\AUD_FileFactory.h"
> >
</File> </File>
<File
RelativePath="..\..\intern\AUD_FloatMixer.cpp"
>
</File>
<File
RelativePath="..\..\intern\AUD_FloatMixer.h"
>
</File>
<File <File
RelativePath="..\..\intern\AUD_I3DDevice.h" RelativePath="..\..\intern\AUD_I3DDevice.h"
> >
@@ -414,11 +406,31 @@
> >
</File> </File>
<File <File
RelativePath="..\..\intern\AUD_IMixer.h" RelativePath="..\..\intern\AUD_IReader.h"
> >
</File> </File>
<File <File
RelativePath="..\..\intern\AUD_IReader.h" RelativePath="..\..\intern\AUD_LinearResampleFactory.cpp"
>
</File>
<File
RelativePath="..\..\intern\AUD_LinearResampleFactory.h"
>
</File>
<File
RelativePath="..\..\intern\AUD_LinearResampleReader.cpp"
>
</File>
<File
RelativePath="..\..\intern\AUD_LinearResampleReader.h"
>
</File>
<File
RelativePath="..\..\intern\AUD_Mixer.cpp"
>
</File>
<File
RelativePath="..\..\intern\AUD_Mixer.h"
> >
</File> </File>
<File <File
@@ -517,6 +529,38 @@
<Filter <Filter
Name="FX" Name="FX"
> >
<File
RelativePath="..\..\FX\AUD_AccumulatorFactory.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_AccumulatorFactory.h"
>
</File>
<File
RelativePath="..\..\FX\AUD_AccumulatorReader.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_AccumulatorReader.h"
>
</File>
<File
RelativePath="..\..\FX\AUD_ButterworthFactory.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_ButterworthFactory.h"
>
</File>
<File
RelativePath="..\..\FX\AUD_ButterworthReader.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_ButterworthReader.h"
>
</File>
<File <File
RelativePath="..\..\FX\AUD_DelayFactory.cpp" RelativePath="..\..\FX\AUD_DelayFactory.cpp"
> >
@@ -557,6 +601,22 @@
RelativePath="..\..\FX\AUD_EffectReader.h" RelativePath="..\..\FX\AUD_EffectReader.h"
> >
</File> </File>
<File
RelativePath="..\..\FX\AUD_EnvelopeFactory.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_EnvelopeFactory.h"
>
</File>
<File
RelativePath="..\..\FX\AUD_EnvelopeReader.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_EnvelopeReader.h"
>
</File>
<File <File
RelativePath="..\..\FX\AUD_FaderFactory.cpp" RelativePath="..\..\FX\AUD_FaderFactory.cpp"
> >
@@ -573,6 +633,22 @@
RelativePath="..\..\FX\AUD_FaderReader.h" RelativePath="..\..\FX\AUD_FaderReader.h"
> >
</File> </File>
<File
RelativePath="..\..\FX\AUD_HighpassFactory.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_HighpassFactory.h"
>
</File>
<File
RelativePath="..\..\FX\AUD_HighpassReader.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_HighpassReader.h"
>
</File>
<File <File
RelativePath="..\..\FX\AUD_LimiterFactory.cpp" RelativePath="..\..\FX\AUD_LimiterFactory.cpp"
> >
@@ -605,6 +681,22 @@
RelativePath="..\..\FX\AUD_LoopReader.h" RelativePath="..\..\FX\AUD_LoopReader.h"
> >
</File> </File>
<File
RelativePath="..\..\FX\AUD_LowpassFactory.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_LowpassFactory.h"
>
</File>
<File
RelativePath="..\..\FX\AUD_LowpassReader.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_LowpassReader.h"
>
</File>
<File <File
RelativePath="..\..\FX\AUD_PingPongFactory.cpp" RelativePath="..\..\FX\AUD_PingPongFactory.cpp"
> >
@@ -661,6 +753,38 @@
RelativePath="..\..\FX\AUD_ReverseReader.h" RelativePath="..\..\FX\AUD_ReverseReader.h"
> >
</File> </File>
<File
RelativePath="..\..\FX\AUD_SquareFactory.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_SquareFactory.h"
>
</File>
<File
RelativePath="..\..\FX\AUD_SquareReader.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_SquareReader.h"
>
</File>
<File
RelativePath="..\..\FX\AUD_SumFactory.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_SumFactory.h"
>
</File>
<File
RelativePath="..\..\FX\AUD_SumReader.cpp"
>
</File>
<File
RelativePath="..\..\FX\AUD_SumReader.h"
>
</File>
<File <File
RelativePath="..\..\FX\AUD_VolumeFactory.cpp" RelativePath="..\..\FX\AUD_VolumeFactory.cpp"
> >
@@ -701,30 +825,6 @@
RelativePath="..\..\SDL\AUD_SDLDevice.h" RelativePath="..\..\SDL\AUD_SDLDevice.h"
> >
</File> </File>
<File
RelativePath="..\..\SDL\AUD_SDLMixer.cpp"
>
</File>
<File
RelativePath="..\..\SDL\AUD_SDLMixer.h"
>
</File>
<File
RelativePath="..\..\SDL\AUD_SDLMixerFactory.cpp"
>
</File>
<File
RelativePath="..\..\SDL\AUD_SDLMixerFactory.h"
>
</File>
<File
RelativePath="..\..\SDL\AUD_SDLMixerReader.cpp"
>
</File>
<File
RelativePath="..\..\SDL\AUD_SDLMixerReader.h"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="SRC" Name="SRC"

View File

@@ -28,31 +28,14 @@
#include <cstring> #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) sf_count_t AUD_SndFileReader::vio_get_filelen(void *user_data)
{ {
AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data;
return reader->m_membuffer.get()->getSize(); 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; 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; 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; AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data;
if(reader->m_memoffset + count > reader->m_membuffer.get()->getSize()) if(reader->m_memoffset + count > reader->m_membuffer.get()->getSize())
count = reader->m_membuffer.get()->getSize() - reader->m_memoffset; 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; reader->m_memoffset += count;
return count; return count;
@@ -103,27 +88,11 @@ AUD_SndFileReader::AUD_SndFileReader(const char* filename)
AUD_THROW(AUD_ERROR_FILE); AUD_THROW(AUD_ERROR_FILE);
m_specs.channels = (AUD_Channels) sfinfo.channels; m_specs.channels = (AUD_Channels) sfinfo.channels;
m_specs.format = SNDFILE_TO_AUD(sfinfo.format);
m_specs.rate = (AUD_SampleRate) sfinfo.samplerate; m_specs.rate = (AUD_SampleRate) sfinfo.samplerate;
m_length = sfinfo.frames; m_length = sfinfo.frames;
m_seekable = sfinfo.seekable; m_seekable = sfinfo.seekable;
m_position = 0; 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") 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); AUD_THROW(AUD_ERROR_FILE);
m_specs.channels = (AUD_Channels) sfinfo.channels; m_specs.channels = (AUD_Channels) sfinfo.channels;
m_specs.format = SNDFILE_TO_AUD(sfinfo.format);
m_specs.rate = (AUD_SampleRate) sfinfo.samplerate; m_specs.rate = (AUD_SampleRate) sfinfo.samplerate;
m_length = sfinfo.frames; m_length = sfinfo.frames;
m_seekable = sfinfo.seekable; m_seekable = sfinfo.seekable;
m_position = 0; 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") 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(); buffer = m_buffer->getBuffer();
length = m_read(m_sndfile, buffer, length); length = sf_readf_float(m_sndfile, buffer, length);
m_position += length; m_position += length;
} }

View File

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

View File

@@ -162,6 +162,8 @@ extern void GHOST_GetMainDisplayDimensions(GHOST_SystemHandle systemhandle,
* @param height The height the window. * @param height The height the window.
* @param state The state of the window when opened. * @param state The state of the window when opened.
* @param type The type of drawing context installed in this window. * @param type The type of drawing context installed in this window.
* @param stereoVisual Stereo visual for quad buffered stereo.
* @param numOfAASamples Number of samples used for AA (zero if no AA)
* @return A handle to the new window ( == NULL if creation failed). * @return A handle to the new window ( == NULL if creation failed).
*/ */
extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
@@ -172,7 +174,8 @@ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
GHOST_TUns32 height, GHOST_TUns32 height,
GHOST_TWindowState state, GHOST_TWindowState state,
GHOST_TDrawingContextType type, GHOST_TDrawingContextType type,
const int stereoVisual); const int stereoVisual,
const GHOST_TUns16 numOfAASamples);
/** /**
* Returns the window user data. * Returns the window user data.

View File

@@ -216,14 +216,15 @@ public:
* Create a new window. * Create a new window.
* The new window is added to the list of windows managed. * The new window is added to the list of windows managed.
* Never explicitly delete the window, use disposeWindow() instead. * Never explicitly delete the window, use disposeWindow() instead.
* @param title The name of the window (displayed in the title bar of the window if the OS supports it). * @param title The name of the window (displayed in the title bar of the window if the OS supports it).
* @param left The coordinate of the left edge of the window. * @param left The coordinate of the left edge of the window.
* @param top The coordinate of the top edge of the window. * @param top The coordinate of the top edge of the window.
* @param width The width the window. * @param width The width the window.
* @param height The height the window. * @param height The height the window.
* @param state The state of the window when opened. * @param state The state of the window when opened.
* @param type The type of drawing context installed in this window. * @param type The type of drawing context installed in this window.
* @param stereoVisual Create a stereo visual for quad buffered stereo. * @param stereoVisual Create a stereo visual for quad buffered stereo.
* @param numOfAASamples Number of samples used for AA (zero if no AA)
* @param parentWindow Parent (embedder) window * @param parentWindow Parent (embedder) window
* @return The new window (or 0 if creation failed). * @return The new window (or 0 if creation failed).
*/ */
@@ -231,7 +232,8 @@ public:
const STR_String& title, const STR_String& title,
GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height,
GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_TWindowState state, GHOST_TDrawingContextType type,
const bool stereoVisual, const bool stereoVisual = false,
const GHOST_TUns16 numOfAASamples = 0,
const GHOST_TEmbedderWindowID parentWindow = 0) = 0; const GHOST_TEmbedderWindowID parentWindow = 0) = 0;
/** /**

Some files were not shown because too many files have changed in this diff Show More