Audaspace (GSoC): First merging commit
* All audaspace changes from the GSoC branch including the aud Python module * This commit also includes some minor changes in source/gameengine/Ketsji/KX_PythonInit.cpp: - Fixing names of some constants - removing outdated stopDSP() python function - Autoinclusion of bge instead of GameLogic - Fix for some error messages: GameLogic -> bge.logic
This commit is contained in:
@@ -60,6 +60,12 @@ IF(WITH_FFTW3)
|
||||
ADD_DEFINITIONS(-DWITH_FFTW3)
|
||||
ENDIF(WITH_FFTW3)
|
||||
|
||||
SET(SRC ${SRC} ${FFMPEGSRC} ${SNDFILESRC} ${FFTW3SRC} ${SDLSRC} ${OPENALSRC} ${JACKSRC})
|
||||
IF(WITH_PYTHON)
|
||||
SET(INC ${INC} Python ${PYTHON_INC})
|
||||
FILE(GLOB PYTHONSRC Python/*.cpp)
|
||||
ADD_DEFINITIONS(-DWITH_PYTHON)
|
||||
ENDIF(WITH_PYTHON)
|
||||
|
||||
SET(SRC ${SRC} ${FFMPEGSRC} ${SNDFILESRC} ${FFTW3SRC} ${SDLSRC} ${OPENALSRC} ${JACKSRC} ${PYTHONSRC})
|
||||
|
||||
BLENDERLIB(bf_audaspace "${SRC}" "${INC}")
|
||||
|
||||
@@ -24,26 +24,37 @@
|
||||
*/
|
||||
|
||||
#include "AUD_AccumulatorFactory.h"
|
||||
#include "AUD_AccumulatorReader.h"
|
||||
#include "AUD_CallbackIIRFilterReader.h"
|
||||
|
||||
sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless)
|
||||
{
|
||||
float in = reader->x(0);
|
||||
float lastin = reader->x(-1);
|
||||
float out = reader->y(-1) + in - lastin;
|
||||
if(in > lastin)
|
||||
out += in - lastin;
|
||||
return out;
|
||||
}
|
||||
|
||||
sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
|
||||
{
|
||||
float in = reader->x(0);
|
||||
float lastin = reader->x(-1);
|
||||
float out = reader->y(-1);
|
||||
if(in > lastin)
|
||||
out += in - lastin;
|
||||
return out;
|
||||
}
|
||||
|
||||
AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_IFactory* factory,
|
||||
bool additive) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_additive(additive) {}
|
||||
|
||||
AUD_AccumulatorFactory::AUD_AccumulatorFactory(bool additive) :
|
||||
AUD_EffectFactory(0),
|
||||
m_additive(additive) {}
|
||||
|
||||
AUD_IReader* AUD_AccumulatorFactory::createReader()
|
||||
m_additive(additive)
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_AccumulatorReader(reader, m_additive);
|
||||
AUD_NEW("reader")
|
||||
}
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_AccumulatorFactory::createReader() const
|
||||
{
|
||||
return new AUD_CallbackIIRFilterReader(getReader(), 2, 2,
|
||||
m_additive ? accumulatorFilterAdditive : accumulatorFilter);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,11 @@ private:
|
||||
/**
|
||||
* Whether the accumulator is additive.
|
||||
*/
|
||||
bool m_additive;
|
||||
const bool m_additive;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_AccumulatorFactory(const AUD_AccumulatorFactory&);
|
||||
AUD_AccumulatorFactory& operator=(const AUD_AccumulatorFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -47,13 +51,7 @@ public:
|
||||
*/
|
||||
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();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_ACCUMULATORFACTORY
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN LGPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* AudaSpace is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "AUD_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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN LGPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* AudaSpace is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef AUD_ACCUMULATORREADER
|
||||
#define AUD_ACCUMULATORREADER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
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
|
||||
76
intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp
Normal file
76
intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN LGPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* AudaSpace is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "AUD_BaseIIRFilterReader.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#define CC m_channels + m_channel
|
||||
|
||||
AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_IReader* reader, int in,
|
||||
int out) :
|
||||
AUD_EffectReader(reader),
|
||||
m_channels(reader->getSpecs().channels),
|
||||
m_xlen(in), m_ylen(out),
|
||||
m_xpos(0), m_ypos(0), m_channel(0)
|
||||
{
|
||||
m_x = new sample_t[in * m_channels];
|
||||
m_y = new sample_t[out * m_channels];
|
||||
|
||||
memset(m_x, 0, sizeof(sample_t) * in * m_channels);
|
||||
memset(m_y, 0, sizeof(sample_t) * out * m_channels);
|
||||
}
|
||||
|
||||
AUD_BaseIIRFilterReader::~AUD_BaseIIRFilterReader()
|
||||
{
|
||||
delete[] m_x;
|
||||
delete[] m_y;
|
||||
}
|
||||
|
||||
void AUD_BaseIIRFilterReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
sample_t* buf;
|
||||
|
||||
int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs());
|
||||
|
||||
m_reader->read(length, buf);
|
||||
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
m_buffer.resize(length * samplesize);
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
for(m_channel = 0; m_channel < m_channels; m_channel++)
|
||||
{
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
m_x[m_xpos * CC] = buf[i * CC];
|
||||
m_y[m_ypos * CC] = buffer[i * CC] = filter();
|
||||
|
||||
m_xpos = (m_xpos + 1) % m_xlen;
|
||||
m_ypos = (m_ypos + 1) % m_ylen;
|
||||
}
|
||||
}
|
||||
}
|
||||
114
intern/audaspace/FX/AUD_BaseIIRFilterReader.h
Normal file
114
intern/audaspace/FX/AUD_BaseIIRFilterReader.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN LGPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* AudaSpace is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef AUD_BASEIIRFILTERREADER
|
||||
#define AUD_BASEIIRFILTERREADER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
/**
|
||||
* This class is a base class for infinite impulse response filters.
|
||||
*/
|
||||
class AUD_BaseIIRFilterReader : public AUD_EffectReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Channel count.
|
||||
*/
|
||||
const int m_channels;
|
||||
|
||||
/**
|
||||
* Length of input samples needed.
|
||||
*/
|
||||
const int m_xlen;
|
||||
|
||||
/**
|
||||
* Length of output samples needed.
|
||||
*/
|
||||
const int m_ylen;
|
||||
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The last in samples array.
|
||||
*/
|
||||
sample_t* m_x;
|
||||
|
||||
/**
|
||||
* The last out samples array.
|
||||
*/
|
||||
sample_t* m_y;
|
||||
|
||||
/**
|
||||
* Position of the current input sample in the input array.
|
||||
*/
|
||||
int m_xpos;
|
||||
|
||||
/**
|
||||
* Position of the current output sample in the output array.
|
||||
*/
|
||||
int m_ypos;
|
||||
|
||||
/**
|
||||
* Current channel.
|
||||
*/
|
||||
int m_channel;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_BaseIIRFilterReader(const AUD_BaseIIRFilterReader&);
|
||||
AUD_BaseIIRFilterReader& operator=(const AUD_BaseIIRFilterReader&);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Creates a new base IIR filter reader.
|
||||
* \param reader The reader to read from.
|
||||
* \param in The count of past input samples needed.
|
||||
* \param out The count of past output samples needed.
|
||||
*/
|
||||
AUD_BaseIIRFilterReader(AUD_IReader* reader, int in, int out);
|
||||
|
||||
public:
|
||||
inline sample_t x(int pos)
|
||||
{
|
||||
return m_x[(m_xpos + pos + m_xlen) % m_xlen * m_channels + m_channel];
|
||||
}
|
||||
|
||||
inline sample_t y(int pos)
|
||||
{
|
||||
return m_y[(m_ypos + pos + m_ylen) % m_ylen * m_channels + m_channel];
|
||||
}
|
||||
|
||||
virtual ~AUD_BaseIIRFilterReader();
|
||||
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
|
||||
virtual sample_t filter()=0;
|
||||
};
|
||||
|
||||
#endif //AUD_BASEIIRFILTERREADER
|
||||
@@ -24,26 +24,49 @@
|
||||
*/
|
||||
|
||||
#include "AUD_ButterworthFactory.h"
|
||||
#include "AUD_ButterworthReader.h"
|
||||
#include "AUD_IIRFilterReader.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#define BWPB41 0.76536686473
|
||||
#define BWPB42 1.84775906502
|
||||
|
||||
AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_IFactory* factory,
|
||||
float frequency) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_frequency(frequency) {}
|
||||
m_frequency(frequency)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_ButterworthFactory::AUD_ButterworthFactory(float frequency) :
|
||||
AUD_EffectFactory(0),
|
||||
m_frequency(frequency) {}
|
||||
|
||||
AUD_IReader* AUD_ButterworthFactory::createReader()
|
||||
AUD_IReader* AUD_ButterworthFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_ButterworthReader(reader, m_frequency);
|
||||
AUD_NEW("reader")
|
||||
}
|
||||
// calculate coefficients
|
||||
float omega = 2 * tan(m_frequency * M_PI / reader->getSpecs().rate);
|
||||
float o2 = omega * omega;
|
||||
float o4 = o2 * o2;
|
||||
float x1 = o2 + 2 * BWPB41 * omega + 4;
|
||||
float x2 = o2 + 2 * BWPB42 * omega + 4;
|
||||
float y1 = o2 - 2 * BWPB41 * omega + 4;
|
||||
float y2 = o2 - 2 * BWPB42 * omega + 4;
|
||||
float o228 = 2 * o2 - 8;
|
||||
float norm = x1 * x2;
|
||||
std::vector<float> a, b;
|
||||
a.push_back(1);
|
||||
a.push_back((x1 + x2) * o228 / norm);
|
||||
a.push_back((x1 * y2 + x2 * y1 + o228 * o228) / norm);
|
||||
a.push_back((y1 + y2) * o228 / norm);
|
||||
a.push_back(y1 * y2 / norm);
|
||||
b.push_back(o4 / norm);
|
||||
b.push_back(4 * o4 / norm);
|
||||
b.push_back(6 * o4 / norm);
|
||||
b.push_back(b[1]);
|
||||
b.push_back(b[0]);
|
||||
|
||||
return reader;
|
||||
return new AUD_IIRFilterReader(reader, b, a);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,11 @@ private:
|
||||
/**
|
||||
* The attack value in seconds.
|
||||
*/
|
||||
float m_frequency;
|
||||
const float m_frequency;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_ButterworthFactory(const AUD_ButterworthFactory&);
|
||||
AUD_ButterworthFactory& operator=(const AUD_ButterworthFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -47,13 +51,7 @@ public:
|
||||
*/
|
||||
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();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_BUTTERWORTHFACTORY
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN LGPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* AudaSpace is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "AUD_ButterworthReader.h"
|
||||
#include "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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 *****
|
||||
*/
|
||||
|
||||
#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
|
||||
@@ -23,33 +23,25 @@
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "AUD_RectifyReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
#include "AUD_CallbackIIRFilterReader.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
AUD_RectifyReader::AUD_RectifyReader(AUD_IReader* reader) :
|
||||
AUD_EffectReader(reader)
|
||||
AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(AUD_IReader* reader,
|
||||
int in, int out,
|
||||
doFilterIIR doFilter,
|
||||
endFilterIIR endFilter,
|
||||
void* data) :
|
||||
AUD_BaseIIRFilterReader(reader, in, out),
|
||||
m_filter(doFilter), m_endFilter(endFilter), m_data(data)
|
||||
{
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
}
|
||||
|
||||
AUD_RectifyReader::~AUD_RectifyReader()
|
||||
AUD_CallbackIIRFilterReader::~AUD_CallbackIIRFilterReader()
|
||||
{
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
if(m_endFilter)
|
||||
m_endFilter(m_data);
|
||||
}
|
||||
|
||||
void AUD_RectifyReader::read(int & length, sample_t* & buffer)
|
||||
sample_t AUD_CallbackIIRFilterReader::filter()
|
||||
{
|
||||
sample_t* buf;
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
|
||||
m_reader->read(length, buf);
|
||||
if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs))
|
||||
m_buffer->resize(length * AUD_SAMPLE_SIZE(specs));
|
||||
|
||||
buffer = m_buffer->getBuffer();
|
||||
|
||||
for(int i = 0; i < length * specs.channels; i++)
|
||||
buffer[i] = fabs(buf[i]);
|
||||
return m_filter(this, m_data);
|
||||
}
|
||||
83
intern/audaspace/FX/AUD_CallbackIIRFilterReader.h
Normal file
83
intern/audaspace/FX/AUD_CallbackIIRFilterReader.h
Normal 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_CALLBACKIIRFILTERREADER
|
||||
#define AUD_CALLBACKIIRFILTERREADER
|
||||
|
||||
#include "AUD_BaseIIRFilterReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
class AUD_CallbackIIRFilterReader;
|
||||
|
||||
typedef sample_t (*doFilterIIR)(AUD_CallbackIIRFilterReader*, void*);
|
||||
typedef void (*endFilterIIR)(void*);
|
||||
|
||||
/**
|
||||
* This class provides an interface for infinite impulse response filters via a
|
||||
* callback filter function.
|
||||
*/
|
||||
class AUD_CallbackIIRFilterReader : public AUD_BaseIIRFilterReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Filter function.
|
||||
*/
|
||||
const doFilterIIR m_filter;
|
||||
|
||||
/**
|
||||
* End filter function.
|
||||
*/
|
||||
const endFilterIIR m_endFilter;
|
||||
|
||||
/**
|
||||
* Data pointer.
|
||||
*/
|
||||
void* m_data;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_CallbackIIRFilterReader(const AUD_CallbackIIRFilterReader&);
|
||||
AUD_CallbackIIRFilterReader& operator=(const AUD_CallbackIIRFilterReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new callback IIR filter reader.
|
||||
* \param reader The reader to read from.
|
||||
* \param in The count of past input samples needed.
|
||||
* \param out The count of past output samples needed.
|
||||
* \param doFilter The filter callback.
|
||||
* \param endFilter The finishing callback.
|
||||
* \param data Data pointer for the callbacks.
|
||||
*/
|
||||
AUD_CallbackIIRFilterReader(AUD_IReader* reader, int in, int out,
|
||||
doFilterIIR doFilter,
|
||||
endFilterIIR endFilter = 0,
|
||||
void* data = 0);
|
||||
|
||||
virtual ~AUD_CallbackIIRFilterReader();
|
||||
|
||||
virtual sample_t filter();
|
||||
};
|
||||
|
||||
#endif //AUD_CALLBACKIIRFILTERREADER
|
||||
@@ -29,30 +29,16 @@
|
||||
|
||||
AUD_DelayFactory::AUD_DelayFactory(AUD_IFactory* factory, float delay) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_delay(delay) {}
|
||||
m_delay(delay)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_DelayFactory::AUD_DelayFactory(float delay) :
|
||||
AUD_EffectFactory(0),
|
||||
m_delay(delay) {}
|
||||
|
||||
float AUD_DelayFactory::getDelay()
|
||||
float AUD_DelayFactory::getDelay() const
|
||||
{
|
||||
return m_delay;
|
||||
}
|
||||
|
||||
void AUD_DelayFactory::setDelay(float delay)
|
||||
AUD_IReader* AUD_DelayFactory::createReader() const
|
||||
{
|
||||
m_delay = delay;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_DelayFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_DelayReader(reader, m_delay); AUD_NEW("reader")
|
||||
}
|
||||
|
||||
return reader;
|
||||
return new AUD_DelayReader(getReader(), m_delay);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,11 @@ private:
|
||||
/**
|
||||
* The delay in samples.
|
||||
*/
|
||||
float m_delay;
|
||||
const float m_delay;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_DelayFactory(const AUD_DelayFactory&);
|
||||
AUD_DelayFactory& operator=(const AUD_DelayFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -45,26 +49,14 @@ public:
|
||||
* \param factory The input factory.
|
||||
* \param delay The desired delay in seconds.
|
||||
*/
|
||||
AUD_DelayFactory(AUD_IFactory* factory = 0, float delay = 0);
|
||||
|
||||
/**
|
||||
* Creates a new delay factory.
|
||||
* \param delay The desired delay in seconds.
|
||||
*/
|
||||
AUD_DelayFactory(float delay);
|
||||
AUD_DelayFactory(AUD_IFactory* factory, float delay = 0);
|
||||
|
||||
/**
|
||||
* Returns the delay in seconds.
|
||||
*/
|
||||
float getDelay();
|
||||
float getDelay() const;
|
||||
|
||||
/**
|
||||
* Sets the delay.
|
||||
* \param delay The new delay value in seconds.
|
||||
*/
|
||||
void setDelay(float delay);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_DELAYFACTORY
|
||||
|
||||
@@ -24,28 +24,19 @@
|
||||
*/
|
||||
|
||||
#include "AUD_DelayReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_DelayReader::AUD_DelayReader(AUD_IReader* reader, float delay) :
|
||||
AUD_EffectReader(reader)
|
||||
AUD_EffectReader(reader),
|
||||
m_delay(int(delay * reader->getSpecs().rate)),
|
||||
m_remdelay(int(delay * reader->getSpecs().rate)),
|
||||
m_empty(true)
|
||||
{
|
||||
m_delay = (int)(delay * reader->getSpecs().rate);
|
||||
m_remdelay = m_delay;
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
}
|
||||
|
||||
AUD_DelayReader::~AUD_DelayReader()
|
||||
{
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
}
|
||||
|
||||
void AUD_DelayReader::seek(int position)
|
||||
{
|
||||
if(position < 0)
|
||||
return;
|
||||
|
||||
if(position < m_delay)
|
||||
{
|
||||
m_remdelay = m_delay - position;
|
||||
@@ -58,18 +49,18 @@ void AUD_DelayReader::seek(int position)
|
||||
}
|
||||
}
|
||||
|
||||
int AUD_DelayReader::getLength()
|
||||
int AUD_DelayReader::getLength() const
|
||||
{
|
||||
int len = m_reader->getLength();
|
||||
if(len < 0)
|
||||
return len;
|
||||
return len+m_delay;
|
||||
return len + m_delay;
|
||||
}
|
||||
|
||||
int AUD_DelayReader::getPosition()
|
||||
int AUD_DelayReader::getPosition() const
|
||||
{
|
||||
if(m_remdelay > 0)
|
||||
return m_delay-m_remdelay;
|
||||
return m_delay - m_remdelay;
|
||||
return m_reader->getPosition() + m_delay;
|
||||
}
|
||||
|
||||
@@ -80,26 +71,41 @@ void AUD_DelayReader::read(int & length, sample_t* & buffer)
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
|
||||
if(m_buffer->getSize() < length * samplesize)
|
||||
m_buffer->resize(length * samplesize);
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
{
|
||||
m_buffer.resize(length * samplesize);
|
||||
m_empty = false;
|
||||
}
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
if(length > m_remdelay)
|
||||
{
|
||||
memset(m_buffer->getBuffer(), 0, m_remdelay * samplesize);
|
||||
if(!m_empty)
|
||||
memset(buffer, 0, m_remdelay * samplesize);
|
||||
|
||||
int len = length - m_remdelay;
|
||||
m_reader->read(len, buffer);
|
||||
memcpy(m_buffer->getBuffer() + m_remdelay * specs.channels,
|
||||
buffer, len * samplesize);
|
||||
sample_t* buf;
|
||||
m_reader->read(len, buf);
|
||||
|
||||
memcpy(buffer + m_remdelay * specs.channels,
|
||||
buf, len * samplesize);
|
||||
|
||||
if(len < length-m_remdelay)
|
||||
length = m_remdelay + len;
|
||||
|
||||
m_remdelay = 0;
|
||||
m_empty = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(m_buffer->getBuffer(), 0, length * samplesize);
|
||||
if(!m_empty)
|
||||
{
|
||||
memset(buffer, 0, length * samplesize);
|
||||
m_empty = true;
|
||||
}
|
||||
m_remdelay -= length;
|
||||
}
|
||||
buffer = m_buffer->getBuffer();
|
||||
}
|
||||
else
|
||||
m_reader->read(length, buffer);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#define AUD_DELAYREADER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
/**
|
||||
* This class reads another reader and changes it's delay.
|
||||
@@ -38,35 +38,38 @@ private:
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer *m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The delay level.
|
||||
*/
|
||||
int m_delay;
|
||||
const int m_delay;
|
||||
|
||||
/**
|
||||
* The remaining delay for playback.
|
||||
*/
|
||||
int m_remdelay;
|
||||
|
||||
/**
|
||||
* Whether the buffer is currently filled with zeros.
|
||||
*/
|
||||
bool m_empty;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_DelayReader(const AUD_DelayReader&);
|
||||
AUD_DelayReader& operator=(const AUD_DelayReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new delay reader.
|
||||
* \param reader The reader to read from.
|
||||
* \param delay The delay in seconds.
|
||||
* \exception AUD_Exception Thrown if the reader specified is NULL.
|
||||
*/
|
||||
AUD_DelayReader(AUD_IReader* reader, float delay);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
*/
|
||||
virtual ~AUD_DelayReader();
|
||||
|
||||
virtual void seek(int position);
|
||||
virtual int getLength();
|
||||
virtual int getPosition();
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
50
intern/audaspace/FX/AUD_DoubleFactory.cpp
Normal file
50
intern/audaspace/FX/AUD_DoubleFactory.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* $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_DoubleFactory.h"
|
||||
#include "AUD_DoubleReader.h"
|
||||
|
||||
AUD_DoubleFactory::AUD_DoubleFactory(AUD_IFactory* factory1, AUD_IFactory* factory2) :
|
||||
m_factory1(factory1), m_factory2(factory2)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_DoubleFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader1 = m_factory1->createReader();
|
||||
AUD_IReader* reader2;
|
||||
|
||||
try
|
||||
{
|
||||
reader2 = m_factory2->createReader();
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
delete reader1;
|
||||
throw;
|
||||
}
|
||||
|
||||
return new AUD_DoubleReader(reader1, reader2);
|
||||
}
|
||||
@@ -23,43 +23,41 @@
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef AUD_SQUAREREADER
|
||||
#define AUD_SQUAREREADER
|
||||
#ifndef AUD_DOUBLEFACTORY
|
||||
#define AUD_DOUBLEFACTORY
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_IFactory.h"
|
||||
|
||||
/**
|
||||
* This class changes another signal into a square signal.
|
||||
* This factory plays two other factories behind each other.
|
||||
* \note Readers from the underlying factories must have the same sample rate and channel count.
|
||||
*/
|
||||
class AUD_SquareReader : public AUD_EffectReader
|
||||
class AUD_DoubleFactory : public AUD_IFactory
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The playback buffer.
|
||||
* First played factory.
|
||||
*/
|
||||
AUD_Buffer *m_buffer;
|
||||
AUD_IFactory* m_factory1;
|
||||
|
||||
/**
|
||||
* The threshold level.
|
||||
* Second played factory.
|
||||
*/
|
||||
float m_threshold;
|
||||
AUD_IFactory* m_factory2;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_DoubleFactory(const AUD_DoubleFactory&);
|
||||
AUD_DoubleFactory& operator=(const AUD_DoubleFactory&);
|
||||
|
||||
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.
|
||||
* Creates a new double factory.
|
||||
* \param factory1 The first input factory.
|
||||
* \param factory2 The second input factory.
|
||||
*/
|
||||
AUD_SquareReader(AUD_IReader* reader, float threshold);
|
||||
AUD_DoubleFactory(AUD_IFactory* factory1, AUD_IFactory* factory2);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
*/
|
||||
virtual ~AUD_SquareReader();
|
||||
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_SQUAREREADER
|
||||
#endif //AUD_DOUBLEFACTORY
|
||||
@@ -24,80 +24,51 @@
|
||||
*/
|
||||
|
||||
#include "AUD_DoubleReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
static const char* specs_error = "AUD_DoubleReader: Both readers have to have "
|
||||
"the same specs.";
|
||||
|
||||
AUD_DoubleReader::AUD_DoubleReader(AUD_IReader* reader1,
|
||||
AUD_IReader* reader2) :
|
||||
m_reader1(reader1), m_reader2(reader2)
|
||||
m_reader1(reader1), m_reader2(reader2), m_finished1(false)
|
||||
{
|
||||
try
|
||||
AUD_Specs s1, s2;
|
||||
s1 = reader1->getSpecs();
|
||||
s2 = reader2->getSpecs();
|
||||
if(memcmp(&s1, &s2, sizeof(AUD_Specs)) != 0)
|
||||
{
|
||||
if(!reader1)
|
||||
AUD_THROW(AUD_ERROR_READER);
|
||||
|
||||
if(!reader2)
|
||||
AUD_THROW(AUD_ERROR_READER);
|
||||
|
||||
AUD_Specs s1, s2;
|
||||
s1 = reader1->getSpecs();
|
||||
s2 = reader2->getSpecs();
|
||||
if(memcmp(&s1, &s2, sizeof(AUD_Specs)) != 0)
|
||||
AUD_THROW(AUD_ERROR_READER);
|
||||
delete reader1;
|
||||
delete reader2;
|
||||
AUD_THROW(AUD_ERROR_SPECS, specs_error);
|
||||
}
|
||||
|
||||
catch(AUD_Exception)
|
||||
{
|
||||
if(reader1)
|
||||
{
|
||||
delete reader1; AUD_DELETE("reader")
|
||||
}
|
||||
if(reader2)
|
||||
{
|
||||
delete reader2; AUD_DELETE("reader")
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
m_finished1 = false;
|
||||
}
|
||||
|
||||
AUD_DoubleReader::~AUD_DoubleReader()
|
||||
{
|
||||
delete m_reader1; AUD_DELETE("reader")
|
||||
delete m_reader2; AUD_DELETE("reader")
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
delete m_reader1;
|
||||
delete m_reader2;
|
||||
}
|
||||
|
||||
bool AUD_DoubleReader::isSeekable()
|
||||
bool AUD_DoubleReader::isSeekable() const
|
||||
{
|
||||
return false;
|
||||
return m_reader1->isSeekable() && m_reader2->isSeekable();
|
||||
}
|
||||
|
||||
void AUD_DoubleReader::seek(int position)
|
||||
{
|
||||
int length1 = m_reader1->getLength();
|
||||
m_reader1->seek(position);
|
||||
|
||||
if(position < 0)
|
||||
position = 0;
|
||||
int pos1 = m_reader1->getPosition();
|
||||
|
||||
if(position < length1)
|
||||
{
|
||||
m_reader1->seek(position);
|
||||
m_reader2->seek(0);
|
||||
m_finished1 = false;
|
||||
}
|
||||
if((m_finished1 = (pos1 < position)))
|
||||
m_reader2->seek(position - pos1);
|
||||
else
|
||||
{
|
||||
m_reader2->seek(position-length1);
|
||||
m_finished1 = true;
|
||||
}
|
||||
m_reader2->seek(0);
|
||||
}
|
||||
|
||||
int AUD_DoubleReader::getLength()
|
||||
int AUD_DoubleReader::getLength() const
|
||||
{
|
||||
int len1 = m_reader1->getLength();
|
||||
int len2 = m_reader2->getLength();
|
||||
@@ -106,49 +77,45 @@ int AUD_DoubleReader::getLength()
|
||||
return len1 + len2;
|
||||
}
|
||||
|
||||
int AUD_DoubleReader::getPosition()
|
||||
int AUD_DoubleReader::getPosition() const
|
||||
{
|
||||
return m_reader1->getPosition() + m_reader2->getPosition();
|
||||
}
|
||||
|
||||
AUD_Specs AUD_DoubleReader::getSpecs()
|
||||
AUD_Specs AUD_DoubleReader::getSpecs() const
|
||||
{
|
||||
return m_reader1->getSpecs();
|
||||
}
|
||||
|
||||
AUD_ReaderType AUD_DoubleReader::getType()
|
||||
{
|
||||
if(m_reader1->getType() == AUD_TYPE_BUFFER &&
|
||||
m_reader2->getType() == AUD_TYPE_BUFFER)
|
||||
return AUD_TYPE_BUFFER;
|
||||
return AUD_TYPE_STREAM;
|
||||
}
|
||||
|
||||
bool AUD_DoubleReader::notify(AUD_Message &message)
|
||||
{
|
||||
return m_reader1->notify(message) | m_reader2->notify(message);
|
||||
}
|
||||
|
||||
void AUD_DoubleReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
if(!m_finished1)
|
||||
{
|
||||
int len = length;
|
||||
m_reader1->read(len, buffer);
|
||||
|
||||
if(len < length)
|
||||
{
|
||||
AUD_Specs specs = m_reader1->getSpecs();
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
if(m_buffer->getSize() < length * samplesize)
|
||||
m_buffer->resize(length * samplesize);
|
||||
memcpy(m_buffer->getBuffer(), buffer, len * samplesize);
|
||||
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
m_buffer.resize(length * samplesize);
|
||||
|
||||
sample_t* buf = buffer;
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
memcpy(buffer, buf, len * samplesize);
|
||||
|
||||
len = length - len;
|
||||
length -= len;
|
||||
m_reader2->read(len, buffer);
|
||||
memcpy(m_buffer->getBuffer() + length * specs.channels, buffer,
|
||||
m_reader2->read(len, buf);
|
||||
|
||||
memcpy(buffer + length * specs.channels, buf,
|
||||
len * samplesize);
|
||||
|
||||
length += len;
|
||||
buffer = m_buffer->getBuffer();
|
||||
|
||||
m_finished1 = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#define AUD_DOUBLEREADER
|
||||
|
||||
#include "AUD_IReader.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
/**
|
||||
* This reader plays two readers with the same specs sequently.
|
||||
@@ -53,15 +53,18 @@ private:
|
||||
/**
|
||||
* The playback buffer for the intersecting part.
|
||||
*/
|
||||
AUD_Buffer* m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_DoubleReader(const AUD_DoubleReader&);
|
||||
AUD_DoubleReader& operator=(const AUD_DoubleReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new ping pong reader.
|
||||
* \param reader1 The first reader to read from.
|
||||
* \param reader2 The second reader to read from.
|
||||
* \exception AUD_Exception Thrown if one of the reader specified is NULL
|
||||
* or the specs from the readers differ.
|
||||
* \exception AUD_Exception Thrown if the specs from the readers differ.
|
||||
*/
|
||||
AUD_DoubleReader(AUD_IReader* reader1, AUD_IReader* reader2);
|
||||
|
||||
@@ -70,13 +73,11 @@ public:
|
||||
*/
|
||||
virtual ~AUD_DoubleReader();
|
||||
|
||||
virtual bool isSeekable();
|
||||
virtual bool isSeekable() const;
|
||||
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 int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -26,25 +26,16 @@
|
||||
#include "AUD_EffectFactory.h"
|
||||
#include "AUD_IReader.h"
|
||||
|
||||
AUD_IReader* AUD_EffectFactory::getReader()
|
||||
{
|
||||
if(m_factory != 0)
|
||||
return m_factory->createReader();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AUD_EffectFactory::AUD_EffectFactory(AUD_IFactory* factory)
|
||||
{
|
||||
m_factory = factory;
|
||||
}
|
||||
|
||||
void AUD_EffectFactory::setFactory(AUD_IFactory* factory)
|
||||
AUD_EffectFactory::~AUD_EffectFactory()
|
||||
{
|
||||
m_factory = factory;
|
||||
}
|
||||
|
||||
AUD_IFactory* AUD_EffectFactory::getFactory()
|
||||
AUD_IFactory* AUD_EffectFactory::getFactory() const
|
||||
{
|
||||
return m_factory;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
*/
|
||||
class AUD_EffectFactory : public AUD_IFactory
|
||||
{
|
||||
private:
|
||||
// hide copy constructor and operator=
|
||||
AUD_EffectFactory(const AUD_EffectFactory&);
|
||||
AUD_EffectFactory& operator=(const AUD_EffectFactory&);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* If there is no reader it is created out of this factory.
|
||||
@@ -44,9 +49,12 @@ protected:
|
||||
* Returns the reader created out of the factory.
|
||||
* This method can be used for the createReader function of the implementing
|
||||
* classes.
|
||||
* \return The reader created out of the factory or NULL if there is none.
|
||||
* \return The reader created out of the factory.
|
||||
*/
|
||||
AUD_IReader* getReader();
|
||||
inline AUD_IReader* getReader() const
|
||||
{
|
||||
return m_factory->createReader();
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -58,19 +66,13 @@ public:
|
||||
/**
|
||||
* Destroys the factory.
|
||||
*/
|
||||
virtual ~AUD_EffectFactory() {}
|
||||
|
||||
/**
|
||||
* Sets the input factory.
|
||||
* \param factory The input factory.
|
||||
*/
|
||||
void setFactory(AUD_IFactory* factory);
|
||||
virtual ~AUD_EffectFactory();
|
||||
|
||||
/**
|
||||
* Returns the saved factory.
|
||||
* \return The factory or NULL if there has no factory been saved.
|
||||
*/
|
||||
AUD_IFactory* getFactory();
|
||||
AUD_IFactory* getFactory() const;
|
||||
};
|
||||
|
||||
#endif //AUD_EFFECTFACTORY
|
||||
|
||||
@@ -27,17 +27,15 @@
|
||||
|
||||
AUD_EffectReader::AUD_EffectReader(AUD_IReader* reader)
|
||||
{
|
||||
if(!reader)
|
||||
AUD_THROW(AUD_ERROR_READER);
|
||||
m_reader = reader;
|
||||
}
|
||||
|
||||
AUD_EffectReader::~AUD_EffectReader()
|
||||
{
|
||||
delete m_reader; AUD_DELETE("reader")
|
||||
delete m_reader;
|
||||
}
|
||||
|
||||
bool AUD_EffectReader::isSeekable()
|
||||
bool AUD_EffectReader::isSeekable() const
|
||||
{
|
||||
return m_reader->isSeekable();
|
||||
}
|
||||
@@ -47,31 +45,21 @@ void AUD_EffectReader::seek(int position)
|
||||
m_reader->seek(position);
|
||||
}
|
||||
|
||||
int AUD_EffectReader::getLength()
|
||||
int AUD_EffectReader::getLength() const
|
||||
{
|
||||
return m_reader->getLength();
|
||||
}
|
||||
|
||||
int AUD_EffectReader::getPosition()
|
||||
int AUD_EffectReader::getPosition() const
|
||||
{
|
||||
return m_reader->getPosition();
|
||||
}
|
||||
|
||||
AUD_Specs AUD_EffectReader::getSpecs()
|
||||
AUD_Specs AUD_EffectReader::getSpecs() const
|
||||
{
|
||||
return m_reader->getSpecs();
|
||||
}
|
||||
|
||||
AUD_ReaderType AUD_EffectReader::getType()
|
||||
{
|
||||
return m_reader->getType();
|
||||
}
|
||||
|
||||
bool AUD_EffectReader::notify(AUD_Message &message)
|
||||
{
|
||||
return m_reader->notify(message);
|
||||
}
|
||||
|
||||
void AUD_EffectReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
m_reader->read(length, buffer);
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
*/
|
||||
class AUD_EffectReader : public AUD_IReader
|
||||
{
|
||||
private:
|
||||
// hide copy constructor and operator=
|
||||
AUD_EffectReader(const AUD_EffectReader&);
|
||||
AUD_EffectReader& operator=(const AUD_EffectReader&);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The reader to read from.
|
||||
@@ -44,7 +49,6 @@ public:
|
||||
/**
|
||||
* Creates a new effect reader.
|
||||
* \param reader The reader to read from.
|
||||
* \exception AUD_Exception Thrown if the reader specified is NULL.
|
||||
*/
|
||||
AUD_EffectReader(AUD_IReader* reader);
|
||||
|
||||
@@ -53,13 +57,11 @@ public:
|
||||
*/
|
||||
virtual ~AUD_EffectReader();
|
||||
|
||||
virtual bool isSeekable();
|
||||
virtual bool isSeekable() const;
|
||||
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 int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -24,7 +24,31 @@
|
||||
*/
|
||||
|
||||
#include "AUD_EnvelopeFactory.h"
|
||||
#include "AUD_EnvelopeReader.h"
|
||||
#include "AUD_CallbackIIRFilterReader.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
struct EnvelopeParameters
|
||||
{
|
||||
float attack;
|
||||
float release;
|
||||
float threshold;
|
||||
float arthreshold;
|
||||
};
|
||||
|
||||
sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param)
|
||||
{
|
||||
float in = fabs(reader->x(0));
|
||||
float out = reader->y(-1);
|
||||
if(in < param->threshold)
|
||||
in = 0.0f;
|
||||
return (in > out ? param->attack : param->release) * (out - in) + in;
|
||||
}
|
||||
|
||||
void endEnvelopeFilter(EnvelopeParameters* param)
|
||||
{
|
||||
delete param;
|
||||
}
|
||||
|
||||
AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack,
|
||||
float release, float threshold,
|
||||
@@ -33,26 +57,22 @@ AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack,
|
||||
m_attack(attack),
|
||||
m_release(release),
|
||||
m_threshold(threshold),
|
||||
m_arthreshold(arthreshold) {}
|
||||
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* AUD_EnvelopeFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_EnvelopeReader(reader, m_attack, m_release,
|
||||
m_threshold, m_arthreshold);
|
||||
AUD_NEW("reader")
|
||||
}
|
||||
EnvelopeParameters* param = new EnvelopeParameters();
|
||||
param->arthreshold = m_arthreshold;
|
||||
param->attack = pow(m_arthreshold, 1.0f/(reader->getSpecs().rate * m_attack));
|
||||
param->release = pow(m_arthreshold, 1.0f/(reader->getSpecs().rate * m_release));
|
||||
param->threshold = m_threshold;
|
||||
|
||||
return reader;
|
||||
return new AUD_CallbackIIRFilterReader(reader, 1, 2,
|
||||
(doFilterIIR) envelopeFilter,
|
||||
(endFilterIIR) endEnvelopeFilter,
|
||||
param);
|
||||
}
|
||||
|
||||
@@ -37,22 +37,26 @@ private:
|
||||
/**
|
||||
* The attack value in seconds.
|
||||
*/
|
||||
float m_attack;
|
||||
const float m_attack;
|
||||
|
||||
/**
|
||||
* The release value in seconds.
|
||||
*/
|
||||
float m_release;
|
||||
const float m_release;
|
||||
|
||||
/**
|
||||
* The threshold value.
|
||||
*/
|
||||
float m_threshold;
|
||||
const float m_threshold;
|
||||
|
||||
/**
|
||||
* The attack/release threshold value.
|
||||
*/
|
||||
float m_arthreshold;
|
||||
const float m_arthreshold;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_EnvelopeFactory(const AUD_EnvelopeFactory&);
|
||||
AUD_EnvelopeFactory& operator=(const AUD_EnvelopeFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -66,17 +70,7 @@ public:
|
||||
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();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_ENVELOPEFACTORY
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN LGPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* AudaSpace is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "AUD_EnvelopeReader.h"
|
||||
#include "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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN LGPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* AudaSpace is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef AUD_ENVELOPEREADER
|
||||
#define AUD_ENVELOPEREADER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
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
|
||||
@@ -31,54 +31,26 @@ AUD_FaderFactory::AUD_FaderFactory(AUD_IFactory* factory, AUD_FadeType type,
|
||||
AUD_EffectFactory(factory),
|
||||
m_type(type),
|
||||
m_start(start),
|
||||
m_length(length) {}
|
||||
m_length(length)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_FaderFactory::AUD_FaderFactory(AUD_FadeType type,
|
||||
float start, float length) :
|
||||
AUD_EffectFactory(0),
|
||||
m_type(type),
|
||||
m_start(start),
|
||||
m_length(length) {}
|
||||
|
||||
AUD_FadeType AUD_FaderFactory::getType()
|
||||
AUD_FadeType AUD_FaderFactory::getType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
void AUD_FaderFactory::setType(AUD_FadeType type)
|
||||
{
|
||||
m_type = type;
|
||||
}
|
||||
|
||||
float AUD_FaderFactory::getStart()
|
||||
float AUD_FaderFactory::getStart() const
|
||||
{
|
||||
return m_start;
|
||||
}
|
||||
|
||||
void AUD_FaderFactory::setStart(float start)
|
||||
{
|
||||
m_start = start;
|
||||
}
|
||||
|
||||
float AUD_FaderFactory::getLength()
|
||||
float AUD_FaderFactory::getLength() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
void AUD_FaderFactory::setLength(float length)
|
||||
AUD_IReader* AUD_FaderFactory::createReader() const
|
||||
{
|
||||
m_length = length;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_FaderFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_FaderReader(reader, m_type, m_start, m_length);
|
||||
AUD_NEW("reader")
|
||||
}
|
||||
|
||||
return reader;
|
||||
return new AUD_FaderReader(getReader(), m_type, m_start, m_length);
|
||||
}
|
||||
|
||||
@@ -39,17 +39,21 @@ private:
|
||||
/**
|
||||
* The fading type.
|
||||
*/
|
||||
AUD_FadeType m_type;
|
||||
const AUD_FadeType m_type;
|
||||
|
||||
/**
|
||||
* The fading start.
|
||||
*/
|
||||
float m_start;
|
||||
const float m_start;
|
||||
|
||||
/**
|
||||
* The fading length.
|
||||
*/
|
||||
float m_length;
|
||||
const float m_length;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_FaderFactory(const AUD_FaderFactory&);
|
||||
AUD_FaderFactory& operator=(const AUD_FaderFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -59,53 +63,26 @@ public:
|
||||
* \param start The time where fading should start in seconds.
|
||||
* \param length How long fading should last in seconds.
|
||||
*/
|
||||
AUD_FaderFactory(AUD_IFactory* factory = 0,
|
||||
AUD_FaderFactory(AUD_IFactory* factory,
|
||||
AUD_FadeType type = AUD_FADE_IN,
|
||||
float start = 0.0f, float length = 1.0f);
|
||||
|
||||
/**
|
||||
* Creates a new fader factory.
|
||||
* \param type The fading type.
|
||||
* \param start The time where fading should start in seconds.
|
||||
* \param length How long fading should last in seconds.
|
||||
*/
|
||||
AUD_FaderFactory(AUD_FadeType type = AUD_FADE_IN,
|
||||
float start = 0.0f, float length = 1.0f);
|
||||
|
||||
/**
|
||||
* Returns the fading type.
|
||||
*/
|
||||
AUD_FadeType getType();
|
||||
|
||||
/**
|
||||
* Sets the fading type.
|
||||
* \param type The new fading type: AUD_FADE_IN or AUD_FADE_OUT.
|
||||
*/
|
||||
void setType(AUD_FadeType type);
|
||||
AUD_FadeType getType() const;
|
||||
|
||||
/**
|
||||
* Returns the fading start.
|
||||
*/
|
||||
float getStart();
|
||||
|
||||
/**
|
||||
* Sets the fading start.
|
||||
* \param start The new fading start.
|
||||
*/
|
||||
void setStart(float start);
|
||||
float getStart() const;
|
||||
|
||||
/**
|
||||
* Returns the fading length.
|
||||
*/
|
||||
float getLength();
|
||||
float getLength() const;
|
||||
|
||||
/**
|
||||
* Sets the fading length.
|
||||
* \param start The new fading length.
|
||||
*/
|
||||
void setLength(float length);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_FADERFACTORY
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
*/
|
||||
|
||||
#include "AUD_FaderReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
@@ -33,19 +32,9 @@ AUD_FaderReader::AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type,
|
||||
AUD_EffectReader(reader),
|
||||
m_type(type),
|
||||
m_start(start),
|
||||
m_length(length)
|
||||
m_length(length),
|
||||
m_empty(true)
|
||||
{
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
}
|
||||
|
||||
AUD_FaderReader::~AUD_FaderReader()
|
||||
{
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
}
|
||||
|
||||
bool AUD_FaderReader::notify(AUD_Message &message)
|
||||
{
|
||||
return m_reader->notify(message);
|
||||
}
|
||||
|
||||
void AUD_FaderReader::read(int & length, sample_t* & buffer)
|
||||
@@ -56,28 +45,50 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer)
|
||||
|
||||
m_reader->read(length, buffer);
|
||||
|
||||
if(m_buffer->getSize() < length * samplesize)
|
||||
m_buffer->resize(length * samplesize);
|
||||
|
||||
if((position + length) / (float)specs.rate <= m_start)
|
||||
{
|
||||
if(m_type != AUD_FADE_OUT)
|
||||
{
|
||||
buffer = m_buffer->getBuffer();
|
||||
memset(buffer, 0, length * samplesize);
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
{
|
||||
m_buffer.resize(length * samplesize);
|
||||
m_empty = false;
|
||||
}
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
if(!m_empty)
|
||||
{
|
||||
memset(buffer, 0, length * samplesize);
|
||||
m_empty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(position / (float)specs.rate >= m_start+m_length)
|
||||
{
|
||||
if(m_type == AUD_FADE_OUT)
|
||||
{
|
||||
buffer = m_buffer->getBuffer();
|
||||
memset(buffer, 0, length * samplesize);
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
{
|
||||
m_buffer.resize(length * samplesize);
|
||||
m_empty = false;
|
||||
}
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
if(!m_empty)
|
||||
{
|
||||
memset(buffer, 0, length * samplesize);
|
||||
m_empty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sample_t* buf = m_buffer->getBuffer();
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
m_buffer.resize(length * samplesize);
|
||||
|
||||
sample_t* buf = m_buffer.getBuffer();
|
||||
float volume = 1.0f;
|
||||
|
||||
for(int i = 0; i < length * specs.channels; i++)
|
||||
@@ -98,5 +109,6 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer)
|
||||
}
|
||||
|
||||
buffer = buf;
|
||||
m_empty = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#define AUD_FADERREADER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
/**
|
||||
* This class fades another reader.
|
||||
@@ -37,25 +37,34 @@ class AUD_Buffer;
|
||||
class AUD_FaderReader : public AUD_EffectReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer *m_buffer;
|
||||
|
||||
/**
|
||||
* The fading type.
|
||||
*/
|
||||
AUD_FadeType m_type;
|
||||
const AUD_FadeType m_type;
|
||||
|
||||
/**
|
||||
* The fading start.
|
||||
*/
|
||||
float m_start;
|
||||
const float m_start;
|
||||
|
||||
/**
|
||||
* The fading length.
|
||||
*/
|
||||
float m_length;
|
||||
const float m_length;
|
||||
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* Whether the buffer is empty.
|
||||
*/
|
||||
bool m_empty;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_FaderReader(const AUD_FaderReader&);
|
||||
AUD_FaderReader& operator=(const AUD_FaderReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -63,17 +72,10 @@ public:
|
||||
* \param type The fading type.
|
||||
* \param start The time where fading should start in seconds.
|
||||
* \param length How long fading should last in seconds.
|
||||
* \exception AUD_Exception Thrown if the reader specified is NULL.
|
||||
*/
|
||||
AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type,
|
||||
float start,float length);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
*/
|
||||
virtual ~AUD_FaderReader();
|
||||
|
||||
virtual bool notify(AUD_Message &message);
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -24,28 +24,38 @@
|
||||
*/
|
||||
|
||||
#include "AUD_HighpassFactory.h"
|
||||
#include "AUD_HighpassReader.h"
|
||||
#include "AUD_IIRFilterReader.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
AUD_HighpassFactory::AUD_HighpassFactory(AUD_IFactory* factory, float frequency,
|
||||
float Q) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_frequency(frequency),
|
||||
m_Q(Q) {}
|
||||
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* AUD_HighpassFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_HighpassReader(reader, m_frequency, m_Q);
|
||||
AUD_NEW("reader")
|
||||
}
|
||||
// calculate coefficients
|
||||
float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate;
|
||||
float alpha = sin(w0) / (2 * m_Q);
|
||||
float norm = 1 + alpha;
|
||||
float c = cos(w0);
|
||||
std::vector<float> a, b;
|
||||
a.push_back(1);
|
||||
a.push_back(-2 * c / norm);
|
||||
a.push_back((1 - alpha) / norm);
|
||||
b.push_back((1 + c) / (2 * norm));
|
||||
b.push_back((-1 - c) / norm);
|
||||
b.push_back(b[0]);
|
||||
|
||||
return reader;
|
||||
return new AUD_IIRFilterReader(reader, b, a);
|
||||
}
|
||||
|
||||
@@ -37,12 +37,16 @@ private:
|
||||
/**
|
||||
* The attack value in seconds.
|
||||
*/
|
||||
float m_frequency;
|
||||
const float m_frequency;
|
||||
|
||||
/**
|
||||
* The Q factor.
|
||||
*/
|
||||
float m_Q;
|
||||
const float m_Q;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_HighpassFactory(const AUD_HighpassFactory&);
|
||||
AUD_HighpassFactory& operator=(const AUD_HighpassFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -53,14 +57,7 @@ public:
|
||||
*/
|
||||
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();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_HIGHPASSFACTORY
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN LGPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* AudaSpace is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "AUD_HighpassReader.h"
|
||||
#include "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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 *****
|
||||
*/
|
||||
|
||||
#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
|
||||
39
intern/audaspace/FX/AUD_IIRFilterFactory.cpp
Normal file
39
intern/audaspace/FX/AUD_IIRFilterFactory.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* $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_IIRFilterFactory.h"
|
||||
#include "AUD_IIRFilterReader.h"
|
||||
|
||||
AUD_IIRFilterFactory::AUD_IIRFilterFactory(AUD_IFactory* factory,
|
||||
std::vector<float> b,
|
||||
std::vector<float> a) :
|
||||
AUD_EffectFactory(factory), m_a(a), m_b(b)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_IIRFilterFactory::createReader() const
|
||||
{
|
||||
return new AUD_IIRFilterReader(getReader(), m_b, m_a);
|
||||
}
|
||||
66
intern/audaspace/FX/AUD_IIRFilterFactory.h
Normal file
66
intern/audaspace/FX/AUD_IIRFilterFactory.h
Normal 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_IIRFILTERFACTORY
|
||||
#define AUD_IIRFILTERFACTORY
|
||||
|
||||
#include "AUD_EffectFactory.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* This factory creates a IIR filter reader.
|
||||
*/
|
||||
class AUD_IIRFilterFactory : public AUD_EffectFactory
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Output filter coefficients.
|
||||
*/
|
||||
std::vector<float> m_a;
|
||||
|
||||
/**
|
||||
* Input filter coefficients.
|
||||
*/
|
||||
std::vector<float> m_b;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_IIRFilterFactory(const AUD_IIRFilterFactory&);
|
||||
AUD_IIRFilterFactory& operator=(const AUD_IIRFilterFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new IIR filter factory.
|
||||
* \param factory The input factory.
|
||||
* \param b The input filter coefficients.
|
||||
* \param a The output filter coefficients.
|
||||
*/
|
||||
AUD_IIRFilterFactory(AUD_IFactory* factory, std::vector<float> b,
|
||||
std::vector<float> a);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_IIRFILTERFACTORY
|
||||
50
intern/audaspace/FX/AUD_IIRFilterReader.cpp
Normal file
50
intern/audaspace/FX/AUD_IIRFilterReader.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* $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_IIRFilterReader.h"
|
||||
|
||||
AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_IReader* reader,
|
||||
std::vector<float> b,
|
||||
std::vector<float> a) :
|
||||
AUD_BaseIIRFilterReader(reader, b.size(), a.size()), m_a(a), m_b(b)
|
||||
{
|
||||
for(int i = 1; i < m_a.size(); i++)
|
||||
m_a[i] /= m_a[0];
|
||||
for(int i = 0; i < m_b.size(); i++)
|
||||
m_b[i] /= m_a[0];
|
||||
m_a[0] = 1;
|
||||
}
|
||||
|
||||
sample_t AUD_IIRFilterReader::filter()
|
||||
{
|
||||
sample_t out = 0;
|
||||
|
||||
for(int i = 1; i < m_a.size(); i++)
|
||||
out -= y(-i) * m_a[i];
|
||||
for(int i = 0; i < m_b.size(); i++)
|
||||
out += x(-i) * m_b[i];
|
||||
|
||||
return out;
|
||||
}
|
||||
@@ -23,44 +23,44 @@
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef AUD_VOLUMEREADER
|
||||
#define AUD_VOLUMEREADER
|
||||
#ifndef AUD_IIRFILTERREADER
|
||||
#define AUD_IIRFILTERREADER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_BaseIIRFilterReader.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* This class reads another reader and changes it's volume.
|
||||
* This class is for infinite impulse response filters with simple coefficients.
|
||||
*/
|
||||
class AUD_VolumeReader : public AUD_EffectReader
|
||||
class AUD_IIRFilterReader : public AUD_BaseIIRFilterReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The playback buffer.
|
||||
* Output filter coefficients.
|
||||
*/
|
||||
AUD_Buffer *m_buffer;
|
||||
std::vector<float> m_a;
|
||||
|
||||
/**
|
||||
* The volume level.
|
||||
* Input filter coefficients.
|
||||
*/
|
||||
float m_volume;
|
||||
std::vector<float> m_b;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_IIRFilterReader(const AUD_IIRFilterReader&);
|
||||
AUD_IIRFilterReader& operator=(const AUD_IIRFilterReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new volume reader.
|
||||
* Creates a new IIR filter reader.
|
||||
* \param reader The reader to read from.
|
||||
* \param volume The size of the buffer.
|
||||
* \exception AUD_Exception Thrown if the reader specified is NULL.
|
||||
* \param b The input filter coefficients.
|
||||
* \param a The output filter coefficients.
|
||||
*/
|
||||
AUD_VolumeReader(AUD_IReader* reader, float volume);
|
||||
AUD_IIRFilterReader(AUD_IReader* reader, std::vector<float> b,
|
||||
std::vector<float> a);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
*/
|
||||
virtual ~AUD_VolumeReader();
|
||||
|
||||
virtual bool notify(AUD_Message &message);
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual sample_t filter();
|
||||
};
|
||||
|
||||
#endif //AUD_VOLUMEREADER
|
||||
#endif //AUD_IIRFILTERREADER
|
||||
@@ -31,37 +31,21 @@ AUD_LimiterFactory::AUD_LimiterFactory(AUD_IFactory* factory,
|
||||
float start, float end) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_start(start),
|
||||
m_end(end) {}
|
||||
m_end(end)
|
||||
{
|
||||
}
|
||||
|
||||
float AUD_LimiterFactory::getStart()
|
||||
float AUD_LimiterFactory::getStart() const
|
||||
{
|
||||
return m_start;
|
||||
}
|
||||
|
||||
void AUD_LimiterFactory::setStart(float start)
|
||||
{
|
||||
m_start = start;
|
||||
}
|
||||
|
||||
float AUD_LimiterFactory::getEnd()
|
||||
float AUD_LimiterFactory::getEnd() const
|
||||
{
|
||||
return m_end;
|
||||
}
|
||||
|
||||
void AUD_LimiterFactory::setEnd(float end)
|
||||
AUD_IReader* AUD_LimiterFactory::createReader() const
|
||||
{
|
||||
m_end = end;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_LimiterFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_LimiterReader(reader, m_start, m_end);
|
||||
AUD_NEW("reader")
|
||||
}
|
||||
|
||||
return reader;
|
||||
return new AUD_LimiterReader(getReader(), m_start, m_end);
|
||||
}
|
||||
|
||||
@@ -37,12 +37,16 @@ private:
|
||||
/**
|
||||
* The start time.
|
||||
*/
|
||||
float m_start;
|
||||
const float m_start;
|
||||
|
||||
/**
|
||||
* The end time.
|
||||
*/
|
||||
float m_end;
|
||||
const float m_end;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_LimiterFactory(const AUD_LimiterFactory&);
|
||||
AUD_LimiterFactory& operator=(const AUD_LimiterFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -52,33 +56,20 @@ public:
|
||||
* \param end The desired end time, a negative value signals that it should
|
||||
* play to the end.
|
||||
*/
|
||||
AUD_LimiterFactory(AUD_IFactory* factory = 0,
|
||||
AUD_LimiterFactory(AUD_IFactory* factory,
|
||||
float start = 0, float end = -1);
|
||||
|
||||
/**
|
||||
* Returns the start time.
|
||||
*/
|
||||
float getStart();
|
||||
|
||||
/**
|
||||
* Sets the start time.
|
||||
* \param start The new start time.
|
||||
*/
|
||||
void setStart(float start);
|
||||
float getStart() const;
|
||||
|
||||
/**
|
||||
* Returns the end time.
|
||||
*/
|
||||
float getEnd();
|
||||
float getEnd() const;
|
||||
|
||||
/**
|
||||
* Sets the end time.
|
||||
* \param end The new end time, a negative value signals that it should play
|
||||
* to the end.
|
||||
*/
|
||||
void setEnd(float end);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_LIMITERFACTORY
|
||||
|
||||
@@ -30,31 +30,27 @@
|
||||
|
||||
AUD_LimiterReader::AUD_LimiterReader(AUD_IReader* reader,
|
||||
float start, float end) :
|
||||
AUD_EffectReader(reader)
|
||||
AUD_EffectReader(reader),
|
||||
m_start(int(start * reader->getSpecs().rate)),
|
||||
m_end(int(end * reader->getSpecs().rate))
|
||||
{
|
||||
m_end = (int)(end * reader->getSpecs().rate);
|
||||
|
||||
if(start <= 0)
|
||||
m_start = 0;
|
||||
else
|
||||
if(m_start > 0)
|
||||
{
|
||||
m_start = (int)(start * reader->getSpecs().rate);
|
||||
if(m_reader->isSeekable())
|
||||
m_reader->seek(m_start);
|
||||
else
|
||||
{
|
||||
// skip first m_start samples by reading them
|
||||
int length;
|
||||
int length = AUD_DEFAULT_BUFFER_SIZE;
|
||||
sample_t* buffer;
|
||||
for(int i = m_start;
|
||||
i >= AUD_DEFAULT_BUFFER_SIZE;
|
||||
i -= AUD_DEFAULT_BUFFER_SIZE)
|
||||
for(int len = m_start;
|
||||
length == AUD_DEFAULT_BUFFER_SIZE;
|
||||
len -= AUD_DEFAULT_BUFFER_SIZE)
|
||||
{
|
||||
length = AUD_DEFAULT_BUFFER_SIZE;
|
||||
if(len < AUD_DEFAULT_BUFFER_SIZE)
|
||||
length = len;
|
||||
m_reader->read(length, buffer);
|
||||
length = i;
|
||||
}
|
||||
m_reader->read(length, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,18 +60,18 @@ void AUD_LimiterReader::seek(int position)
|
||||
m_reader->seek(position + m_start);
|
||||
}
|
||||
|
||||
int AUD_LimiterReader::getLength()
|
||||
int AUD_LimiterReader::getLength() const
|
||||
{
|
||||
int len = m_reader->getLength();
|
||||
if(m_reader->getType() != AUD_TYPE_BUFFER || len < 0 ||
|
||||
(len > m_end && m_end >= 0))
|
||||
if(len < 0 || (len > m_end && m_end >= 0))
|
||||
len = m_end;
|
||||
return len - m_start;
|
||||
}
|
||||
|
||||
int AUD_LimiterReader::getPosition()
|
||||
int AUD_LimiterReader::getPosition() const
|
||||
{
|
||||
return m_reader->getPosition() - m_start;
|
||||
int pos = m_reader->getPosition();
|
||||
return AUD_MIN(pos, m_end) - m_start;
|
||||
}
|
||||
|
||||
void AUD_LimiterReader::read(int & length, sample_t* & buffer)
|
||||
@@ -83,7 +79,7 @@ void AUD_LimiterReader::read(int & length, sample_t* & buffer)
|
||||
if(m_end >= 0)
|
||||
{
|
||||
int position = m_reader->getPosition();
|
||||
if(position+length > m_end)
|
||||
if(position + length > m_end)
|
||||
length = m_end - position;
|
||||
if(length < 0)
|
||||
{
|
||||
|
||||
@@ -37,12 +37,16 @@ private:
|
||||
/**
|
||||
* The start sample: inclusive.
|
||||
*/
|
||||
int m_start;
|
||||
const int m_start;
|
||||
|
||||
/**
|
||||
* The end sample: exlusive.
|
||||
*/
|
||||
int m_end;
|
||||
const int m_end;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_LimiterReader(const AUD_LimiterReader&);
|
||||
AUD_LimiterReader& operator=(const AUD_LimiterReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -51,13 +55,12 @@ public:
|
||||
* \param start The desired start sample (inclusive).
|
||||
* \param end The desired end sample (exklusive), a negative value signals
|
||||
* that it should play to the end.
|
||||
* \exception AUD_Exception Thrown if the reader specified is NULL.
|
||||
*/
|
||||
AUD_LimiterReader(AUD_IReader* reader, float start = 0, float end = -1);
|
||||
|
||||
virtual void seek(int position);
|
||||
virtual int getLength();
|
||||
virtual int getPosition();
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -28,30 +28,16 @@
|
||||
|
||||
AUD_LoopFactory::AUD_LoopFactory(AUD_IFactory* factory, int loop) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_loop(loop) {}
|
||||
m_loop(loop)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_LoopFactory::AUD_LoopFactory(int loop) :
|
||||
AUD_EffectFactory(0),
|
||||
m_loop(loop) {}
|
||||
|
||||
int AUD_LoopFactory::getLoop()
|
||||
int AUD_LoopFactory::getLoop() const
|
||||
{
|
||||
return m_loop;
|
||||
}
|
||||
|
||||
void AUD_LoopFactory::setLoop(int loop)
|
||||
AUD_IReader* AUD_LoopFactory::createReader() const
|
||||
{
|
||||
m_loop = loop;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_LoopFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_LoopReader(reader, m_loop); AUD_NEW("reader")
|
||||
}
|
||||
|
||||
return reader;
|
||||
return new AUD_LoopReader(getReader(), m_loop);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,11 @@ private:
|
||||
/**
|
||||
* The loop count.
|
||||
*/
|
||||
int m_loop;
|
||||
const int m_loop;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_LoopFactory(const AUD_LoopFactory&);
|
||||
AUD_LoopFactory& operator=(const AUD_LoopFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -47,28 +51,14 @@ public:
|
||||
* \param loop The desired loop count, negative values result in endless
|
||||
* looping.
|
||||
*/
|
||||
AUD_LoopFactory(AUD_IFactory* factory = 0, int loop = -1);
|
||||
|
||||
/**
|
||||
* Creates a new loop factory.
|
||||
* \param loop The desired loop count, negative values result in endless
|
||||
* looping.
|
||||
*/
|
||||
AUD_LoopFactory(int loop);
|
||||
AUD_LoopFactory(AUD_IFactory* factory, int loop = -1);
|
||||
|
||||
/**
|
||||
* Returns the loop count.
|
||||
*/
|
||||
int getLoop();
|
||||
int getLoop() const;
|
||||
|
||||
/**
|
||||
* Sets the loop count.
|
||||
* \param loop The desired loop count, negative values result in endless
|
||||
* looping.
|
||||
*/
|
||||
void setLoop(int loop);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_LOOPFACTORY
|
||||
|
||||
@@ -29,36 +29,37 @@
|
||||
#include <cstring>
|
||||
|
||||
AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) :
|
||||
AUD_EffectReader(reader), m_loop(loop)
|
||||
AUD_EffectReader(reader), m_count(loop), m_left(loop)
|
||||
{
|
||||
m_samples = -1;
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
}
|
||||
|
||||
AUD_LoopReader::~AUD_LoopReader()
|
||||
void AUD_LoopReader::seek(int position)
|
||||
{
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
}
|
||||
|
||||
AUD_ReaderType AUD_LoopReader::getType()
|
||||
{
|
||||
if(m_loop < 0)
|
||||
return AUD_TYPE_STREAM;
|
||||
return m_reader->getType();
|
||||
}
|
||||
|
||||
bool AUD_LoopReader::notify(AUD_Message &message)
|
||||
{
|
||||
if(message.type == AUD_MSG_LOOP)
|
||||
int len = m_reader->getLength();
|
||||
if(len < 0)
|
||||
m_reader->seek(position);
|
||||
else
|
||||
{
|
||||
m_loop = message.loopcount;
|
||||
m_samples = message.time * m_reader->getSpecs().rate;
|
||||
|
||||
m_reader->notify(message);
|
||||
|
||||
return true;
|
||||
if(m_count >= 0)
|
||||
{
|
||||
m_left = m_count - (position / len);
|
||||
if(m_left < 0)
|
||||
m_left = 0;
|
||||
}
|
||||
m_reader->seek(position % len);
|
||||
}
|
||||
return m_reader->notify(message);
|
||||
}
|
||||
|
||||
int AUD_LoopReader::getLength() const
|
||||
{
|
||||
if(m_count < 0)
|
||||
return -1;
|
||||
return m_reader->getLength() * m_count;
|
||||
}
|
||||
|
||||
int AUD_LoopReader::getPosition() const
|
||||
{
|
||||
return m_reader->getPosition() * (m_count < 0 ? 1 : m_count);
|
||||
}
|
||||
|
||||
void AUD_LoopReader::read(int & length, sample_t* & buffer)
|
||||
@@ -66,50 +67,44 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer)
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
|
||||
if(m_samples >= 0)
|
||||
{
|
||||
if(length > m_samples)
|
||||
length = m_samples;
|
||||
m_samples -= length;
|
||||
}
|
||||
|
||||
int len = length;
|
||||
|
||||
m_reader->read(len, buffer);
|
||||
|
||||
if(len < length && m_loop != 0)
|
||||
if(len < length && m_left)
|
||||
{
|
||||
int pos = 0;
|
||||
|
||||
if(m_buffer->getSize() < length * samplesize)
|
||||
m_buffer->resize(length * samplesize);
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
m_buffer.resize(length * samplesize);
|
||||
|
||||
memcpy(m_buffer->getBuffer() + pos * specs.channels,
|
||||
buffer, len * samplesize);
|
||||
sample_t* buf = m_buffer.getBuffer();
|
||||
|
||||
memcpy(buf + pos * specs.channels, buffer, len * samplesize);
|
||||
|
||||
pos += len;
|
||||
|
||||
while(pos < length && m_loop != 0)
|
||||
while(pos < length && m_left)
|
||||
{
|
||||
if(m_loop > 0)
|
||||
m_loop--;
|
||||
if(m_left > 0)
|
||||
m_left--;
|
||||
|
||||
m_reader->seek(0);
|
||||
|
||||
len = length - pos;
|
||||
m_reader->read(len, buffer);
|
||||
|
||||
// prevent endless loop
|
||||
if(!len)
|
||||
break;
|
||||
|
||||
memcpy(m_buffer->getBuffer() + pos * specs.channels,
|
||||
buffer, len * samplesize);
|
||||
memcpy(buf + pos * specs.channels, buffer, len * samplesize);
|
||||
|
||||
pos += len;
|
||||
}
|
||||
|
||||
length = pos;
|
||||
buffer = m_buffer->getBuffer();
|
||||
buffer = buf;
|
||||
}
|
||||
else
|
||||
length = len;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#define AUD_LOOPREADER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
/**
|
||||
* This class reads another reader and loops it.
|
||||
@@ -39,17 +39,21 @@ private:
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer *m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The loop count.
|
||||
*/
|
||||
const int m_count;
|
||||
|
||||
/**
|
||||
* The left loop count.
|
||||
*/
|
||||
int m_loop;
|
||||
int m_left;
|
||||
|
||||
/**
|
||||
* The left samples.
|
||||
*/
|
||||
int m_samples;
|
||||
// hide copy constructor and operator=
|
||||
AUD_LoopReader(const AUD_LoopReader&);
|
||||
AUD_LoopReader& operator=(const AUD_LoopReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -57,17 +61,12 @@ public:
|
||||
* \param reader The reader to read from.
|
||||
* \param loop The desired loop count, negative values result in endless
|
||||
* looping.
|
||||
* \exception AUD_Exception Thrown if the reader specified is NULL.
|
||||
*/
|
||||
AUD_LoopReader(AUD_IReader* reader, int loop);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
*/
|
||||
virtual ~AUD_LoopReader();
|
||||
|
||||
virtual AUD_ReaderType getType();
|
||||
virtual bool notify(AUD_Message &message);
|
||||
virtual void seek(int position);
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -24,28 +24,38 @@
|
||||
*/
|
||||
|
||||
#include "AUD_LowpassFactory.h"
|
||||
#include "AUD_LowpassReader.h"
|
||||
#include "AUD_IIRFilterReader.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
AUD_LowpassFactory::AUD_LowpassFactory(AUD_IFactory* factory, float frequency,
|
||||
float Q) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_frequency(frequency),
|
||||
m_Q(Q) {}
|
||||
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* AUD_LowpassFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_LowpassReader(reader, m_frequency, m_Q);
|
||||
AUD_NEW("reader")
|
||||
}
|
||||
// calculate coefficients
|
||||
float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate;
|
||||
float alpha = sin(w0) / (2 * m_Q);
|
||||
float norm = 1 + alpha;
|
||||
float c = cos(w0);
|
||||
std::vector<float> a, b;
|
||||
a.push_back(1);
|
||||
a.push_back(-2 * c / norm);
|
||||
a.push_back((1 - alpha) / norm);
|
||||
b.push_back((1 - c) / (2 * norm));
|
||||
b.push_back((1 - c) / norm);
|
||||
b.push_back(b[0]);
|
||||
|
||||
return reader;
|
||||
return new AUD_IIRFilterReader(reader, b, a);
|
||||
}
|
||||
|
||||
@@ -37,12 +37,16 @@ private:
|
||||
/**
|
||||
* The attack value in seconds.
|
||||
*/
|
||||
float m_frequency;
|
||||
const float m_frequency;
|
||||
|
||||
/**
|
||||
* The Q factor.
|
||||
*/
|
||||
float m_Q;
|
||||
const float m_Q;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_LowpassFactory(const AUD_LowpassFactory&);
|
||||
AUD_LowpassFactory& operator=(const AUD_LowpassFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -53,14 +57,7 @@ public:
|
||||
*/
|
||||
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();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_LOWPASSFACTORY
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN LGPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* AudaSpace is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "AUD_LowpassReader.h"
|
||||
#include "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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,40 +28,25 @@
|
||||
#include "AUD_ReverseFactory.h"
|
||||
|
||||
AUD_PingPongFactory::AUD_PingPongFactory(AUD_IFactory* factory) :
|
||||
AUD_EffectFactory(factory) {}
|
||||
|
||||
AUD_IReader* AUD_PingPongFactory::createReader()
|
||||
AUD_EffectFactory(factory)
|
||||
{
|
||||
if(m_factory == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
AUD_IReader* reader = m_factory->createReader();
|
||||
AUD_IReader* AUD_PingPongFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
AUD_IReader* reader2;
|
||||
AUD_ReverseFactory factory(m_factory);
|
||||
|
||||
if(reader != 0)
|
||||
try
|
||||
{
|
||||
AUD_IReader* reader2;
|
||||
AUD_ReverseFactory factory(m_factory);
|
||||
|
||||
try
|
||||
{
|
||||
reader2 = factory.createReader();
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
{
|
||||
reader2 = 0;
|
||||
}
|
||||
|
||||
if(reader2 != 0)
|
||||
{
|
||||
reader = new AUD_DoubleReader(reader, reader2);
|
||||
AUD_NEW("reader")
|
||||
}
|
||||
else
|
||||
{
|
||||
delete reader; AUD_DELETE("reader")
|
||||
reader = 0;
|
||||
}
|
||||
reader2 = factory.createReader();
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
delete reader;
|
||||
throw;
|
||||
}
|
||||
|
||||
return reader;
|
||||
return new AUD_DoubleReader(reader, reader2);
|
||||
}
|
||||
|
||||
@@ -34,18 +34,19 @@
|
||||
*/
|
||||
class AUD_PingPongFactory : public AUD_EffectFactory
|
||||
{
|
||||
private:
|
||||
// hide copy constructor and operator=
|
||||
AUD_PingPongFactory(const AUD_PingPongFactory&);
|
||||
AUD_PingPongFactory& operator=(const AUD_PingPongFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new ping pong factory.
|
||||
* \param factory The input factory.
|
||||
*/
|
||||
AUD_PingPongFactory(AUD_IFactory* factory = 0);
|
||||
AUD_PingPongFactory(AUD_IFactory* factory);
|
||||
|
||||
/**
|
||||
* Destroys the factory.
|
||||
*/
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_PINGPONGFACTORY
|
||||
|
||||
@@ -29,20 +29,11 @@
|
||||
|
||||
AUD_PitchFactory::AUD_PitchFactory(AUD_IFactory* factory, float pitch) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_pitch(pitch) {}
|
||||
|
||||
AUD_PitchFactory::AUD_PitchFactory(float pitch) :
|
||||
AUD_EffectFactory(0),
|
||||
m_pitch(pitch) {}
|
||||
|
||||
AUD_IReader* AUD_PitchFactory::createReader()
|
||||
m_pitch(pitch)
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_PitchReader(reader, m_pitch); AUD_NEW("reader")
|
||||
}
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_PitchFactory::createReader() const
|
||||
{
|
||||
return new AUD_PitchReader(getReader(), m_pitch);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,11 @@ private:
|
||||
/**
|
||||
* The pitch.
|
||||
*/
|
||||
float m_pitch;
|
||||
const float m_pitch;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_PitchFactory(const AUD_PitchFactory&);
|
||||
AUD_PitchFactory& operator=(const AUD_PitchFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -45,26 +49,9 @@ public:
|
||||
* \param factory The input factory.
|
||||
* \param pitch The desired pitch.
|
||||
*/
|
||||
AUD_PitchFactory(AUD_IFactory* factory = 0, float pitch = 1.0f);
|
||||
AUD_PitchFactory(AUD_IFactory* factory, float pitch);
|
||||
|
||||
/**
|
||||
* Creates a new pitch factory.
|
||||
* \param pitch The desired pitch.
|
||||
*/
|
||||
AUD_PitchFactory(float pitch);
|
||||
|
||||
/**
|
||||
* Returns the pitch.
|
||||
*/
|
||||
float getPitch();
|
||||
|
||||
/**
|
||||
* Sets the pitch.
|
||||
* \param pitch The new pitch value. Should be between 0.0 and 1.0.
|
||||
*/
|
||||
void setPitch(float pitch);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_PITCHFACTORY
|
||||
|
||||
@@ -26,12 +26,11 @@
|
||||
#include "AUD_PitchReader.h"
|
||||
|
||||
AUD_PitchReader::AUD_PitchReader(AUD_IReader* reader, float pitch) :
|
||||
AUD_EffectReader(reader)
|
||||
AUD_EffectReader(reader), m_pitch(pitch)
|
||||
{
|
||||
m_pitch = pitch;
|
||||
}
|
||||
|
||||
AUD_Specs AUD_PitchReader::getSpecs()
|
||||
AUD_Specs AUD_PitchReader::getSpecs() const
|
||||
{
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
specs.rate = (AUD_SampleRate)((int)(specs.rate * m_pitch));
|
||||
|
||||
@@ -37,18 +37,21 @@ private:
|
||||
/**
|
||||
* The pitch level.
|
||||
*/
|
||||
float m_pitch;
|
||||
const float m_pitch;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_PitchReader(const AUD_PitchReader&);
|
||||
AUD_PitchReader& operator=(const AUD_PitchReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new pitch reader.
|
||||
* \param reader The reader to read from.
|
||||
* \param pitch The size of the buffer.
|
||||
* \exception AUD_Exception Thrown if the reader specified is NULL.
|
||||
*/
|
||||
AUD_PitchReader(AUD_IReader* reader, float pitch);
|
||||
|
||||
virtual AUD_Specs getSpecs();
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
};
|
||||
|
||||
#endif //AUD_PITCHREADER
|
||||
|
||||
@@ -24,22 +24,21 @@
|
||||
*/
|
||||
|
||||
#include "AUD_RectifyFactory.h"
|
||||
#include "AUD_RectifyReader.h"
|
||||
#include "AUD_CallbackIIRFilterReader.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
sample_t rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
|
||||
{
|
||||
return fabs(reader->x(0));
|
||||
}
|
||||
|
||||
AUD_RectifyFactory::AUD_RectifyFactory(AUD_IFactory* factory) :
|
||||
AUD_EffectFactory(factory) {}
|
||||
|
||||
AUD_RectifyFactory::AUD_RectifyFactory() :
|
||||
AUD_EffectFactory(0) {}
|
||||
|
||||
AUD_IReader* AUD_RectifyFactory::createReader()
|
||||
AUD_EffectFactory(factory)
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_RectifyReader(reader); AUD_NEW("reader")
|
||||
}
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_RectifyFactory::createReader() const
|
||||
{
|
||||
return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, rectifyFilter);
|
||||
}
|
||||
|
||||
@@ -33,19 +33,19 @@
|
||||
*/
|
||||
class AUD_RectifyFactory : public AUD_EffectFactory
|
||||
{
|
||||
private:
|
||||
// hide copy constructor and operator=
|
||||
AUD_RectifyFactory(const AUD_RectifyFactory&);
|
||||
AUD_RectifyFactory& operator=(const AUD_RectifyFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new rectify factory.
|
||||
* \param factory The input factory.
|
||||
*/
|
||||
AUD_RectifyFactory(AUD_IFactory* factory = 0);
|
||||
AUD_RectifyFactory(AUD_IFactory* factory);
|
||||
|
||||
/**
|
||||
* Creates a new rectify factory.
|
||||
*/
|
||||
AUD_RectifyFactory();
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_RECTIFYFACTORY
|
||||
|
||||
@@ -28,16 +28,11 @@
|
||||
#include "AUD_Space.h"
|
||||
|
||||
AUD_ReverseFactory::AUD_ReverseFactory(AUD_IFactory* factory) :
|
||||
AUD_EffectFactory(factory) {}
|
||||
|
||||
AUD_IReader* AUD_ReverseFactory::createReader()
|
||||
AUD_EffectFactory(factory)
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_ReverseReader(reader); AUD_NEW("reader")
|
||||
}
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_ReverseFactory::createReader() const
|
||||
{
|
||||
return new AUD_ReverseReader(getReader());
|
||||
}
|
||||
|
||||
@@ -34,17 +34,19 @@
|
||||
*/
|
||||
class AUD_ReverseFactory : public AUD_EffectFactory
|
||||
{
|
||||
private:
|
||||
// hide copy constructor and operator=
|
||||
AUD_ReverseFactory(const AUD_ReverseFactory&);
|
||||
AUD_ReverseFactory& operator=(const AUD_ReverseFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new reverse factory.
|
||||
* \param factory The input factory.
|
||||
*/
|
||||
AUD_ReverseFactory(AUD_IFactory* factory = 0);
|
||||
AUD_ReverseFactory(AUD_IFactory* factory);
|
||||
|
||||
/**
|
||||
* Destroys the factory.
|
||||
*/
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_REVERSEFACTORY
|
||||
|
||||
@@ -24,27 +24,19 @@
|
||||
*/
|
||||
|
||||
#include "AUD_ReverseReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
static const char* props_error = "AUD_ReverseReader: The reader has to be "
|
||||
"seekable and a finite length.";
|
||||
|
||||
AUD_ReverseReader::AUD_ReverseReader(AUD_IReader* reader) :
|
||||
AUD_EffectReader(reader)
|
||||
AUD_EffectReader(reader),
|
||||
m_length(reader->getLength()),
|
||||
m_position(0)
|
||||
{
|
||||
if(reader->getType() != AUD_TYPE_BUFFER)
|
||||
AUD_THROW(AUD_ERROR_READER);
|
||||
|
||||
m_length = reader->getLength();
|
||||
if(m_length < 0)
|
||||
AUD_THROW(AUD_ERROR_READER);
|
||||
|
||||
m_position = 0;
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
}
|
||||
|
||||
AUD_ReverseReader::~AUD_ReverseReader()
|
||||
{
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
if(m_length < 0 || !reader->isSeekable())
|
||||
AUD_THROW(AUD_ERROR_PROPS, props_error);
|
||||
}
|
||||
|
||||
void AUD_ReverseReader::seek(int position)
|
||||
@@ -52,12 +44,12 @@ void AUD_ReverseReader::seek(int position)
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
int AUD_ReverseReader::getLength()
|
||||
int AUD_ReverseReader::getLength() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
int AUD_ReverseReader::getPosition()
|
||||
int AUD_ReverseReader::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
@@ -66,7 +58,7 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
// first correct the length
|
||||
if(m_position + length > m_length)
|
||||
length = m_length-m_position;
|
||||
length = m_length - m_position;
|
||||
|
||||
if(length <= 0)
|
||||
{
|
||||
@@ -78,10 +70,10 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer)
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
|
||||
// resize buffer if needed
|
||||
if(m_buffer->getSize() < length * samplesize)
|
||||
m_buffer->resize(length * samplesize);
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
m_buffer.resize(length * samplesize);
|
||||
|
||||
buffer = m_buffer->getBuffer();
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
sample_t* buf;
|
||||
int len = length;
|
||||
@@ -105,5 +97,5 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer)
|
||||
|
||||
m_position += length;
|
||||
|
||||
buffer = m_buffer->getBuffer();
|
||||
buffer = m_buffer.getBuffer();
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#define AUD_REVERSEREADER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
/**
|
||||
* This class reads another reader from back to front.
|
||||
@@ -36,38 +36,37 @@ class AUD_Buffer;
|
||||
class AUD_ReverseReader : public AUD_EffectReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The sample count.
|
||||
*/
|
||||
const int m_length;
|
||||
|
||||
/**
|
||||
* The current position.
|
||||
*/
|
||||
int m_position;
|
||||
|
||||
/**
|
||||
* The sample count.
|
||||
*/
|
||||
int m_length;
|
||||
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer* m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_ReverseReader(const AUD_ReverseReader&);
|
||||
AUD_ReverseReader& operator=(const AUD_ReverseReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new reverse reader.
|
||||
* \param reader The reader to read from.
|
||||
* \exception AUD_Exception Thrown if the reader specified is NULL or not
|
||||
* a buffer.
|
||||
* \exception AUD_Exception Thrown if the reader specified has an
|
||||
* undeterminable/infinite length or is not seekable.
|
||||
*/
|
||||
AUD_ReverseReader(AUD_IReader* reader);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
*/
|
||||
virtual ~AUD_ReverseReader();
|
||||
|
||||
virtual void seek(int position);
|
||||
virtual int getLength();
|
||||
virtual int getPosition();
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -24,34 +24,39 @@
|
||||
*/
|
||||
|
||||
#include "AUD_SquareFactory.h"
|
||||
#include "AUD_SquareReader.h"
|
||||
#include "AUD_CallbackIIRFilterReader.h"
|
||||
|
||||
sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold)
|
||||
{
|
||||
float in = reader->x(0);
|
||||
if(in >= *threshold)
|
||||
return 1;
|
||||
else if(in <= -*threshold)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void endSquareFilter(float* threshold)
|
||||
{
|
||||
delete threshold;
|
||||
}
|
||||
|
||||
AUD_SquareFactory::AUD_SquareFactory(AUD_IFactory* factory, float threshold) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_threshold(threshold) {}
|
||||
m_threshold(threshold)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_SquareFactory::AUD_SquareFactory(float threshold) :
|
||||
AUD_EffectFactory(0),
|
||||
m_threshold(threshold) {}
|
||||
|
||||
float AUD_SquareFactory::getThreshold()
|
||||
float AUD_SquareFactory::getThreshold() const
|
||||
{
|
||||
return m_threshold;
|
||||
}
|
||||
|
||||
void AUD_SquareFactory::setThreshold(float threshold)
|
||||
AUD_IReader* AUD_SquareFactory::createReader() const
|
||||
{
|
||||
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;
|
||||
return new AUD_CallbackIIRFilterReader(getReader(), 1, 1,
|
||||
(doFilterIIR) squareFilter,
|
||||
(endFilterIIR) endSquareFilter,
|
||||
new float(m_threshold));
|
||||
}
|
||||
|
||||
@@ -37,7 +37,11 @@ private:
|
||||
/**
|
||||
* The threshold.
|
||||
*/
|
||||
float m_threshold;
|
||||
const float m_threshold;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SquareFactory(const AUD_SquareFactory&);
|
||||
AUD_SquareFactory& operator=(const AUD_SquareFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -45,26 +49,14 @@ public:
|
||||
* \param factory The input factory.
|
||||
* \param threshold The threshold.
|
||||
*/
|
||||
AUD_SquareFactory(AUD_IFactory* factory = 0, float threshold = 0.0f);
|
||||
|
||||
/**
|
||||
* Creates a new square factory.
|
||||
* \param threshold The threshold.
|
||||
*/
|
||||
AUD_SquareFactory(float threshold);
|
||||
AUD_SquareFactory(AUD_IFactory* factory, float threshold = 0.0f);
|
||||
|
||||
/**
|
||||
* Returns the threshold.
|
||||
*/
|
||||
float getThreshold();
|
||||
float getThreshold() const;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_SQUAREFACTORY
|
||||
|
||||
@@ -24,20 +24,18 @@
|
||||
*/
|
||||
|
||||
#include "AUD_SumFactory.h"
|
||||
#include "AUD_SumReader.h"
|
||||
#include "AUD_IIRFilterReader.h"
|
||||
|
||||
AUD_SumFactory::AUD_SumFactory(AUD_IFactory* factory) :
|
||||
AUD_EffectFactory(factory) {}
|
||||
|
||||
AUD_IReader* AUD_SumFactory::createReader()
|
||||
AUD_EffectFactory(factory)
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_SumReader(reader);
|
||||
AUD_NEW("reader")
|
||||
}
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_SumFactory::createReader() const
|
||||
{
|
||||
std::vector<float> a, b;
|
||||
a.push_back(1);
|
||||
a.push_back(-1);
|
||||
b.push_back(1);
|
||||
return new AUD_IIRFilterReader(getReader(), b, a);
|
||||
}
|
||||
|
||||
@@ -33,14 +33,19 @@
|
||||
*/
|
||||
class AUD_SumFactory : public AUD_EffectFactory
|
||||
{
|
||||
private:
|
||||
// hide copy constructor and operator=
|
||||
AUD_SumFactory(const AUD_SumFactory&);
|
||||
AUD_SumFactory& operator=(const AUD_SumFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new sum factory.
|
||||
* \param factory The input factory.
|
||||
*/
|
||||
AUD_SumFactory(AUD_IFactory* factory = 0);
|
||||
AUD_SumFactory(AUD_IFactory* factory);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_SUMFACTORY
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN LGPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* AudaSpace is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "AUD_SumReader.h"
|
||||
#include "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];
|
||||
}
|
||||
49
intern/audaspace/FX/AUD_SuperposeFactory.cpp
Normal file
49
intern/audaspace/FX/AUD_SuperposeFactory.cpp
Normal 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_SuperposeFactory.h"
|
||||
#include "AUD_SuperposeReader.h"
|
||||
|
||||
AUD_SuperposeFactory::AUD_SuperposeFactory(AUD_IFactory* factory1, AUD_IFactory* factory2) :
|
||||
m_factory1(factory1), m_factory2(factory2)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_SuperposeFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader1 = m_factory1->createReader();
|
||||
AUD_IReader* reader2;
|
||||
try
|
||||
{
|
||||
reader2 = m_factory2->createReader();
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
delete reader1;
|
||||
throw;
|
||||
}
|
||||
|
||||
return new AUD_SuperposeReader(reader1, reader2);
|
||||
}
|
||||
63
intern/audaspace/FX/AUD_SuperposeFactory.h
Normal file
63
intern/audaspace/FX/AUD_SuperposeFactory.h
Normal 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 *****
|
||||
*/
|
||||
|
||||
#ifndef AUD_SUPERPOSEFACTORY
|
||||
#define AUD_SUPERPOSEFACTORY
|
||||
|
||||
#include "AUD_IFactory.h"
|
||||
|
||||
/**
|
||||
* This factory plays two other factories behind each other.
|
||||
* \note Readers from the underlying factories must have the same sample rate and channel count.
|
||||
*/
|
||||
class AUD_SuperposeFactory : public AUD_IFactory
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* First played factory.
|
||||
*/
|
||||
AUD_IFactory* m_factory1;
|
||||
|
||||
/**
|
||||
* Second played factory.
|
||||
*/
|
||||
AUD_IFactory* m_factory2;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SuperposeFactory(const AUD_SuperposeFactory&);
|
||||
AUD_SuperposeFactory& operator=(const AUD_SuperposeFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new superpose factory.
|
||||
* \param factory1 The first input factory.
|
||||
* \param factory2 The second input factory.
|
||||
*/
|
||||
AUD_SuperposeFactory(AUD_IFactory* factory1, AUD_IFactory* factory2);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_SUPERPOSEFACTORY
|
||||
115
intern/audaspace/FX/AUD_SuperposeReader.cpp
Normal file
115
intern/audaspace/FX/AUD_SuperposeReader.cpp
Normal 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_SuperposeReader.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
static const char* specs_error = "AUD_SuperposeReader: Both readers have to "
|
||||
"have the same specs.";
|
||||
|
||||
AUD_SuperposeReader::AUD_SuperposeReader(AUD_IReader* reader1, AUD_IReader* reader2) :
|
||||
m_reader1(reader1), m_reader2(reader2)
|
||||
{
|
||||
try
|
||||
{
|
||||
AUD_Specs s1, s2;
|
||||
s1 = reader1->getSpecs();
|
||||
s2 = reader2->getSpecs();
|
||||
if(memcmp(&s1, &s2, sizeof(AUD_Specs)))
|
||||
AUD_THROW(AUD_ERROR_SPECS, specs_error);
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
delete reader1;
|
||||
delete reader2;
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
AUD_SuperposeReader::~AUD_SuperposeReader()
|
||||
{
|
||||
delete m_reader1;
|
||||
delete m_reader2;
|
||||
}
|
||||
|
||||
bool AUD_SuperposeReader::isSeekable() const
|
||||
{
|
||||
return m_reader1->isSeekable() && m_reader2->isSeekable();
|
||||
}
|
||||
|
||||
void AUD_SuperposeReader::seek(int position)
|
||||
{
|
||||
m_reader1->seek(position);
|
||||
m_reader2->seek(position);
|
||||
}
|
||||
|
||||
int AUD_SuperposeReader::getLength() const
|
||||
{
|
||||
int len1 = m_reader1->getLength();
|
||||
int len2 = m_reader2->getLength();
|
||||
if((len1 < 0) || (len2 < 0))
|
||||
return -1;
|
||||
return AUD_MIN(len1, len2);
|
||||
}
|
||||
|
||||
int AUD_SuperposeReader::getPosition() const
|
||||
{
|
||||
int pos1 = m_reader1->getPosition();
|
||||
int pos2 = m_reader2->getPosition();
|
||||
return AUD_MAX(pos1, pos2);
|
||||
}
|
||||
|
||||
AUD_Specs AUD_SuperposeReader::getSpecs() const
|
||||
{
|
||||
return m_reader1->getSpecs();
|
||||
}
|
||||
|
||||
void AUD_SuperposeReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
AUD_Specs specs = m_reader1->getSpecs();
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
m_buffer.resize(length * samplesize);
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
int len1 = length;
|
||||
sample_t* buf;
|
||||
m_reader1->read(len1, buf);
|
||||
memcpy(buffer, buf, len1 * samplesize);
|
||||
|
||||
if(len1 < length)
|
||||
memset(buffer + len1 * specs.channels, 0, (length - len1) * samplesize);
|
||||
|
||||
int len2 = length;
|
||||
m_reader2->read(len2, buf);
|
||||
|
||||
for(int i = 0; i < len2 * specs.channels; i++)
|
||||
buffer[i] += buf[i];
|
||||
|
||||
length = AUD_MAX(len1, len2);
|
||||
}
|
||||
79
intern/audaspace/FX/AUD_SuperposeReader.h
Normal file
79
intern/audaspace/FX/AUD_SuperposeReader.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* $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_SUPERPOSEREADER
|
||||
#define AUD_SUPERPOSEREADER
|
||||
|
||||
#include "AUD_IReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
/**
|
||||
* This reader plays two readers with the same specs sequently.
|
||||
*/
|
||||
class AUD_SuperposeReader : public AUD_IReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The first reader.
|
||||
*/
|
||||
AUD_IReader* m_reader1;
|
||||
|
||||
/**
|
||||
* The second reader.
|
||||
*/
|
||||
AUD_IReader* m_reader2;
|
||||
|
||||
/**
|
||||
* The playback buffer for the intersecting part.
|
||||
*/
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SuperposeReader(const AUD_SuperposeReader&);
|
||||
AUD_SuperposeReader& operator=(const AUD_SuperposeReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new superpose reader.
|
||||
* \param reader1 The first reader to read from.
|
||||
* \param reader2 The second reader to read from.
|
||||
* \exception AUD_Exception Thrown if the specs from the readers differ.
|
||||
*/
|
||||
AUD_SuperposeReader(AUD_IReader* reader1, AUD_IReader* reader2);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
*/
|
||||
virtual ~AUD_SuperposeReader();
|
||||
|
||||
virtual bool isSeekable() const;
|
||||
virtual void seek(int position);
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_SUPERPOSEREADER
|
||||
@@ -24,34 +24,23 @@
|
||||
*/
|
||||
|
||||
#include "AUD_VolumeFactory.h"
|
||||
#include "AUD_VolumeReader.h"
|
||||
#include "AUD_IIRFilterReader.h"
|
||||
|
||||
AUD_VolumeFactory::AUD_VolumeFactory(AUD_IFactory* factory, float volume) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_volume(volume) {}
|
||||
m_volume(volume)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_VolumeFactory::AUD_VolumeFactory(float volume) :
|
||||
AUD_EffectFactory(0),
|
||||
m_volume(volume) {}
|
||||
|
||||
float AUD_VolumeFactory::getVolume()
|
||||
float AUD_VolumeFactory::getVolume() const
|
||||
{
|
||||
return m_volume;
|
||||
}
|
||||
|
||||
void AUD_VolumeFactory::setVolume(float volume)
|
||||
AUD_IReader* AUD_VolumeFactory::createReader() const
|
||||
{
|
||||
m_volume = volume;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_VolumeFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
reader = new AUD_VolumeReader(reader, m_volume); AUD_NEW("reader")
|
||||
}
|
||||
|
||||
return reader;
|
||||
std::vector<float> a, b;
|
||||
a.push_back(1);
|
||||
b.push_back(m_volume);
|
||||
return new AUD_IIRFilterReader(getReader(), b, a);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,11 @@ private:
|
||||
/**
|
||||
* The volume.
|
||||
*/
|
||||
float m_volume;
|
||||
const float m_volume;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_VolumeFactory(const AUD_VolumeFactory&);
|
||||
AUD_VolumeFactory& operator=(const AUD_VolumeFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -47,26 +51,14 @@ public:
|
||||
* \param factory The input factory.
|
||||
* \param volume The desired volume.
|
||||
*/
|
||||
AUD_VolumeFactory(AUD_IFactory* factory = 0, float volume = 1.0f);
|
||||
|
||||
/**
|
||||
* Creates a new volume factory.
|
||||
* \param volume The desired volume.
|
||||
*/
|
||||
AUD_VolumeFactory(float volume);
|
||||
AUD_VolumeFactory(AUD_IFactory* factory, float volume);
|
||||
|
||||
/**
|
||||
* Returns the volume.
|
||||
*/
|
||||
float getVolume();
|
||||
float getVolume() const;
|
||||
|
||||
/**
|
||||
* Sets the volume.
|
||||
* \param volume The new volume value. Should be between 0.0 and 1.0.
|
||||
*/
|
||||
void setVolume(float volume);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_VOLUMEFACTORY
|
||||
|
||||
@@ -1,69 +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_VolumeReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_VolumeReader::AUD_VolumeReader(AUD_IReader* reader, float volume) :
|
||||
AUD_EffectReader(reader),
|
||||
m_volume(volume)
|
||||
{
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
}
|
||||
|
||||
AUD_VolumeReader::~AUD_VolumeReader()
|
||||
{
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
}
|
||||
|
||||
bool AUD_VolumeReader::notify(AUD_Message &message)
|
||||
{
|
||||
if(message.type == AUD_MSG_VOLUME)
|
||||
{
|
||||
m_volume = message.volume;
|
||||
|
||||
m_reader->notify(message);
|
||||
|
||||
return true;
|
||||
}
|
||||
return m_reader->notify(message);
|
||||
}
|
||||
|
||||
void AUD_VolumeReader::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++)
|
||||
buffer[i] = buf[i] * m_volume;
|
||||
}
|
||||
@@ -24,9 +24,9 @@
|
||||
*/
|
||||
|
||||
#include "AUD_OpenALDevice.h"
|
||||
#include "AUD_IFactory.h"
|
||||
#include "AUD_IReader.h"
|
||||
#include "AUD_ConverterFactory.h"
|
||||
#include "AUD_SourceCaps.h"
|
||||
#include "AUD_ConverterReader.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
@@ -65,6 +65,15 @@ struct AUD_OpenALHandle : AUD_Handle
|
||||
|
||||
/// Whether the stream doesn't return any more data.
|
||||
bool data_end;
|
||||
|
||||
/// The loop count of the source.
|
||||
int loopcount;
|
||||
|
||||
/// The stop callback.
|
||||
stopCallback stop;
|
||||
|
||||
/// Stop callback data.
|
||||
void* stop_data;
|
||||
};
|
||||
|
||||
struct AUD_OpenALBufferedFactory
|
||||
@@ -128,13 +137,9 @@ void AUD_OpenALDevice::updateStreams()
|
||||
|
||||
{
|
||||
// for all sounds
|
||||
AUD_HandleIterator it = m_playingSounds->begin();
|
||||
while(it != m_playingSounds->end())
|
||||
for(AUD_HandleIterator it = m_playingSounds->begin(); it != m_playingSounds->end(); it++)
|
||||
{
|
||||
sound = *it;
|
||||
// increment the iterator to make sure it's valid,
|
||||
// in case the sound gets deleted after stopping
|
||||
++it;
|
||||
|
||||
// is it a streamed sound?
|
||||
if(!sound->isBuffered)
|
||||
@@ -156,6 +161,18 @@ void AUD_OpenALDevice::updateStreams()
|
||||
length = m_buffersize;
|
||||
sound->reader->read(length, buffer);
|
||||
|
||||
// looping necessary?
|
||||
if(length == 0 && sound->loopcount)
|
||||
{
|
||||
if(sound->loopcount > 0)
|
||||
sound->loopcount--;
|
||||
|
||||
sound->reader->seek(0);
|
||||
|
||||
length = m_buffersize;
|
||||
sound->reader->read(length, buffer);
|
||||
}
|
||||
|
||||
// read nothing?
|
||||
if(length == 0)
|
||||
{
|
||||
@@ -212,12 +229,21 @@ void AUD_OpenALDevice::updateStreams()
|
||||
// if it really stopped
|
||||
if(sound->data_end)
|
||||
{
|
||||
if(sound->stop)
|
||||
sound->stop(sound->stop_data);
|
||||
|
||||
// increment the iterator to the next value,
|
||||
// because the sound gets deleted in the list here.
|
||||
++it;
|
||||
// pause or
|
||||
if(sound->keep)
|
||||
pause(sound);
|
||||
// stop
|
||||
else
|
||||
stop(sound);
|
||||
// decrement again, so that we get the next sound in the
|
||||
// next loop run
|
||||
--it;
|
||||
}
|
||||
// continue playing
|
||||
else
|
||||
@@ -263,6 +289,8 @@ bool AUD_OpenALDevice::isValid(AUD_Handle* handle)
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened.";
|
||||
|
||||
AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
|
||||
{
|
||||
// cannot determine how many channels or which format OpenAL uses, but
|
||||
@@ -287,7 +315,7 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
|
||||
m_device = alcOpenDevice(NULL);
|
||||
|
||||
if(!m_device)
|
||||
AUD_THROW(AUD_ERROR_OPENAL);
|
||||
AUD_THROW(AUD_ERROR_OPENAL, open_error);
|
||||
|
||||
// at least try to set the frequency
|
||||
ALCint attribs[] = { ALC_FREQUENCY, specs.rate, 0 };
|
||||
@@ -302,12 +330,7 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
|
||||
|
||||
// check for specific formats and channel counts to be played back
|
||||
if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE)
|
||||
{
|
||||
specs.format = AUD_FORMAT_FLOAT32;
|
||||
m_converter = NULL;
|
||||
}
|
||||
else
|
||||
m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory")
|
||||
|
||||
m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE;
|
||||
|
||||
@@ -317,10 +340,9 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize)
|
||||
m_buffersize = buffersize;
|
||||
m_playing = false;
|
||||
|
||||
m_playingSounds = new std::list<AUD_OpenALHandle*>(); AUD_NEW("list")
|
||||
m_pausedSounds = new std::list<AUD_OpenALHandle*>(); AUD_NEW("list")
|
||||
m_playingSounds = new std::list<AUD_OpenALHandle*>();
|
||||
m_pausedSounds = new std::list<AUD_OpenALHandle*>();
|
||||
m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
|
||||
AUD_NEW("list")
|
||||
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
@@ -345,10 +367,10 @@ AUD_OpenALDevice::~AUD_OpenALDevice()
|
||||
alDeleteSources(1, &sound->source);
|
||||
if(!sound->isBuffered)
|
||||
{
|
||||
delete sound->reader; AUD_DELETE("reader")
|
||||
delete sound->reader;
|
||||
alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
|
||||
}
|
||||
delete sound; AUD_DELETE("handle")
|
||||
delete sound;
|
||||
m_playingSounds->erase(m_playingSounds->begin());
|
||||
}
|
||||
|
||||
@@ -359,10 +381,10 @@ AUD_OpenALDevice::~AUD_OpenALDevice()
|
||||
alDeleteSources(1, &sound->source);
|
||||
if(!sound->isBuffered)
|
||||
{
|
||||
delete sound->reader; AUD_DELETE("reader")
|
||||
delete sound->reader;
|
||||
alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
|
||||
}
|
||||
delete sound; AUD_DELETE("handle")
|
||||
delete sound;
|
||||
m_pausedSounds->erase(m_pausedSounds->begin());
|
||||
}
|
||||
|
||||
@@ -370,7 +392,7 @@ AUD_OpenALDevice::~AUD_OpenALDevice()
|
||||
while(!m_bufferedFactories->empty())
|
||||
{
|
||||
alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer);
|
||||
delete *m_bufferedFactories->begin(); AUD_DELETE("bufferedfactory");
|
||||
delete *m_bufferedFactories->begin();
|
||||
m_bufferedFactories->erase(m_bufferedFactories->begin());
|
||||
}
|
||||
|
||||
@@ -385,22 +407,19 @@ AUD_OpenALDevice::~AUD_OpenALDevice()
|
||||
else
|
||||
unlock();
|
||||
|
||||
delete m_playingSounds; AUD_DELETE("list")
|
||||
delete m_pausedSounds; AUD_DELETE("list")
|
||||
delete m_bufferedFactories; AUD_DELETE("list")
|
||||
delete m_playingSounds;
|
||||
delete m_pausedSounds;
|
||||
delete m_bufferedFactories;
|
||||
|
||||
// quit OpenAL
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(m_context);
|
||||
alcCloseDevice(m_device);
|
||||
|
||||
if(m_converter)
|
||||
delete m_converter; AUD_DELETE("factory")
|
||||
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
}
|
||||
|
||||
AUD_DeviceSpecs AUD_OpenALDevice::getSpecs()
|
||||
AUD_DeviceSpecs AUD_OpenALDevice::getSpecs() const
|
||||
{
|
||||
return m_specs;
|
||||
}
|
||||
@@ -496,6 +515,15 @@ bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs)
|
||||
return valid;
|
||||
}
|
||||
|
||||
static const char* genbuffer_error = "AUD_OpenALDevice: Buffer couldn't be "
|
||||
"generated.";
|
||||
static const char* gensource_error = "AUD_OpenALDevice: Source couldn't be "
|
||||
"generated.";
|
||||
static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be "
|
||||
"queued to the source.";
|
||||
static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be "
|
||||
"filled with data.";
|
||||
|
||||
AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
|
||||
{
|
||||
lock();
|
||||
@@ -511,11 +539,14 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
|
||||
if((*i)->factory == factory)
|
||||
{
|
||||
// create the handle
|
||||
sound = new AUD_OpenALHandle; AUD_NEW("handle")
|
||||
sound = new AUD_OpenALHandle;
|
||||
sound->keep = keep;
|
||||
sound->current = -1;
|
||||
sound->isBuffered = true;
|
||||
sound->data_end = true;
|
||||
sound->loopcount = 0;
|
||||
sound->stop = NULL;
|
||||
sound->stop_data = NULL;
|
||||
|
||||
alcSuspendContext(m_context);
|
||||
|
||||
@@ -524,23 +555,23 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
|
||||
{
|
||||
alGenSources(1, &sound->source);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
AUD_THROW(AUD_ERROR_OPENAL);
|
||||
AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
|
||||
|
||||
try
|
||||
{
|
||||
alSourcei(sound->source, AL_BUFFER, (*i)->buffer);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
AUD_THROW(AUD_ERROR_OPENAL);
|
||||
AUD_THROW(AUD_ERROR_OPENAL, queue_error);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
alDeleteSources(1, &sound->source);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
delete sound; AUD_DELETE("handle")
|
||||
delete sound;
|
||||
alcProcessContext(m_context);
|
||||
throw;
|
||||
}
|
||||
@@ -555,7 +586,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
unlock();
|
||||
throw;
|
||||
@@ -568,35 +599,32 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
|
||||
|
||||
AUD_IReader* reader = factory->createReader();
|
||||
|
||||
if(reader == NULL)
|
||||
AUD_THROW(AUD_ERROR_READER);
|
||||
|
||||
AUD_DeviceSpecs specs = m_specs;
|
||||
specs.specs = reader->getSpecs();
|
||||
|
||||
// check format
|
||||
bool valid = specs.channels != AUD_CHANNELS_INVALID;
|
||||
|
||||
if(m_converter)
|
||||
{
|
||||
m_converter->setReader(reader);
|
||||
reader = m_converter->createReader();
|
||||
}
|
||||
if(m_specs.format != AUD_FORMAT_FLOAT32)
|
||||
reader = new AUD_ConverterReader(reader, m_specs);
|
||||
|
||||
// create the handle
|
||||
sound = new AUD_OpenALHandle; AUD_NEW("handle")
|
||||
sound = new AUD_OpenALHandle;
|
||||
sound->keep = keep;
|
||||
sound->reader = reader;
|
||||
sound->current = 0;
|
||||
sound->isBuffered = false;
|
||||
sound->data_end = false;
|
||||
sound->loopcount = 0;
|
||||
sound->stop = NULL;
|
||||
sound->stop_data = NULL;
|
||||
|
||||
valid &= getFormat(sound->format, specs.specs);
|
||||
|
||||
if(!valid)
|
||||
{
|
||||
delete sound; AUD_DELETE("handle")
|
||||
delete reader; AUD_DELETE("reader")
|
||||
delete sound;
|
||||
delete reader;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -608,7 +636,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
|
||||
{
|
||||
alGenBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
AUD_THROW(AUD_ERROR_OPENAL);
|
||||
AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -623,36 +651,36 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
|
||||
length * AUD_DEVICE_SAMPLE_SIZE(specs),
|
||||
specs.rate);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
AUD_THROW(AUD_ERROR_OPENAL);
|
||||
AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error);
|
||||
}
|
||||
|
||||
alGenSources(1, &sound->source);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
AUD_THROW(AUD_ERROR_OPENAL);
|
||||
AUD_THROW(AUD_ERROR_OPENAL, gensource_error);
|
||||
|
||||
try
|
||||
{
|
||||
alSourceQueueBuffers(sound->source, AUD_OPENAL_CYCLE_BUFFERS,
|
||||
sound->buffers);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
AUD_THROW(AUD_ERROR_OPENAL);
|
||||
AUD_THROW(AUD_ERROR_OPENAL, queue_error);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
alDeleteSources(1, &sound->source);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
delete sound; AUD_DELETE("handle")
|
||||
delete reader; AUD_DELETE("reader")
|
||||
delete sound;
|
||||
delete reader;
|
||||
alcProcessContext(m_context);
|
||||
unlock();
|
||||
throw;
|
||||
@@ -737,10 +765,10 @@ bool AUD_OpenALDevice::stop(AUD_Handle* handle)
|
||||
alDeleteSources(1, &sound->source);
|
||||
if(!sound->isBuffered)
|
||||
{
|
||||
delete sound->reader; AUD_DELETE("reader")
|
||||
delete sound->reader;
|
||||
alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
|
||||
}
|
||||
delete *i; AUD_DELETE("handle")
|
||||
delete *i;
|
||||
m_playingSounds->erase(i);
|
||||
result = true;
|
||||
break;
|
||||
@@ -757,10 +785,10 @@ bool AUD_OpenALDevice::stop(AUD_Handle* handle)
|
||||
alDeleteSources(1, &sound->source);
|
||||
if(!sound->isBuffered)
|
||||
{
|
||||
delete sound->reader; AUD_DELETE("reader")
|
||||
delete sound->reader;
|
||||
alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers);
|
||||
}
|
||||
delete *i; AUD_DELETE("handle")
|
||||
delete *i;
|
||||
m_pausedSounds->erase(i);
|
||||
result = true;
|
||||
break;
|
||||
@@ -773,6 +801,20 @@ bool AUD_OpenALDevice::stop(AUD_Handle* handle)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::getKeep(AUD_Handle* handle)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
lock();
|
||||
|
||||
if(isValid(handle))
|
||||
result = ((AUD_OpenALHandle*)handle)->keep;
|
||||
|
||||
unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep)
|
||||
{
|
||||
bool result = false;
|
||||
@@ -790,32 +832,6 @@ bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::sendMessage(AUD_Handle* handle, AUD_Message &message)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
lock();
|
||||
|
||||
if(handle == 0)
|
||||
{
|
||||
for(AUD_HandleIterator i = m_playingSounds->begin();
|
||||
i != m_playingSounds->end(); i++)
|
||||
if(!(*i)->isBuffered)
|
||||
result |= (*i)->reader->notify(message);
|
||||
for(AUD_HandleIterator i = m_pausedSounds->begin();
|
||||
i != m_pausedSounds->end(); i++)
|
||||
if(!(*i)->isBuffered)
|
||||
result |= (*i)->reader->notify(message);
|
||||
}
|
||||
else if(isValid(handle))
|
||||
if(!((AUD_OpenALHandle*)handle)->isBuffered)
|
||||
result = ((AUD_OpenALHandle*)handle)->reader->notify(message);
|
||||
|
||||
unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position)
|
||||
{
|
||||
bool result = false;
|
||||
@@ -947,440 +963,657 @@ void AUD_OpenALDevice::unlock()
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**************************** Capabilities Code *******************************/
|
||||
/******************************************************************************/
|
||||
|
||||
bool AUD_OpenALDevice::checkCapability(int capability)
|
||||
float AUD_OpenALDevice::getVolume() const
|
||||
{
|
||||
return capability == AUD_CAPS_3D_DEVICE ||
|
||||
capability == AUD_CAPS_VOLUME ||
|
||||
capability == AUD_CAPS_SOURCE_VOLUME ||
|
||||
capability == AUD_CAPS_SOURCE_PITCH ||
|
||||
capability == AUD_CAPS_BUFFERED_FACTORY;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setCapability(int capability, void *value)
|
||||
{
|
||||
bool result = false;
|
||||
switch(capability)
|
||||
{
|
||||
case AUD_CAPS_VOLUME:
|
||||
alListenerf(AL_GAIN, *((float*)value));
|
||||
return true;
|
||||
case AUD_CAPS_SOURCE_VOLUME:
|
||||
{
|
||||
AUD_SourceCaps* caps = (AUD_SourceCaps*) value;
|
||||
lock();
|
||||
if(isValid(caps->handle))
|
||||
{
|
||||
alSourcef(((AUD_OpenALHandle*)caps->handle)->source,
|
||||
AL_GAIN, caps->value);
|
||||
result = true;
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
break;
|
||||
case AUD_CAPS_SOURCE_PITCH:
|
||||
{
|
||||
AUD_SourceCaps* caps = (AUD_SourceCaps*) value;
|
||||
lock();
|
||||
if(isValid(caps->handle))
|
||||
{
|
||||
alSourcef(((AUD_OpenALHandle*)caps->handle)->source,
|
||||
AL_PITCH, caps->value);
|
||||
result = true;
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
break;
|
||||
case AUD_CAPS_BUFFERED_FACTORY:
|
||||
{
|
||||
AUD_IFactory* factory = (AUD_IFactory*) value;
|
||||
|
||||
// load the factory into an OpenAL buffer
|
||||
if(factory)
|
||||
{
|
||||
// check if the factory is already buffered
|
||||
lock();
|
||||
for(AUD_BFIterator i = m_bufferedFactories->begin();
|
||||
i != m_bufferedFactories->end(); i++)
|
||||
{
|
||||
if((*i)->factory == factory)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
AUD_IReader* reader = factory->createReader();
|
||||
|
||||
if(reader == NULL)
|
||||
return false;
|
||||
|
||||
AUD_DeviceSpecs specs = m_specs;
|
||||
specs.specs = reader->getSpecs();
|
||||
|
||||
// determine format
|
||||
bool valid = reader->getType() == AUD_TYPE_BUFFER;
|
||||
|
||||
if(valid)
|
||||
{
|
||||
if(m_converter)
|
||||
{
|
||||
m_converter->setReader(reader);
|
||||
reader = m_converter->createReader();
|
||||
}
|
||||
}
|
||||
|
||||
ALenum format;
|
||||
|
||||
if(valid)
|
||||
valid = getFormat(format, specs.specs);
|
||||
|
||||
if(!valid)
|
||||
{
|
||||
delete reader; AUD_DELETE("reader")
|
||||
return false;
|
||||
}
|
||||
|
||||
// load into a buffer
|
||||
lock();
|
||||
alcSuspendContext(m_context);
|
||||
|
||||
AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory;
|
||||
AUD_NEW("bufferedfactory");
|
||||
bf->factory = factory;
|
||||
|
||||
try
|
||||
{
|
||||
alGenBuffers(1, &bf->buffer);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
AUD_THROW(AUD_ERROR_OPENAL);
|
||||
|
||||
try
|
||||
{
|
||||
sample_t* buf;
|
||||
int length = reader->getLength();
|
||||
|
||||
reader->read(length, buf);
|
||||
alBufferData(bf->buffer, format, buf,
|
||||
length * AUD_DEVICE_SAMPLE_SIZE(specs),
|
||||
specs.rate);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
AUD_THROW(AUD_ERROR_OPENAL);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
{
|
||||
alDeleteBuffers(1, &bf->buffer);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
{
|
||||
delete bf; AUD_DELETE("bufferedfactory")
|
||||
delete reader; AUD_DELETE("reader")
|
||||
alcProcessContext(m_context);
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_bufferedFactories->push_back(bf);
|
||||
|
||||
alcProcessContext(m_context);
|
||||
unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
// stop all playing and paused buffered sources
|
||||
lock();
|
||||
alcSuspendContext(m_context);
|
||||
|
||||
AUD_OpenALHandle* sound;
|
||||
AUD_HandleIterator it = m_playingSounds->begin();
|
||||
while(it != m_playingSounds->end())
|
||||
{
|
||||
sound = *it;
|
||||
++it;
|
||||
|
||||
if(sound->isBuffered)
|
||||
stop(sound);
|
||||
}
|
||||
alcProcessContext(m_context);
|
||||
|
||||
while(!m_bufferedFactories->empty())
|
||||
{
|
||||
alDeleteBuffers(1,
|
||||
&(*(m_bufferedFactories->begin()))->buffer);
|
||||
delete *m_bufferedFactories->begin();
|
||||
AUD_DELETE("bufferedfactory");
|
||||
m_bufferedFactories->erase(m_bufferedFactories->begin());
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
float result;
|
||||
alGetListenerf(AL_GAIN, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::getCapability(int capability, void *value)
|
||||
void AUD_OpenALDevice::setVolume(float volume)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
switch(capability)
|
||||
{
|
||||
case AUD_CAPS_VOLUME:
|
||||
alGetListenerf(AL_GAIN, (float*)value);
|
||||
return true;
|
||||
case AUD_CAPS_SOURCE_VOLUME:
|
||||
{
|
||||
AUD_SourceCaps* caps = (AUD_SourceCaps*) value;
|
||||
lock();
|
||||
if(isValid(caps->handle))
|
||||
{
|
||||
alGetSourcef(((AUD_OpenALHandle*)caps->handle)->source,
|
||||
AL_GAIN, &caps->value);
|
||||
result = true;
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
break;
|
||||
case AUD_CAPS_SOURCE_PITCH:
|
||||
{
|
||||
AUD_SourceCaps* caps = (AUD_SourceCaps*) value;
|
||||
lock();
|
||||
if(isValid(caps->handle))
|
||||
{
|
||||
alGetSourcef(((AUD_OpenALHandle*)caps->handle)->source,
|
||||
AL_PITCH, &caps->value);
|
||||
result = true;
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
alListenerf(AL_GAIN, volume);
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getVolume(AUD_Handle* handle)
|
||||
{
|
||||
lock();
|
||||
float result = std::numeric_limits<float>::quiet_NaN();
|
||||
if(isValid(handle))
|
||||
alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_GAIN, &result);
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setVolume(AUD_Handle* handle, float volume)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
if(result)
|
||||
alSourcef(((AUD_OpenALHandle*)handle)->source, AL_GAIN, volume);
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getPitch(AUD_Handle* handle)
|
||||
{
|
||||
lock();
|
||||
float result = std::numeric_limits<float>::quiet_NaN();
|
||||
if(isValid(handle))
|
||||
alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_PITCH, &result);
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setPitch(AUD_Handle* handle, float pitch)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
if(result)
|
||||
alSourcef(((AUD_OpenALHandle*)handle)->source, AL_PITCH, pitch);
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
int AUD_OpenALDevice::getLoopCount(AUD_Handle* handle)
|
||||
{
|
||||
lock();
|
||||
int result = 0;
|
||||
if(isValid(handle))
|
||||
result = ((AUD_OpenALHandle*)handle)->loopcount;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setLoopCount(AUD_Handle* handle, int count)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
if(result)
|
||||
((AUD_OpenALHandle*)handle)->loopcount = count;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
if(result)
|
||||
{
|
||||
AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle;
|
||||
h->stop = callback;
|
||||
h->stop_data = data;
|
||||
}
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
/* AUD_XXX Temorary disabled
|
||||
|
||||
bool AUD_OpenALDevice::bufferFactory(void *value)
|
||||
{
|
||||
bool result = false;
|
||||
AUD_IFactory* factory = (AUD_IFactory*) value;
|
||||
|
||||
// load the factory into an OpenAL buffer
|
||||
if(factory)
|
||||
{
|
||||
// check if the factory is already buffered
|
||||
lock();
|
||||
for(AUD_BFIterator i = m_bufferedFactories->begin();
|
||||
i != m_bufferedFactories->end(); i++)
|
||||
{
|
||||
if((*i)->factory == factory)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
AUD_IReader* reader = factory->createReader();
|
||||
|
||||
if(reader == NULL)
|
||||
return false;
|
||||
|
||||
AUD_DeviceSpecs specs = m_specs;
|
||||
specs.specs = reader->getSpecs();
|
||||
|
||||
if(m_specs.format != AUD_FORMAT_FLOAT32)
|
||||
reader = new AUD_ConverterReader(reader, m_specs);
|
||||
|
||||
ALenum format;
|
||||
|
||||
if(!getFormat(format, specs.specs))
|
||||
{
|
||||
delete reader;
|
||||
return false;
|
||||
}
|
||||
|
||||
// load into a buffer
|
||||
lock();
|
||||
alcSuspendContext(m_context);
|
||||
|
||||
AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory;
|
||||
bf->factory = factory;
|
||||
|
||||
try
|
||||
{
|
||||
alGenBuffers(1, &bf->buffer);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
AUD_THROW(AUD_ERROR_OPENAL);
|
||||
|
||||
try
|
||||
{
|
||||
sample_t* buf;
|
||||
int length = reader->getLength();
|
||||
|
||||
reader->read(length, buf);
|
||||
alBufferData(bf->buffer, format, buf,
|
||||
length * AUD_DEVICE_SAMPLE_SIZE(specs),
|
||||
specs.rate);
|
||||
if(alGetError() != AL_NO_ERROR)
|
||||
AUD_THROW(AUD_ERROR_OPENAL);
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
alDeleteBuffers(1, &bf->buffer);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
delete bf;
|
||||
delete reader;
|
||||
alcProcessContext(m_context);
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_bufferedFactories->push_back(bf);
|
||||
|
||||
alcProcessContext(m_context);
|
||||
unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
// stop all playing and paused buffered sources
|
||||
lock();
|
||||
alcSuspendContext(m_context);
|
||||
|
||||
AUD_OpenALHandle* sound;
|
||||
AUD_HandleIterator it = m_playingSounds->begin();
|
||||
while(it != m_playingSounds->end())
|
||||
{
|
||||
sound = *it;
|
||||
++it;
|
||||
|
||||
if(sound->isBuffered)
|
||||
stop(sound);
|
||||
}
|
||||
alcProcessContext(m_context);
|
||||
|
||||
while(!m_bufferedFactories->empty())
|
||||
{
|
||||
alDeleteBuffers(1,
|
||||
&(*(m_bufferedFactories->begin()))->buffer);
|
||||
delete *m_bufferedFactories->begin();
|
||||
m_bufferedFactories->erase(m_bufferedFactories->begin());
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
return true;
|
||||
}*/
|
||||
|
||||
/******************************************************************************/
|
||||
/**************************** 3D Device Code **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
AUD_Handle* AUD_OpenALDevice::play3D(AUD_IFactory* factory, bool keep)
|
||||
AUD_Vector3 AUD_OpenALDevice::getListenerLocation() const
|
||||
{
|
||||
AUD_OpenALHandle* handle = (AUD_OpenALHandle*)play(factory, keep);
|
||||
if(handle)
|
||||
alSourcei(handle->source, AL_SOURCE_RELATIVE, 0);
|
||||
return handle;
|
||||
ALfloat p[3];
|
||||
alGetListenerfv(AL_POSITION, p);
|
||||
return AUD_Vector3(p[0], p[1], p[2]);
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::updateListener(AUD_3DData &data)
|
||||
void AUD_OpenALDevice::setListenerLocation(const AUD_Vector3& location)
|
||||
{
|
||||
alListenerfv(AL_POSITION, (ALfloat*)data.position);
|
||||
alListenerfv(AL_VELOCITY, (ALfloat*)data.velocity);
|
||||
alListenerfv(AL_ORIENTATION, (ALfloat*)&(data.orientation[3]));
|
||||
|
||||
return true;
|
||||
alListenerfv(AL_POSITION, (ALfloat*)location.get());
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setSetting(AUD_3DSetting setting, float value)
|
||||
AUD_Vector3 AUD_OpenALDevice::getListenerVelocity() const
|
||||
{
|
||||
switch(setting)
|
||||
ALfloat v[3];
|
||||
alGetListenerfv(AL_VELOCITY, v);
|
||||
return AUD_Vector3(v[0], v[1], v[2]);
|
||||
}
|
||||
|
||||
void AUD_OpenALDevice::setListenerVelocity(const AUD_Vector3& velocity)
|
||||
{
|
||||
alListenerfv(AL_VELOCITY, (ALfloat*)velocity.get());
|
||||
}
|
||||
|
||||
AUD_Quaternion AUD_OpenALDevice::getListenerOrientation() const
|
||||
{
|
||||
// AUD_XXX not implemented yet
|
||||
return AUD_Quaternion(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void AUD_OpenALDevice::setListenerOrientation(const AUD_Quaternion& orientation)
|
||||
{
|
||||
ALfloat direction[6];
|
||||
direction[0] = -2 * (orientation.w() * orientation.y() +
|
||||
orientation.x() * orientation.z());
|
||||
direction[1] = 2 * (orientation.x() * orientation.w() -
|
||||
orientation.z() * orientation.y());
|
||||
direction[2] = 2 * (orientation.x() * orientation.x() +
|
||||
orientation.y() * orientation.y()) - 1;
|
||||
direction[3] = 2 * (orientation.x() * orientation.y() -
|
||||
orientation.w() * orientation.z());
|
||||
direction[4] = 1 - 2 * (orientation.x() * orientation.x() +
|
||||
orientation.z() * orientation.z());
|
||||
direction[5] = 2 * (orientation.w() * orientation.x() +
|
||||
orientation.y() * orientation.z());
|
||||
alListenerfv(AL_ORIENTATION, direction);
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getSpeedOfSound() const
|
||||
{
|
||||
return alGetFloat(AL_SPEED_OF_SOUND);
|
||||
}
|
||||
|
||||
void AUD_OpenALDevice::setSpeedOfSound(float speed)
|
||||
{
|
||||
alSpeedOfSound(speed);
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getDopplerFactor() const
|
||||
{
|
||||
return alGetFloat(AL_DOPPLER_FACTOR);
|
||||
}
|
||||
|
||||
void AUD_OpenALDevice::setDopplerFactor(float factor)
|
||||
{
|
||||
alDopplerFactor(factor);
|
||||
}
|
||||
|
||||
AUD_DistanceModel AUD_OpenALDevice::getDistanceModel() const
|
||||
{
|
||||
switch(alGetInteger(AL_DISTANCE_MODEL))
|
||||
{
|
||||
case AUD_3DS_DISTANCE_MODEL:
|
||||
if(value == AUD_DISTANCE_MODEL_NONE)
|
||||
alDistanceModel(AL_NONE);
|
||||
else if(value == AUD_DISTANCE_MODEL_INVERSE)
|
||||
alDistanceModel(AL_INVERSE_DISTANCE);
|
||||
else if(value == AUD_DISTANCE_MODEL_INVERSE_CLAMPED)
|
||||
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
|
||||
else if(value == AUD_DISTANCE_MODEL_LINEAR)
|
||||
alDistanceModel(AL_LINEAR_DISTANCE);
|
||||
else if(value == AUD_DISTANCE_MODEL_LINEAR_CLAMPED)
|
||||
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
|
||||
else if(value == AUD_DISTANCE_MODEL_EXPONENT)
|
||||
alDistanceModel(AL_EXPONENT_DISTANCE);
|
||||
else if(value == AUD_DISTANCE_MODEL_EXPONENT_CLAMPED)
|
||||
alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
case AUD_3DS_DOPPLER_FACTOR:
|
||||
alDopplerFactor(value);
|
||||
return true;
|
||||
case AUD_3DS_SPEED_OF_SOUND:
|
||||
alSpeedOfSound(value);
|
||||
return true;
|
||||
case AL_INVERSE_DISTANCE:
|
||||
return AUD_DISTANCE_MODEL_INVERSE;
|
||||
case AL_INVERSE_DISTANCE_CLAMPED:
|
||||
return AUD_DISTANCE_MODEL_INVERSE_CLAMPED;
|
||||
case AL_LINEAR_DISTANCE:
|
||||
return AUD_DISTANCE_MODEL_LINEAR;
|
||||
case AL_LINEAR_DISTANCE_CLAMPED:
|
||||
return AUD_DISTANCE_MODEL_LINEAR_CLAMPED;
|
||||
case AL_EXPONENT_DISTANCE:
|
||||
return AUD_DISTANCE_MODEL_EXPONENT;
|
||||
case AL_EXPONENT_DISTANCE_CLAMPED:
|
||||
return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED;
|
||||
default:
|
||||
return false;
|
||||
return AUD_DISTANCE_MODEL_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getSetting(AUD_3DSetting setting)
|
||||
void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model)
|
||||
{
|
||||
switch(setting)
|
||||
switch(model)
|
||||
{
|
||||
case AUD_3DS_DISTANCE_MODEL:
|
||||
switch(alGetInteger(AL_DISTANCE_MODEL))
|
||||
{
|
||||
case AL_NONE:
|
||||
return AUD_DISTANCE_MODEL_NONE;
|
||||
case AL_INVERSE_DISTANCE:
|
||||
return AUD_DISTANCE_MODEL_INVERSE;
|
||||
case AL_INVERSE_DISTANCE_CLAMPED:
|
||||
return AUD_DISTANCE_MODEL_INVERSE_CLAMPED;
|
||||
case AL_LINEAR_DISTANCE:
|
||||
return AUD_DISTANCE_MODEL_LINEAR;
|
||||
case AL_LINEAR_DISTANCE_CLAMPED:
|
||||
return AUD_DISTANCE_MODEL_LINEAR_CLAMPED;
|
||||
case AL_EXPONENT_DISTANCE:
|
||||
return AUD_DISTANCE_MODEL_EXPONENT;
|
||||
case AL_EXPONENT_DISTANCE_CLAMPED:
|
||||
return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED;
|
||||
}
|
||||
case AUD_3DS_DOPPLER_FACTOR:
|
||||
return alGetFloat(AL_DOPPLER_FACTOR);
|
||||
case AUD_3DS_SPEED_OF_SOUND:
|
||||
return alGetFloat(AL_SPEED_OF_SOUND);
|
||||
case AUD_DISTANCE_MODEL_INVERSE:
|
||||
alDistanceModel(AL_INVERSE_DISTANCE);
|
||||
break;
|
||||
case AUD_DISTANCE_MODEL_INVERSE_CLAMPED:
|
||||
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
|
||||
break;
|
||||
case AUD_DISTANCE_MODEL_LINEAR:
|
||||
alDistanceModel(AL_LINEAR_DISTANCE);
|
||||
break;
|
||||
case AUD_DISTANCE_MODEL_LINEAR_CLAMPED:
|
||||
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
|
||||
break;
|
||||
case AUD_DISTANCE_MODEL_EXPONENT:
|
||||
alDistanceModel(AL_EXPONENT_DISTANCE);
|
||||
break;
|
||||
case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED:
|
||||
alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED);
|
||||
break;
|
||||
default:
|
||||
return std::numeric_limits<float>::quiet_NaN();
|
||||
alDistanceModel(AL_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::updateSource(AUD_Handle* handle, AUD_3DData &data)
|
||||
AUD_Vector3 AUD_OpenALDevice::getSourceLocation(AUD_Handle* handle)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
AUD_Vector3 result = AUD_Vector3(0, 0, 0);
|
||||
ALfloat p[3];
|
||||
lock();
|
||||
|
||||
if(isValid(handle))
|
||||
{
|
||||
int source = ((AUD_OpenALHandle*)handle)->source;
|
||||
alSourcefv(source, AL_POSITION, (ALfloat*)data.position);
|
||||
alSourcefv(source, AL_VELOCITY, (ALfloat*)data.velocity);
|
||||
alSourcefv(source, AL_DIRECTION, (ALfloat*)&(data.orientation[3]));
|
||||
result = true;
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setSourceSetting(AUD_Handle* handle,
|
||||
AUD_3DSourceSetting setting,
|
||||
float value)
|
||||
{
|
||||
lock();
|
||||
|
||||
bool result = false;
|
||||
|
||||
if(isValid(handle))
|
||||
{
|
||||
int source = ((AUD_OpenALHandle*)handle)->source;
|
||||
|
||||
switch(setting)
|
||||
{
|
||||
case AUD_3DSS_CONE_INNER_ANGLE:
|
||||
alSourcef(source, AL_CONE_INNER_ANGLE, value);
|
||||
result = true;
|
||||
break;
|
||||
case AUD_3DSS_CONE_OUTER_ANGLE:
|
||||
alSourcef(source, AL_CONE_OUTER_ANGLE, value);
|
||||
result = true;
|
||||
break;
|
||||
case AUD_3DSS_CONE_OUTER_GAIN:
|
||||
alSourcef(source, AL_CONE_OUTER_GAIN, value);
|
||||
result = true;
|
||||
break;
|
||||
case AUD_3DSS_IS_RELATIVE:
|
||||
alSourcei(source, AL_SOURCE_RELATIVE, value > 0.0f);
|
||||
result = true;
|
||||
break;
|
||||
case AUD_3DSS_MAX_DISTANCE:
|
||||
alSourcef(source, AL_MAX_DISTANCE, value);
|
||||
result = true;
|
||||
break;
|
||||
case AUD_3DSS_MAX_GAIN:
|
||||
alSourcef(source, AL_MAX_GAIN, value);
|
||||
result = true;
|
||||
break;
|
||||
case AUD_3DSS_MIN_GAIN:
|
||||
alSourcef(source, AL_MIN_GAIN, value);
|
||||
result = true;
|
||||
break;
|
||||
case AUD_3DSS_REFERENCE_DISTANCE:
|
||||
alSourcef(source, AL_REFERENCE_DISTANCE, value);
|
||||
result = true;
|
||||
break;
|
||||
case AUD_3DSS_ROLLOFF_FACTOR:
|
||||
alSourcef(source, AL_ROLLOFF_FACTOR, value);
|
||||
result = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION, p);
|
||||
result = AUD_Vector3(p[0], p[1], p[2]);
|
||||
}
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getSourceSetting(AUD_Handle* handle,
|
||||
AUD_3DSourceSetting setting)
|
||||
bool AUD_OpenALDevice::setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
|
||||
if(result)
|
||||
alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION,
|
||||
(ALfloat*)location.get());
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
AUD_Vector3 AUD_OpenALDevice::getSourceVelocity(AUD_Handle* handle)
|
||||
{
|
||||
AUD_Vector3 result = AUD_Vector3(0, 0, 0);
|
||||
ALfloat v[3];
|
||||
lock();
|
||||
|
||||
if(isValid(handle))
|
||||
{
|
||||
alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY, v);
|
||||
result = AUD_Vector3(v[0], v[1], v[2]);
|
||||
}
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
|
||||
if(result)
|
||||
alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY,
|
||||
(ALfloat*)velocity.get());
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
AUD_Quaternion AUD_OpenALDevice::getSourceOrientation(AUD_Handle* handle)
|
||||
{
|
||||
// AUD_XXX not implemented yet
|
||||
return AUD_Quaternion(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
|
||||
if(result)
|
||||
{
|
||||
ALfloat direction[3];
|
||||
direction[0] = -2 * (orientation.w() * orientation.y() +
|
||||
orientation.x() * orientation.z());
|
||||
direction[1] = 2 * (orientation.x() * orientation.w() -
|
||||
orientation.z() * orientation.y());
|
||||
direction[2] = 2 * (orientation.x() * orientation.x() +
|
||||
orientation.y() * orientation.y()) - 1;
|
||||
alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_DIRECTION,
|
||||
direction);
|
||||
}
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::isRelative(AUD_Handle* handle)
|
||||
{
|
||||
int result = std::numeric_limits<float>::quiet_NaN();;
|
||||
|
||||
lock();
|
||||
|
||||
if(isValid(handle))
|
||||
alGetSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE,
|
||||
&result);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setRelative(AUD_Handle* handle, bool relative)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
|
||||
if(result)
|
||||
alSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE,
|
||||
relative);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getVolumeMaximum(AUD_Handle* handle)
|
||||
{
|
||||
float result = std::numeric_limits<float>::quiet_NaN();;
|
||||
|
||||
lock();
|
||||
|
||||
if(isValid(handle))
|
||||
{
|
||||
int source = ((AUD_OpenALHandle*)handle)->source;
|
||||
|
||||
switch(setting)
|
||||
{
|
||||
case AUD_3DSS_CONE_INNER_ANGLE:
|
||||
alGetSourcef(source, AL_CONE_INNER_ANGLE, &result);
|
||||
break;
|
||||
case AUD_3DSS_CONE_OUTER_ANGLE:
|
||||
alGetSourcef(source, AL_CONE_OUTER_ANGLE, &result);
|
||||
break;
|
||||
case AUD_3DSS_CONE_OUTER_GAIN:
|
||||
alGetSourcef(source, AL_CONE_OUTER_GAIN, &result);
|
||||
break;
|
||||
case AUD_3DSS_IS_RELATIVE:
|
||||
{
|
||||
ALint i;
|
||||
alGetSourcei(source, AL_SOURCE_RELATIVE, &i);
|
||||
result = i ? 1.0f : 0.0f;
|
||||
break;
|
||||
}
|
||||
case AUD_3DSS_MAX_DISTANCE:
|
||||
alGetSourcef(source, AL_MAX_DISTANCE, &result);
|
||||
break;
|
||||
case AUD_3DSS_MAX_GAIN:
|
||||
alGetSourcef(source, AL_MAX_GAIN, &result);
|
||||
break;
|
||||
case AUD_3DSS_MIN_GAIN:
|
||||
alGetSourcef(source, AL_MIN_GAIN, &result);
|
||||
break;
|
||||
case AUD_3DSS_REFERENCE_DISTANCE:
|
||||
alGetSourcef(source, AL_REFERENCE_DISTANCE, &result);
|
||||
break;
|
||||
case AUD_3DSS_ROLLOFF_FACTOR:
|
||||
alGetSourcef(source, AL_ROLLOFF_FACTOR, &result);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN,
|
||||
&result);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setVolumeMaximum(AUD_Handle* handle, float volume)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
|
||||
if(result)
|
||||
|
||||
alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN,
|
||||
volume);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getVolumeMinimum(AUD_Handle* handle)
|
||||
{
|
||||
float result = std::numeric_limits<float>::quiet_NaN();;
|
||||
|
||||
lock();
|
||||
|
||||
if(isValid(handle))
|
||||
alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN,
|
||||
&result);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setVolumeMinimum(AUD_Handle* handle, float volume)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
|
||||
if(result)
|
||||
alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN,
|
||||
volume);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getDistanceMaximum(AUD_Handle* handle)
|
||||
{
|
||||
float result = std::numeric_limits<float>::quiet_NaN();;
|
||||
|
||||
lock();
|
||||
|
||||
if(isValid(handle))
|
||||
alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE,
|
||||
&result);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setDistanceMaximum(AUD_Handle* handle, float distance)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
|
||||
if(result)
|
||||
alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE,
|
||||
distance);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getDistanceReference(AUD_Handle* handle)
|
||||
{
|
||||
float result = std::numeric_limits<float>::quiet_NaN();;
|
||||
|
||||
lock();
|
||||
|
||||
if(isValid(handle))
|
||||
alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE,
|
||||
&result);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setDistanceReference(AUD_Handle* handle, float distance)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
|
||||
if(result)
|
||||
alSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE,
|
||||
distance);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getAttenuation(AUD_Handle* handle)
|
||||
{
|
||||
float result = std::numeric_limits<float>::quiet_NaN();;
|
||||
|
||||
lock();
|
||||
|
||||
if(isValid(handle))
|
||||
alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR,
|
||||
&result);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setAttenuation(AUD_Handle* handle, float factor)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
|
||||
if(result)
|
||||
alSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR,
|
||||
factor);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getConeAngleOuter(AUD_Handle* handle)
|
||||
{
|
||||
float result = std::numeric_limits<float>::quiet_NaN();;
|
||||
|
||||
lock();
|
||||
|
||||
if(isValid(handle))
|
||||
alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE,
|
||||
&result);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setConeAngleOuter(AUD_Handle* handle, float angle)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
|
||||
if(result)
|
||||
alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE,
|
||||
angle);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getConeAngleInner(AUD_Handle* handle)
|
||||
{
|
||||
float result = std::numeric_limits<float>::quiet_NaN();;
|
||||
|
||||
lock();
|
||||
|
||||
if(isValid(handle))
|
||||
alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE,
|
||||
&result);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setConeAngleInner(AUD_Handle* handle, float angle)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
|
||||
if(result)
|
||||
alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE,
|
||||
angle);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
float AUD_OpenALDevice::getConeVolumeOuter(AUD_Handle* handle)
|
||||
{
|
||||
float result = std::numeric_limits<float>::quiet_NaN();;
|
||||
|
||||
lock();
|
||||
|
||||
if(isValid(handle))
|
||||
alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN,
|
||||
&result);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::setConeVolumeOuter(AUD_Handle* handle, float volume)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
|
||||
if(result)
|
||||
alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN,
|
||||
volume);
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "AUD_I3DDevice.h"
|
||||
struct AUD_OpenALHandle;
|
||||
struct AUD_OpenALBufferedFactory;
|
||||
class AUD_ConverterFactory;
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
@@ -63,11 +62,6 @@ private:
|
||||
*/
|
||||
bool m_useMC;
|
||||
|
||||
/**
|
||||
* The converter factory for readers with wrong input format.
|
||||
*/
|
||||
AUD_ConverterFactory* m_converter;
|
||||
|
||||
/**
|
||||
* The list of sounds that are currently playing.
|
||||
*/
|
||||
@@ -123,6 +117,10 @@ private:
|
||||
*/
|
||||
bool getFormat(ALenum &format, AUD_Specs specs);
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_OpenALDevice(const AUD_OpenALDevice&);
|
||||
AUD_OpenALDevice& operator=(const AUD_OpenALDevice&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Opens the OpenAL audio device for playback.
|
||||
@@ -142,31 +140,64 @@ public:
|
||||
|
||||
virtual ~AUD_OpenALDevice();
|
||||
|
||||
virtual AUD_DeviceSpecs getSpecs();
|
||||
virtual AUD_DeviceSpecs getSpecs() const;
|
||||
virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false);
|
||||
virtual bool pause(AUD_Handle* handle);
|
||||
virtual bool resume(AUD_Handle* handle);
|
||||
virtual bool stop(AUD_Handle* handle);
|
||||
virtual bool getKeep(AUD_Handle* handle);
|
||||
virtual bool setKeep(AUD_Handle* handle, bool keep);
|
||||
virtual bool sendMessage(AUD_Handle* handle, AUD_Message &message);
|
||||
virtual bool seek(AUD_Handle* handle, float position);
|
||||
virtual float getPosition(AUD_Handle* handle);
|
||||
virtual AUD_Status getStatus(AUD_Handle* handle);
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
virtual bool checkCapability(int capability);
|
||||
virtual bool setCapability(int capability, void *value);
|
||||
virtual bool getCapability(int capability, void *value);
|
||||
virtual float getVolume() const;
|
||||
virtual void setVolume(float volume);
|
||||
virtual float getVolume(AUD_Handle* handle);
|
||||
virtual bool setVolume(AUD_Handle* handle, float volume);
|
||||
virtual float getPitch(AUD_Handle* handle);
|
||||
virtual bool setPitch(AUD_Handle* handle, float pitch);
|
||||
virtual int getLoopCount(AUD_Handle* handle);
|
||||
virtual bool setLoopCount(AUD_Handle* handle, int count);
|
||||
virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = NULL, void* data = NULL);
|
||||
|
||||
virtual AUD_Handle* play3D(AUD_IFactory* factory, bool keep = false);
|
||||
virtual bool updateListener(AUD_3DData &data);
|
||||
virtual bool setSetting(AUD_3DSetting setting, float value);
|
||||
virtual float getSetting(AUD_3DSetting setting);
|
||||
virtual bool updateSource(AUD_Handle* handle, AUD_3DData &data);
|
||||
virtual bool setSourceSetting(AUD_Handle* handle,
|
||||
AUD_3DSourceSetting setting, float value);
|
||||
virtual float getSourceSetting(AUD_Handle* handle,
|
||||
AUD_3DSourceSetting setting);
|
||||
virtual AUD_Vector3 getListenerLocation() const;
|
||||
virtual void setListenerLocation(const AUD_Vector3& location);
|
||||
virtual AUD_Vector3 getListenerVelocity() const;
|
||||
virtual void setListenerVelocity(const AUD_Vector3& velocity);
|
||||
virtual AUD_Quaternion getListenerOrientation() const;
|
||||
virtual void setListenerOrientation(const AUD_Quaternion& orientation);
|
||||
virtual float getSpeedOfSound() const;
|
||||
virtual void setSpeedOfSound(float speed);
|
||||
virtual float getDopplerFactor() const;
|
||||
virtual void setDopplerFactor(float factor);
|
||||
virtual AUD_DistanceModel getDistanceModel() const;
|
||||
virtual void setDistanceModel(AUD_DistanceModel model);
|
||||
virtual AUD_Vector3 getSourceLocation(AUD_Handle* handle);
|
||||
virtual bool setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location);
|
||||
virtual AUD_Vector3 getSourceVelocity(AUD_Handle* handle);
|
||||
virtual bool setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity);
|
||||
virtual AUD_Quaternion getSourceOrientation(AUD_Handle* handle);
|
||||
virtual bool setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation);
|
||||
virtual bool isRelative(AUD_Handle* handle);
|
||||
virtual bool setRelative(AUD_Handle* handle, bool relative);
|
||||
virtual float getVolumeMaximum(AUD_Handle* handle);
|
||||
virtual bool setVolumeMaximum(AUD_Handle* handle, float volume);
|
||||
virtual float getVolumeMinimum(AUD_Handle* handle);
|
||||
virtual bool setVolumeMinimum(AUD_Handle* handle, float volume);
|
||||
virtual float getDistanceMaximum(AUD_Handle* handle);
|
||||
virtual bool setDistanceMaximum(AUD_Handle* handle, float distance);
|
||||
virtual float getDistanceReference(AUD_Handle* handle);
|
||||
virtual bool setDistanceReference(AUD_Handle* handle, float distance);
|
||||
virtual float getAttenuation(AUD_Handle* handle);
|
||||
virtual bool setAttenuation(AUD_Handle* handle, float factor);
|
||||
virtual float getConeAngleOuter(AUD_Handle* handle);
|
||||
virtual bool setConeAngleOuter(AUD_Handle* handle, float angle);
|
||||
virtual float getConeAngleInner(AUD_Handle* handle);
|
||||
virtual bool setConeAngleInner(AUD_Handle* handle, float angle);
|
||||
virtual float getConeVolumeOuter(AUD_Handle* handle);
|
||||
virtual bool setConeVolumeOuter(AUD_Handle* handle, float volume);
|
||||
};
|
||||
|
||||
#endif //AUD_OPENALDEVICE
|
||||
|
||||
2976
intern/audaspace/Python/AUD_PyAPI.cpp
Normal file
2976
intern/audaspace/Python/AUD_PyAPI.cpp
Normal file
@@ -0,0 +1,2976 @@
|
||||
/*
|
||||
* $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_PyAPI.h"
|
||||
#include "structmember.h"
|
||||
|
||||
#include "AUD_I3DDevice.h"
|
||||
#include "AUD_NULLDevice.h"
|
||||
#include "AUD_DelayFactory.h"
|
||||
#include "AUD_DoubleFactory.h"
|
||||
#include "AUD_FaderFactory.h"
|
||||
#include "AUD_HighpassFactory.h"
|
||||
#include "AUD_LimiterFactory.h"
|
||||
#include "AUD_LoopFactory.h"
|
||||
#include "AUD_LowpassFactory.h"
|
||||
#include "AUD_PingPongFactory.h"
|
||||
#include "AUD_PitchFactory.h"
|
||||
#include "AUD_ReverseFactory.h"
|
||||
#include "AUD_SinusFactory.h"
|
||||
#include "AUD_FileFactory.h"
|
||||
#include "AUD_SquareFactory.h"
|
||||
#include "AUD_StreamBufferFactory.h"
|
||||
#include "AUD_SuperposeFactory.h"
|
||||
#include "AUD_VolumeFactory.h"
|
||||
#include "AUD_IIRFilterFactory.h"
|
||||
|
||||
#ifdef WITH_SDL
|
||||
#include "AUD_SDLDevice.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_OPENAL
|
||||
#include "AUD_OpenALDevice.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_JACK
|
||||
#include "AUD_JackDevice.h"
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
|
||||
// ====================================================================
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AUD_DEVICE_NULL = 0,
|
||||
AUD_DEVICE_OPENAL,
|
||||
AUD_DEVICE_SDL,
|
||||
AUD_DEVICE_JACK,
|
||||
AUD_DEVICE_READ,
|
||||
} AUD_DeviceTypes;
|
||||
|
||||
// ====================================================================
|
||||
|
||||
#define PY_MODULE_ADD_CONSTANT(module, name) PyModule_AddIntConstant(module, #name, name)
|
||||
|
||||
// ====================================================================
|
||||
|
||||
static PyObject* AUDError;
|
||||
|
||||
static const char* device_not_3d_error = "Device is not a 3D device!";
|
||||
|
||||
// ====================================================================
|
||||
|
||||
static void
|
||||
Factory_dealloc(Factory* self)
|
||||
{
|
||||
if(self->factory)
|
||||
delete self->factory;
|
||||
Py_XDECREF(self->child_list);
|
||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
Factory_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
Factory *self;
|
||||
|
||||
self = (Factory*)type->tp_alloc(type, 0);
|
||||
if(self != NULL)
|
||||
{
|
||||
static const char *kwlist[] = {"filename", NULL};
|
||||
const char* filename = NULL;
|
||||
|
||||
if(!PyArg_ParseTupleAndKeywords(args, kwds, "s:Factory", const_cast<char**>(kwlist), &filename))
|
||||
{
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
self->factory = new AUD_FileFactory(filename);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(self);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_sine_doc,
|
||||
"sine(frequency, rate=44100)\n\n"
|
||||
"Creates a sine factory which plays a sine wave.\n\n"
|
||||
":arg frequency: The frequency of the sine wave in Hz.\n"
|
||||
":type frequency: float\n"
|
||||
":arg rate: The sampling rate in Hz. It's recommended to set this "
|
||||
"value to the playback device's samling rate to avoid resamping.\n"
|
||||
":type rate: int\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`");
|
||||
|
||||
static PyObject *
|
||||
Factory_sine(PyTypeObject* type, PyObject* args)
|
||||
{
|
||||
float frequency;
|
||||
int rate = 44100;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "f|i:sine", &frequency, &rate))
|
||||
return NULL;
|
||||
|
||||
Factory *self;
|
||||
|
||||
self = (Factory*)type->tp_alloc(type, 0);
|
||||
if(self != NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
self->factory = new AUD_SinusFactory(frequency, (AUD_SampleRate)rate);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(self);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_file_doc,
|
||||
"file(filename)\n\n"
|
||||
"Creates a factory object of a sound file.\n\n"
|
||||
":arg filename: Path of the file.\n"
|
||||
":type filename: string\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`\n\n"
|
||||
".. warning:: If the file doesn't exist or can't be read you will "
|
||||
"not get an exception immediately, but when you try to start "
|
||||
"playback of that factory.");
|
||||
|
||||
static PyObject *
|
||||
Factory_file(PyTypeObject* type, PyObject* args)
|
||||
{
|
||||
const char* filename = NULL;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "s:file", &filename))
|
||||
return NULL;
|
||||
|
||||
Factory *self;
|
||||
|
||||
self = (Factory*)type->tp_alloc(type, 0);
|
||||
if(self != NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
self->factory = new AUD_FileFactory(filename);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(self);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_lowpass_doc,
|
||||
"lowpass(frequency, Q=0.5)\n\n"
|
||||
"Creates a second order lowpass filter based on the transfer "
|
||||
"function H(s) = 1 / (s^2 + s/Q + 1)\n\n"
|
||||
":arg frequency: The cut off trequency of the lowpass.\n"
|
||||
":type frequency: float\n"
|
||||
":arg Q: Q factor of the lowpass.\n"
|
||||
":type Q: float\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`");
|
||||
|
||||
static PyObject *
|
||||
Factory_lowpass(Factory* self, PyObject* args)
|
||||
{
|
||||
float frequency;
|
||||
float Q = 0.5;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "f|f:lowpass", &frequency, &Q))
|
||||
return NULL;
|
||||
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
Py_INCREF(self);
|
||||
parent->child_list = (PyObject*)self;
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_LowpassFactory(self->factory, frequency, Q);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_delay_doc,
|
||||
"delay(time)\n\n"
|
||||
"Delays by playing adding silence in front of the other factory's "
|
||||
"data.\n\n"
|
||||
":arg time: How many seconds of silence should be added before "
|
||||
"the factory.\n"
|
||||
":type time: float\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`");
|
||||
|
||||
static PyObject *
|
||||
Factory_delay(Factory* self, PyObject* args)
|
||||
{
|
||||
float delay;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "f:delay", &delay))
|
||||
return NULL;
|
||||
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
Py_INCREF(self);
|
||||
parent->child_list = (PyObject*)self;
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_DelayFactory(self->factory, delay);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_join_doc,
|
||||
"join(factory)\n\n"
|
||||
"Plays two factories in sequence.\n\n"
|
||||
":arg factory: The factory to play second.\n"
|
||||
":type factory: :class:`Factory`\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`\n\n"
|
||||
".. note:: The two factories have to have the same specifications "
|
||||
"(channels and samplerate).");
|
||||
|
||||
static PyObject *
|
||||
Factory_join(Factory* self, PyObject* object)
|
||||
{
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
|
||||
if(!PyObject_TypeCheck(object, type))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Object has to be of type Factory!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Factory *parent;
|
||||
Factory *child = (Factory*)object;
|
||||
|
||||
parent = (Factory*)type->tp_alloc(type, 0);
|
||||
if(parent != NULL)
|
||||
{
|
||||
parent->child_list = Py_BuildValue("(OO)", self, object);
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_DoubleFactory(self->factory, child->factory);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_highpass_doc,
|
||||
"highpass(frequency, Q=0.5)\n\n"
|
||||
"Creates a second order highpass filter based on the transfer "
|
||||
"function H(s) = s^2 / (s^2 + s/Q + 1)\n\n"
|
||||
":arg frequency: The cut off trequency of the highpass.\n"
|
||||
":type frequency: float\n"
|
||||
":arg Q: Q factor of the lowpass.\n"
|
||||
":type Q: float\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`");
|
||||
|
||||
static PyObject *
|
||||
Factory_highpass(Factory* self, PyObject* args)
|
||||
{
|
||||
float frequency;
|
||||
float Q = 0.5;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "f|f:highpass", &frequency, &Q))
|
||||
return NULL;
|
||||
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
Py_INCREF(self);
|
||||
parent->child_list = (PyObject*)self;
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_HighpassFactory(self->factory, frequency, Q);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_limit_doc,
|
||||
"limit(start, end)\n\n"
|
||||
"Limits a factory within a specific start and end time.\n\n"
|
||||
":arg start: Start time in seconds.\n"
|
||||
":type start: float\n"
|
||||
":arg end: End time in seconds.\n"
|
||||
":type end: float\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`");
|
||||
|
||||
static PyObject *
|
||||
Factory_limit(Factory* self, PyObject* args)
|
||||
{
|
||||
float start, end;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "ff:limit", &start, &end))
|
||||
return NULL;
|
||||
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
Py_INCREF(self);
|
||||
parent->child_list = (PyObject*)self;
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_LimiterFactory(self->factory, start, end);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_pitch_doc,
|
||||
"pitch(factor)\n\n"
|
||||
"Changes the pitch of a factory with a specific factor.\n\n"
|
||||
":arg factor: The factor to change the pitch with.\n"
|
||||
":type factor: float\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`\n\n"
|
||||
".. note:: This is done by changing the sample rate of the "
|
||||
"underlying factory, which has to be an integer, so the factor "
|
||||
"value rounded and the factor may not be 100 % accurate.\n\n"
|
||||
".. note:: This is a filter function, you might consider using "
|
||||
":attr:`Handle.pitch` instead.");
|
||||
|
||||
static PyObject *
|
||||
Factory_pitch(Factory* self, PyObject* args)
|
||||
{
|
||||
float factor;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "f:pitch", &factor))
|
||||
return NULL;
|
||||
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
Py_INCREF(self);
|
||||
parent->child_list = (PyObject*)self;
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_PitchFactory(self->factory, factor);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_volume_doc,
|
||||
"volume(volume)\n\n"
|
||||
"Changes the volume of a factory.\n\n"
|
||||
":arg volume: The new volume..\n"
|
||||
":type volume: float\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`\n\n"
|
||||
".. note:: Should be in the range [0, 1] to avoid clipping.\n\n"
|
||||
".. note:: This is a filter function, you might consider using "
|
||||
":attr:`Handle.volume` instead.");
|
||||
|
||||
static PyObject *
|
||||
Factory_volume(Factory* self, PyObject* args)
|
||||
{
|
||||
float volume;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "f:volume", &volume))
|
||||
return NULL;
|
||||
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
Py_INCREF(self);
|
||||
parent->child_list = (PyObject*)self;
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_VolumeFactory(self->factory, volume);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_fadein_doc,
|
||||
"fadein(start, length)\n\n"
|
||||
"Fades a factory in by raising the volume linearly in the given "
|
||||
"time interval.\n\n"
|
||||
":arg start: Time in seconds when the fading should start.\n"
|
||||
":type start: float\n"
|
||||
":arg length: Time in seconds how long the fading should last.\n"
|
||||
":type length: float\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`\n\n"
|
||||
".. note:: Before the fade starts it plays silence.");
|
||||
|
||||
static PyObject *
|
||||
Factory_fadein(Factory* self, PyObject* args)
|
||||
{
|
||||
float start, length;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "ff:fadein", &start, &length))
|
||||
return NULL;
|
||||
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
Py_INCREF(self);
|
||||
parent->child_list = (PyObject*)self;
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_IN, start, length);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_fadeout_doc,
|
||||
"fadeout(start, length)\n\n"
|
||||
"Fades a factory in by lowering the volume linearly in the given "
|
||||
"time interval.\n\n"
|
||||
":arg start: Time in seconds when the fading should start.\n"
|
||||
":type start: float\n"
|
||||
":arg length: Time in seconds how long the fading should last.\n"
|
||||
":type length: float\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`\n\n"
|
||||
".. note:: After the fade this factory plays silence, so that "
|
||||
"the length of the factory is not altered.");
|
||||
|
||||
static PyObject *
|
||||
Factory_fadeout(Factory* self, PyObject* args)
|
||||
{
|
||||
float start, length;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "ff:fadeout", &start, &length))
|
||||
return NULL;
|
||||
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
Py_INCREF(self);
|
||||
parent->child_list = (PyObject*)self;
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_OUT, start, length);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_loop_doc,
|
||||
"loop(count)\n\n"
|
||||
"Loops a factory.\n\n"
|
||||
":arg count: How often the factory should be looped. "
|
||||
"Negative values mean endlessly.\n"
|
||||
":type count: integer\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`\n\n"
|
||||
".. note:: This is a filter function, you might consider using "
|
||||
":attr:`Handle.loop_count` instead.");
|
||||
|
||||
static PyObject *
|
||||
Factory_loop(Factory* self, PyObject* args)
|
||||
{
|
||||
int loop;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "i:loop", &loop))
|
||||
return NULL;
|
||||
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
Py_INCREF(self);
|
||||
parent->child_list = (PyObject*)self;
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_LoopFactory(self->factory, loop);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_mix_doc,
|
||||
"mix(factory)\n\n"
|
||||
"Mixes two factories.\n\n"
|
||||
":arg factory: The factory to mix over the other.\n"
|
||||
":type factory: :class:`Factory`\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`\n\n"
|
||||
".. note:: The two factories have to have the same specifications "
|
||||
"(channels and samplerate).");
|
||||
|
||||
static PyObject *
|
||||
Factory_mix(Factory* self, PyObject* object)
|
||||
{
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
|
||||
if(!PyObject_TypeCheck(object, type))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
Factory *child = (Factory*)object;
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
parent->child_list = Py_BuildValue("(OO)", self, object);
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_SuperposeFactory(self->factory, child->factory);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_pingpong_doc,
|
||||
"pingpong()\n\n"
|
||||
"Plays a factory forward and then backward.\n"
|
||||
"This is like joining a factory with its reverse.\n\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`");
|
||||
|
||||
static PyObject *
|
||||
Factory_pingpong(Factory* self)
|
||||
{
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
Py_INCREF(self);
|
||||
parent->child_list = (PyObject*)self;
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_PingPongFactory(self->factory);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_reverse_doc,
|
||||
"reverse()\n\n"
|
||||
"Plays a factory reversed.\n\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`\n\n"
|
||||
".. note:: The factory has to have a finite length and has to be "
|
||||
"seekable. It's recommended to use this only with factories with "
|
||||
"fast and accurate seeking, which is not true for encoded audio "
|
||||
"files, such ones should be buffered using :meth:`buffer` before "
|
||||
"being played reversed.\n\n"
|
||||
".. warning:: If seeking is not accurate in the underlying factory "
|
||||
"you'll likely hear skips/jumps/cracks.");
|
||||
|
||||
static PyObject *
|
||||
Factory_reverse(Factory* self)
|
||||
{
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
Py_INCREF(self);
|
||||
parent->child_list = (PyObject*)self;
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_ReverseFactory(self->factory);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_buffer_doc,
|
||||
"buffer()\n\n"
|
||||
"Buffers a factory into RAM.\n"
|
||||
"This saves CPU usage needed for decoding and file access if the "
|
||||
"underlying factory reads from a file on the harddisk, but it "
|
||||
"consumes a lot of memory.\n\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`\n\n"
|
||||
".. note:: Only known-length factories can be buffered.\n\n"
|
||||
".. warning:: Raw PCM data needs a lot of space, only buffer "
|
||||
"short factories.");
|
||||
|
||||
static PyObject *
|
||||
Factory_buffer(Factory* self)
|
||||
{
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_StreamBufferFactory(self->factory);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_square_doc,
|
||||
"square(threshold = 0)\n\n"
|
||||
"Makes a square wave out of an audio wave by setting all samples "
|
||||
"with a amplitude >= threshold to 1, all <= -threshold to -1 and "
|
||||
"all between to 0.\n\n"
|
||||
":arg threshold: Threshold value over which an amplitude counts "
|
||||
"non-zero.\n"
|
||||
":type threshold: float\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`");
|
||||
|
||||
static PyObject *
|
||||
Factory_square(Factory* self, PyObject* args)
|
||||
{
|
||||
float threshold = 0;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "|f:square", &threshold))
|
||||
return NULL;
|
||||
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
Py_INCREF(self);
|
||||
parent->child_list = (PyObject*)self;
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_SquareFactory(self->factory, threshold);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_filter_doc,
|
||||
"filter(b, a = (1))\n\n"
|
||||
"Filters a factory with the supplied IIR filter coefficients.\n"
|
||||
"Without the second parameter you'll get a FIR filter.\n"
|
||||
"If the first value of the a sequence is 0 it will be set to 1 "
|
||||
"automatically.\n"
|
||||
"If the first value of the a sequence is neither 0 nor 1, all "
|
||||
"filter coefficients will be scaled by this value so that it is 1 "
|
||||
"in the end, you don't have to scale yourself.\n\n"
|
||||
":arg b: The nominator filter coefficients.\n"
|
||||
":type b: sequence of float\n"
|
||||
":arg a: The denominator filter coefficients.\n"
|
||||
":type a: sequence of float\n"
|
||||
":return: The created :class:`Factory` object.\n"
|
||||
":rtype: :class:`Factory`");
|
||||
|
||||
static PyObject *
|
||||
Factory_filter(Factory* self, PyObject* args)
|
||||
{
|
||||
PyObject* py_b;
|
||||
PyObject* py_a = NULL;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "O|O:filter", &py_b, &py_a))
|
||||
return NULL;
|
||||
|
||||
if(!PySequence_Check(py_b) || (py_a != NULL && !PySequence_Check(py_a)))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!PySequence_Length(py_b) || (py_a != NULL && !PySequence_Length(py_a)))
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::vector<float> a, b;
|
||||
PyObject* py_value;
|
||||
float value;
|
||||
int result;
|
||||
|
||||
for(int i = 0; i < PySequence_Length(py_b); i++)
|
||||
{
|
||||
py_value = PySequence_GetItem(py_b, i);
|
||||
result = PyArg_Parse(py_value, "f:filter", &value);
|
||||
Py_DECREF(py_value);
|
||||
|
||||
if(!result)
|
||||
return NULL;
|
||||
|
||||
b.push_back(value);
|
||||
}
|
||||
|
||||
if(py_a)
|
||||
{
|
||||
for(int i = 0; i < PySequence_Length(py_a); i++)
|
||||
{
|
||||
py_value = PySequence_GetItem(py_a, i);
|
||||
result = PyArg_Parse(py_value, "f:filter", &value);
|
||||
Py_DECREF(py_value);
|
||||
|
||||
if(!result)
|
||||
return NULL;
|
||||
|
||||
a.push_back(value);
|
||||
}
|
||||
|
||||
if(a[0] == 0)
|
||||
a[0] = 1;
|
||||
}
|
||||
else
|
||||
a.push_back(1);
|
||||
|
||||
PyTypeObject* type = ((PyObject*)self)->ob_type;
|
||||
Factory *parent = (Factory*)type->tp_alloc(type, 0);
|
||||
|
||||
if(parent != NULL)
|
||||
{
|
||||
Py_INCREF(self);
|
||||
parent->child_list = (PyObject*)self;
|
||||
|
||||
try
|
||||
{
|
||||
parent->factory = new AUD_IIRFilterFactory(self->factory, b, a);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(parent);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)parent;
|
||||
}
|
||||
|
||||
static PyMethodDef Factory_methods[] = {
|
||||
{"sine", (PyCFunction)Factory_sine, METH_VARARGS | METH_CLASS,
|
||||
M_aud_Factory_sine_doc
|
||||
},
|
||||
{"file", (PyCFunction)Factory_file, METH_VARARGS | METH_CLASS,
|
||||
M_aud_Factory_file_doc
|
||||
},
|
||||
{"lowpass", (PyCFunction)Factory_lowpass, METH_VARARGS,
|
||||
M_aud_Factory_lowpass_doc
|
||||
},
|
||||
{"delay", (PyCFunction)Factory_delay, METH_VARARGS,
|
||||
M_aud_Factory_delay_doc
|
||||
},
|
||||
{"join", (PyCFunction)Factory_join, METH_O,
|
||||
M_aud_Factory_join_doc
|
||||
},
|
||||
{"highpass", (PyCFunction)Factory_highpass, METH_VARARGS,
|
||||
M_aud_Factory_highpass_doc
|
||||
},
|
||||
{"limit", (PyCFunction)Factory_limit, METH_VARARGS,
|
||||
M_aud_Factory_limit_doc
|
||||
},
|
||||
{"pitch", (PyCFunction)Factory_pitch, METH_VARARGS,
|
||||
M_aud_Factory_pitch_doc
|
||||
},
|
||||
{"volume", (PyCFunction)Factory_volume, METH_VARARGS,
|
||||
M_aud_Factory_volume_doc
|
||||
},
|
||||
{"fadein", (PyCFunction)Factory_fadein, METH_VARARGS,
|
||||
M_aud_Factory_fadein_doc
|
||||
},
|
||||
{"fadeout", (PyCFunction)Factory_fadeout, METH_VARARGS,
|
||||
M_aud_Factory_fadeout_doc
|
||||
},
|
||||
{"loop", (PyCFunction)Factory_loop, METH_VARARGS,
|
||||
M_aud_Factory_loop_doc
|
||||
},
|
||||
{"mix", (PyCFunction)Factory_mix, METH_O,
|
||||
M_aud_Factory_mix_doc
|
||||
},
|
||||
{"pingpong", (PyCFunction)Factory_pingpong, METH_NOARGS,
|
||||
M_aud_Factory_pingpong_doc
|
||||
},
|
||||
{"reverse", (PyCFunction)Factory_reverse, METH_NOARGS,
|
||||
M_aud_Factory_reverse_doc
|
||||
},
|
||||
{"buffer", (PyCFunction)Factory_buffer, METH_NOARGS,
|
||||
M_aud_Factory_buffer_doc
|
||||
},
|
||||
{"square", (PyCFunction)Factory_square, METH_VARARGS,
|
||||
M_aud_Factory_square_doc
|
||||
},
|
||||
{"filter", (PyCFunction)Factory_filter, METH_VARARGS,
|
||||
M_aud_Factory_filter_doc
|
||||
},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
PyDoc_STRVAR(M_aud_Factory_doc,
|
||||
"Factory objects are immutable and represent a sound that can be "
|
||||
"played simultaneously multiple times. They are called factories "
|
||||
"because they create reader objects internally that are used for "
|
||||
"playback.");
|
||||
|
||||
static PyTypeObject FactoryType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"aud.Factory", /* tp_name */
|
||||
sizeof(Factory), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)Factory_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_reserved */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
M_aud_Factory_doc, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
Factory_methods, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
Factory_new, /* tp_new */
|
||||
};
|
||||
|
||||
// ========== Handle ==================================================
|
||||
|
||||
static void
|
||||
Handle_dealloc(Handle* self)
|
||||
{
|
||||
Py_XDECREF(self->device);
|
||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_pause_doc,
|
||||
"pause()\n\n"
|
||||
"Pauses playback.\n\n"
|
||||
":return: Whether the action succeeded.\n"
|
||||
":rtype: bool");
|
||||
|
||||
static PyObject *
|
||||
Handle_pause(Handle *self)
|
||||
{
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
if(device->device->pause(self->handle))
|
||||
{
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_resume_doc,
|
||||
"resume()\n\n"
|
||||
"Resumes playback.\n\n"
|
||||
":return: Whether the action succeeded.\n"
|
||||
":rtype: bool");
|
||||
|
||||
static PyObject *
|
||||
Handle_resume(Handle *self)
|
||||
{
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
if(device->device->resume(self->handle))
|
||||
{
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_stop_doc,
|
||||
"stop()\n\n"
|
||||
"Stops playback.\n\n"
|
||||
":return: Whether the action succeeded.\n"
|
||||
":rtype: bool\n\n"
|
||||
".. note:: This makes the handle invalid.");
|
||||
|
||||
static PyObject *
|
||||
Handle_stop(Handle *self)
|
||||
{
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
if(device->device->stop(self->handle))
|
||||
{
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
static PyMethodDef Handle_methods[] = {
|
||||
{"pause", (PyCFunction)Handle_pause, METH_NOARGS,
|
||||
M_aud_Handle_pause_doc
|
||||
},
|
||||
{"resume", (PyCFunction)Handle_resume, METH_NOARGS,
|
||||
M_aud_Handle_resume_doc
|
||||
},
|
||||
{"stop", (PyCFunction)Handle_stop, METH_NOARGS,
|
||||
M_aud_Handle_stop_doc
|
||||
},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_position_doc,
|
||||
"The playback position of the sound in seconds.");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_position(Handle *self, void* nothing)
|
||||
{
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
return Py_BuildValue("f", device->device->getPosition(self->handle));
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_position(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float position;
|
||||
|
||||
if(!PyArg_Parse(args, "f:position", &position))
|
||||
return -1;
|
||||
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
if(device->device->seek(self->handle, position))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't seek the sound!");
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_keep_doc,
|
||||
"Whether the sound should be kept paused in the device when its "
|
||||
"end is reached.\n"
|
||||
"This can be used to seek the sound to some position and start "
|
||||
"playback again.\n\n"
|
||||
".. warning:: If this is set to true and you forget stopping this "
|
||||
"equals a memory leak as the handle exists until the device is "
|
||||
"destroyed.");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_keep(Handle *self, void* nothing)
|
||||
{
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
if(device->device->getKeep(self->handle))
|
||||
{
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_keep(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
if(!PyBool_Check(args))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool keep = args == Py_True;
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
if(device->device->setKeep(self->handle, keep))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set keep of the sound!");
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_status_doc,
|
||||
"Whether the sound is playing, paused or stopped (=invalid).");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_status(Handle *self, void* nothing)
|
||||
{
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
return Py_BuildValue("i", device->device->getStatus(self->handle));
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_volume_doc,
|
||||
"The volume of the sound.");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_volume(Handle *self, void* nothing)
|
||||
{
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
return Py_BuildValue("f", device->device->getVolume(self->handle));
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_volume(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float volume;
|
||||
|
||||
if(!PyArg_Parse(args, "f:volume", &volume))
|
||||
return -1;
|
||||
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
if(device->device->setVolume(self->handle, volume))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the sound volume!");
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_pitch_doc,
|
||||
"The pitch of the sound.");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_pitch(Handle *self, void* nothing)
|
||||
{
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
return Py_BuildValue("f", device->device->getPitch(self->handle));
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_pitch(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float pitch;
|
||||
|
||||
if(!PyArg_Parse(args, "f:pitch", &pitch))
|
||||
return -1;
|
||||
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
if(device->device->setPitch(self->handle, pitch))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the sound pitch!");
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_loop_count_doc,
|
||||
"The (remaining) loop count of the sound. A negative value indicates infinity.");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_loop_count(Handle *self, void* nothing)
|
||||
{
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
return Py_BuildValue("i", device->device->getLoopCount(self->handle));
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_loop_count(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
int loops;
|
||||
|
||||
if(!PyArg_Parse(args, "i:loop_count", &loops))
|
||||
return -1;
|
||||
|
||||
Device* device = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
if(device->device->setLoopCount(self->handle, loops))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the loop count!");
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_location_doc,
|
||||
"The source's location in 3D space, a 3D tuple of floats.");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_location(Handle *self, void* nothing)
|
||||
{
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
AUD_Vector3 v = device->getSourceLocation(self->handle);
|
||||
return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_location(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float x, y, z;
|
||||
|
||||
if(!PyArg_Parse(args, "(fff):location", &x, &y, &z))
|
||||
return -1;
|
||||
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
AUD_Vector3 location(x, y, z);
|
||||
if(device->setSourceLocation(self->handle, location))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Location couldn't be set!");
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_velocity_doc,
|
||||
"The source's velocity in 3D space, a 3D tuple of floats.");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_velocity(Handle *self, void* nothing)
|
||||
{
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
AUD_Vector3 v = device->getSourceVelocity(self->handle);
|
||||
return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_velocity(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float x, y, z;
|
||||
|
||||
if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z))
|
||||
return -1;
|
||||
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
AUD_Vector3 velocity(x, y, z);
|
||||
if(device->setSourceVelocity(self->handle, velocity))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the velocity!");
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_orientation_doc,
|
||||
"The source's orientation in 3D space as quaternion, a 4 float tuple.");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_orientation(Handle *self, void* nothing)
|
||||
{
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
AUD_Quaternion o = device->getSourceOrientation(self->handle);
|
||||
return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_orientation(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float w, x, y, z;
|
||||
|
||||
if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z))
|
||||
return -1;
|
||||
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
AUD_Quaternion orientation(w, x, y, z);
|
||||
if(device->setSourceOrientation(self->handle, orientation))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the orientation!");
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_relative_doc,
|
||||
"Whether the source's location, velocity and orientation is relative or absolute to the listener.");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_relative(Handle *self, void* nothing)
|
||||
{
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
if(device->isRelative(self->handle))
|
||||
{
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_relative(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
if(!PyBool_Check(args))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Value is not a boolean!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool relative = (args == Py_True);
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
if(device->setRelative(self->handle, relative))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the relativeness!");
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc,
|
||||
"The minimum volume of the source.\n\n"
|
||||
".. seealso:: :attr:`Device.distance_model`");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_volume_minimum(Handle *self, void* nothing)
|
||||
{
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
return Py_BuildValue("f", device->getVolumeMinimum(self->handle));
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float volume;
|
||||
|
||||
if(!PyArg_Parse(args, "f:volume_minimum", &volume))
|
||||
return -1;
|
||||
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
if(device->setVolumeMinimum(self->handle, volume))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the minimum volume!");
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc,
|
||||
"The maximum volume of the source.\n\n"
|
||||
".. seealso:: :attr:`Device.distance_model`");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_volume_maximum(Handle *self, void* nothing)
|
||||
{
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
return Py_BuildValue("f", device->getVolumeMaximum(self->handle));
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float volume;
|
||||
|
||||
if(!PyArg_Parse(args, "f:volume_maximum", &volume))
|
||||
return -1;
|
||||
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
if(device->setVolumeMaximum(self->handle, volume))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the maximum volume!");
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_distance_reference_doc,
|
||||
"The reference distance of the source.\n"
|
||||
"At this distance the volume will be exactly :attr:`volume`.\n\n"
|
||||
".. seealso:: :attr:`Device.distance_model`");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_distance_reference(Handle *self, void* nothing)
|
||||
{
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
return Py_BuildValue("f", device->getDistanceReference(self->handle));
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float distance;
|
||||
|
||||
if(!PyArg_Parse(args, "f:distance_reference", &distance))
|
||||
return -1;
|
||||
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
if(device->setDistanceReference(self->handle, distance))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the reference distance!");
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc,
|
||||
"The maximum distance of the source.\n"
|
||||
"If the listener is further away the source volume will be 0.\n\n"
|
||||
".. seealso:: :attr:`Device.distance_model`");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_distance_maximum(Handle *self, void* nothing)
|
||||
{
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
return Py_BuildValue("f", device->getDistanceMaximum(self->handle));
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float distance;
|
||||
|
||||
if(!PyArg_Parse(args, "f:distance_maximum", &distance))
|
||||
return -1;
|
||||
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
if(device->setDistanceMaximum(self->handle, distance))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the maximum distance!");
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_attenuation_doc,
|
||||
"This factor is used for distance based attenuation of the "
|
||||
"source.\n\n"
|
||||
".. seealso:: :attr:`Device.distance_model`");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_attenuation(Handle *self, void* nothing)
|
||||
{
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
return Py_BuildValue("f", device->getAttenuation(self->handle));
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_attenuation(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float factor;
|
||||
|
||||
if(!PyArg_Parse(args, "f:attenuation", &factor))
|
||||
return -1;
|
||||
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
if(device->setAttenuation(self->handle, factor))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the attenuation!");
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc,
|
||||
"The opening angle of the inner cone of the source. If the cone "
|
||||
"values of a source are set there are two (audible) cones with "
|
||||
"the apex at the :attr:`location` of the source and with infinite "
|
||||
"height, heading in the direction of the source's "
|
||||
":attr:`orientation`.\n"
|
||||
"In the inner cone the volume is normal. Outside the outer cone "
|
||||
"the volume will be :attr:`cone_volume_outer` and in the area "
|
||||
"between the volume will be interpolated linearly.");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_cone_angle_inner(Handle *self, void* nothing)
|
||||
{
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
return Py_BuildValue("f", device->getConeAngleInner(self->handle));
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float angle;
|
||||
|
||||
if(!PyArg_Parse(args, "f:cone_angle_inner", &angle))
|
||||
return -1;
|
||||
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
if(device->setConeAngleInner(self->handle, angle))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the cone inner angle!");
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc,
|
||||
"The opening angle of the outer cone of the source.\n\n"
|
||||
".. seealso:: :attr:`cone_angle_inner`");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_cone_angle_outer(Handle *self, void* nothing)
|
||||
{
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
return Py_BuildValue("f", device->getConeAngleOuter(self->handle));
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float angle;
|
||||
|
||||
if(!PyArg_Parse(args, "f:cone_angle_outer", &angle))
|
||||
return -1;
|
||||
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
if(device->setConeAngleOuter(self->handle, angle))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the cone outer angle!");
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc,
|
||||
"The volume outside the outer cone of the source.\n\n"
|
||||
".. seealso:: :attr:`cone_angle_inner`");
|
||||
|
||||
static PyObject *
|
||||
Handle_get_cone_volume_outer(Handle *self, void* nothing)
|
||||
{
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
return Py_BuildValue("f", device->getConeVolumeOuter(self->handle));
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float volume;
|
||||
|
||||
if(!PyArg_Parse(args, "f:cone_volume_outer", &volume))
|
||||
return -1;
|
||||
|
||||
Device* dev = (Device*)self->device;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device);
|
||||
if(device)
|
||||
{
|
||||
if(device->setConeVolumeOuter(self->handle, volume))
|
||||
return 0;
|
||||
PyErr_SetString(AUDError, "Couldn't set the cone outer volume!");
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static PyGetSetDef Handle_properties[] = {
|
||||
{(char*)"position", (getter)Handle_get_position, (setter)Handle_set_position,
|
||||
M_aud_Handle_position_doc, NULL },
|
||||
{(char*)"keep", (getter)Handle_get_keep, (setter)Handle_set_keep,
|
||||
M_aud_Handle_keep_doc, NULL },
|
||||
{(char*)"status", (getter)Handle_get_status, NULL,
|
||||
M_aud_Handle_status_doc, NULL },
|
||||
{(char*)"volume", (getter)Handle_get_volume, (setter)Handle_set_volume,
|
||||
M_aud_Handle_volume_doc, NULL },
|
||||
{(char*)"pitch", (getter)Handle_get_pitch, (setter)Handle_set_pitch,
|
||||
M_aud_Handle_pitch_doc, NULL },
|
||||
{(char*)"loop_count", (getter)Handle_get_loop_count, (setter)Handle_set_loop_count,
|
||||
M_aud_Handle_loop_count_doc, NULL },
|
||||
{(char*)"location", (getter)Handle_get_location, (setter)Handle_set_location,
|
||||
M_aud_Handle_location_doc, NULL },
|
||||
{(char*)"velocity", (getter)Handle_get_velocity, (setter)Handle_set_velocity,
|
||||
M_aud_Handle_velocity_doc, NULL },
|
||||
{(char*)"orientation", (getter)Handle_get_orientation, (setter)Handle_set_orientation,
|
||||
M_aud_Handle_orientation_doc, NULL },
|
||||
{(char*)"relative", (getter)Handle_get_relative, (setter)Handle_set_relative,
|
||||
M_aud_Handle_relative_doc, NULL },
|
||||
{(char*)"volume_minimum", (getter)Handle_get_volume_minimum, (setter)Handle_set_volume_minimum,
|
||||
M_aud_Handle_volume_minimum_doc, NULL },
|
||||
{(char*)"volume_maximum", (getter)Handle_get_volume_maximum, (setter)Handle_set_volume_maximum,
|
||||
M_aud_Handle_volume_maximum_doc, NULL },
|
||||
{(char*)"distance_reference", (getter)Handle_get_distance_reference, (setter)Handle_set_distance_reference,
|
||||
M_aud_Handle_distance_reference_doc, NULL },
|
||||
{(char*)"distance_maximum", (getter)Handle_get_distance_maximum, (setter)Handle_set_distance_maximum,
|
||||
M_aud_Handle_distance_maximum_doc, NULL },
|
||||
{(char*)"attenuation", (getter)Handle_get_attenuation, (setter)Handle_set_attenuation,
|
||||
M_aud_Handle_attenuation_doc, NULL },
|
||||
{(char*)"cone_angle_inner", (getter)Handle_get_cone_angle_inner, (setter)Handle_set_cone_angle_inner,
|
||||
M_aud_Handle_cone_angle_inner_doc, NULL },
|
||||
{(char*)"cone_angle_outer", (getter)Handle_get_cone_angle_outer, (setter)Handle_set_cone_angle_outer,
|
||||
M_aud_Handle_cone_angle_outer_doc, NULL },
|
||||
{(char*)"cone_volume_outer", (getter)Handle_get_cone_volume_outer, (setter)Handle_set_cone_volume_outer,
|
||||
M_aud_Handle_cone_volume_outer_doc, NULL },
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
PyDoc_STRVAR(M_aud_Handle_doc,
|
||||
"Handle objects are playback handles that can be used to control "
|
||||
"playback of a sound. If a sound is played back multiple times "
|
||||
"then there are as many handles.");
|
||||
|
||||
static PyTypeObject HandleType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"aud.Handle", /* tp_name */
|
||||
sizeof(Handle), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)Handle_dealloc,/* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_reserved */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
M_aud_Handle_doc, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
Handle_methods, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
Handle_properties, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
0, /* tp_new */
|
||||
};
|
||||
|
||||
// ========== Device ==================================================
|
||||
|
||||
static void
|
||||
Device_dealloc(Device* self)
|
||||
{
|
||||
if(self->device)
|
||||
delete self->device;
|
||||
Py_TYPE(self)->tp_free((PyObject*)self);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
Device *self;
|
||||
|
||||
static const char *kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", NULL};
|
||||
int device;
|
||||
int rate = AUD_RATE_44100;
|
||||
int channels = AUD_CHANNELS_STEREO;
|
||||
int format = AUD_FORMAT_FLOAT32;
|
||||
int buffersize = AUD_DEFAULT_BUFFER_SIZE;
|
||||
const char* name = "Audaspace";
|
||||
|
||||
if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|iiiis:Device", const_cast<char**>(kwlist),
|
||||
&device, &rate, &channels, &format, &buffersize, &name))
|
||||
return NULL;
|
||||
|
||||
if(buffersize < 128)
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "buffer_size must be greater than 127!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self = (Device*)type->tp_alloc(type, 0);
|
||||
if(self != NULL)
|
||||
{
|
||||
AUD_DeviceSpecs specs;
|
||||
specs.channels = (AUD_Channels)channels;
|
||||
specs.format = (AUD_SampleFormat)format;
|
||||
specs.rate = (AUD_SampleRate)rate;
|
||||
|
||||
self->device = NULL;
|
||||
|
||||
try
|
||||
{
|
||||
switch(device)
|
||||
{
|
||||
case AUD_DEVICE_NULL:
|
||||
self->device = new AUD_NULLDevice();
|
||||
break;
|
||||
case AUD_DEVICE_OPENAL:
|
||||
#ifdef WITH_OPENAL
|
||||
self->device = new AUD_OpenALDevice(specs, buffersize);
|
||||
#endif
|
||||
break;
|
||||
case AUD_DEVICE_SDL:
|
||||
#ifdef WITH_SDL
|
||||
self->device = new AUD_SDLDevice(specs, buffersize);
|
||||
#endif
|
||||
break;
|
||||
case AUD_DEVICE_JACK:
|
||||
#ifdef WITH_JACK
|
||||
self->device = new AUD_JackDevice(name, specs, buffersize);
|
||||
#endif
|
||||
break;
|
||||
case AUD_DEVICE_READ:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(self);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!self->device)
|
||||
{
|
||||
Py_DECREF(self);
|
||||
PyErr_SetString(AUDError, "Unsupported device type!");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)self;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_play_doc,
|
||||
"play(factory, keep=False)\n\n"
|
||||
"Plays a factory.\n\n"
|
||||
":arg factory: The factory to play.\n"
|
||||
":type factory: :class:`Factory`\n"
|
||||
":arg keep: See :attr:`Handle.keep`.\n"
|
||||
":type keep: bool\n"
|
||||
":return: The playback handle with which playback can be "
|
||||
"controlled with.\n"
|
||||
":rtype: :class:`Handle`");
|
||||
|
||||
static PyObject *
|
||||
Device_play(Device *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject* object;
|
||||
PyObject* keepo = NULL;
|
||||
|
||||
bool keep = false;
|
||||
|
||||
static const char *kwlist[] = {"factory", "keep", NULL};
|
||||
|
||||
if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:play", const_cast<char**>(kwlist), &object, &keepo))
|
||||
return NULL;
|
||||
|
||||
if(!PyObject_TypeCheck(object, &FactoryType))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(keepo != NULL)
|
||||
{
|
||||
if(!PyBool_Check(keepo))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
keep = keepo == Py_True;
|
||||
}
|
||||
|
||||
Factory* sound = (Factory*)object;
|
||||
Handle *handle;
|
||||
|
||||
handle = (Handle*)HandleType.tp_alloc(&HandleType, 0);
|
||||
if(handle != NULL)
|
||||
{
|
||||
handle->device = (PyObject*)self;
|
||||
Py_INCREF(self);
|
||||
|
||||
try
|
||||
{
|
||||
handle->handle = self->device->play(sound->factory, keep);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
Py_DECREF(handle);
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (PyObject *)handle;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_lock_doc,
|
||||
"lock()\n\n"
|
||||
"Locks the device so that it's guaranteed, that no samples are "
|
||||
"read from the streams until :meth:`unlock` is called.\n"
|
||||
"This is useful if you want to do start/stop/pause/resume some "
|
||||
"sounds at the same time.\n\n"
|
||||
".. note:: The device has to be unlocked as often as locked to be "
|
||||
"able to continue playback.\n\n"
|
||||
".. warning:: Make sure the time between locking and unlocking is "
|
||||
"as short as possible to avoid clicks.");
|
||||
|
||||
static PyObject *
|
||||
Device_lock(Device *self)
|
||||
{
|
||||
try
|
||||
{
|
||||
self->device->lock();
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_unlock_doc,
|
||||
"unlock()\n\n"
|
||||
"Unlocks the device after a lock call, see :meth:`lock` for "
|
||||
"details.");
|
||||
|
||||
static PyObject *
|
||||
Device_unlock(Device *self)
|
||||
{
|
||||
try
|
||||
{
|
||||
self->device->unlock();
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyMethodDef Device_methods[] = {
|
||||
{"play", (PyCFunction)Device_play, METH_VARARGS | METH_KEYWORDS,
|
||||
M_aud_Device_play_doc
|
||||
},
|
||||
{"lock", (PyCFunction)Device_lock, METH_NOARGS,
|
||||
M_aud_Device_lock_doc
|
||||
},
|
||||
{"unlock", (PyCFunction)Device_unlock, METH_NOARGS,
|
||||
M_aud_Device_unlock_doc
|
||||
},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_rate_doc,
|
||||
"The sampling rate of the device in Hz.");
|
||||
|
||||
static PyObject *
|
||||
Device_get_rate(Device *self, void* nothing)
|
||||
{
|
||||
try
|
||||
{
|
||||
AUD_DeviceSpecs specs = self->device->getSpecs();
|
||||
return Py_BuildValue("i", specs.rate);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_format_doc,
|
||||
"The native sample format of the device.");
|
||||
|
||||
static PyObject *
|
||||
Device_get_format(Device *self, void* nothing)
|
||||
{
|
||||
try
|
||||
{
|
||||
AUD_DeviceSpecs specs = self->device->getSpecs();
|
||||
return Py_BuildValue("i", specs.format);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_channels_doc,
|
||||
"The channel count of the device.");
|
||||
|
||||
static PyObject *
|
||||
Device_get_channels(Device *self, void* nothing)
|
||||
{
|
||||
try
|
||||
{
|
||||
AUD_DeviceSpecs specs = self->device->getSpecs();
|
||||
return Py_BuildValue("i", specs.channels);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_volume_doc,
|
||||
"The overall volume of the device.");
|
||||
|
||||
static PyObject *
|
||||
Device_get_volume(Device *self, void* nothing)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Py_BuildValue("f", self->device->getVolume());
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Device_set_volume(Device *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float volume;
|
||||
|
||||
if(!PyArg_Parse(args, "f:volume", &volume))
|
||||
return -1;
|
||||
|
||||
try
|
||||
{
|
||||
self->device->setVolume(volume);
|
||||
return 0;
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_listener_location_doc,
|
||||
"The listeners's location in 3D space, a 3D tuple of floats.");
|
||||
|
||||
static PyObject *
|
||||
Device_get_listener_location(Device *self, void* nothing)
|
||||
{
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
|
||||
if(device)
|
||||
{
|
||||
AUD_Vector3 v = device->getListenerLocation();
|
||||
return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
Device_set_listener_location(Device *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float x, y, z;
|
||||
|
||||
if(!PyArg_Parse(args, "(fff):listener_location", &x, &y, &z))
|
||||
return -1;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
|
||||
if(device)
|
||||
{
|
||||
AUD_Vector3 location(x, y, z);
|
||||
device->setListenerLocation(location);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_listener_velocity_doc,
|
||||
"The listener's velocity in 3D space, a 3D tuple of floats.");
|
||||
|
||||
static PyObject *
|
||||
Device_get_listener_velocity(Device *self, void* nothing)
|
||||
{
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
|
||||
if(device)
|
||||
{
|
||||
AUD_Vector3 v = device->getListenerVelocity();
|
||||
return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
Device_set_listener_velocity(Device *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float x, y, z;
|
||||
|
||||
if(!PyArg_Parse(args, "(fff):listener_velocity", &x, &y, &z))
|
||||
return -1;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
|
||||
if(device)
|
||||
{
|
||||
AUD_Vector3 velocity(x, y, z);
|
||||
device->setListenerVelocity(velocity);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_listener_orientation_doc,
|
||||
"The listener's orientation in 3D space as quaternion, a 4 float tuple.");
|
||||
|
||||
static PyObject *
|
||||
Device_get_listener_orientation(Device *self, void* nothing)
|
||||
{
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
|
||||
if(device)
|
||||
{
|
||||
AUD_Quaternion o = device->getListenerOrientation();
|
||||
return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
Device_set_listener_orientation(Device *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float w, x, y, z;
|
||||
|
||||
if(!PyArg_Parse(args, "(ffff):listener_orientation", &w, &x, &y, &z))
|
||||
return -1;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
|
||||
if(device)
|
||||
{
|
||||
AUD_Quaternion orientation(w, x, y, z);
|
||||
device->setListenerOrientation(orientation);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_speed_of_sound_doc,
|
||||
"The speed of sound of the device.\n"
|
||||
"The speed of sound in air is typically 343 m/s.");
|
||||
|
||||
static PyObject *
|
||||
Device_get_speed_of_sound(Device *self, void* nothing)
|
||||
{
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
|
||||
if(device)
|
||||
{
|
||||
return Py_BuildValue("f", device->getSpeedOfSound());
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Device_set_speed_of_sound(Device *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float speed;
|
||||
|
||||
if(!PyArg_Parse(args, "f:speed_of_sound", &speed))
|
||||
return -1;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
|
||||
if(device)
|
||||
{
|
||||
device->setSpeedOfSound(speed);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_doppler_factor_doc,
|
||||
"The doppler factor of the device.\n"
|
||||
"This factor is a scaling factor for the velocity vectors in "
|
||||
"doppler calculation. So a value bigger than 1 will exaggerate "
|
||||
"the effect as it raises the velocity.");
|
||||
|
||||
static PyObject *
|
||||
Device_get_doppler_factor(Device *self, void* nothing)
|
||||
{
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
|
||||
if(device)
|
||||
{
|
||||
return Py_BuildValue("f", device->getDopplerFactor());
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Device_set_doppler_factor(Device *self, PyObject* args, void* nothing)
|
||||
{
|
||||
float factor;
|
||||
|
||||
if(!PyArg_Parse(args, "f:doppler_factor", &factor))
|
||||
return -1;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
|
||||
if(device)
|
||||
{
|
||||
device->setDopplerFactor(factor);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_distance_model_doc,
|
||||
"The distance model of the device.\n\n"
|
||||
".. seealso:: http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm#_Toc199835864");
|
||||
|
||||
static PyObject *
|
||||
Device_get_distance_model(Device *self, void* nothing)
|
||||
{
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
|
||||
if(device)
|
||||
{
|
||||
return Py_BuildValue("i", int(device->getDistanceModel()));
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
Device_set_distance_model(Device *self, PyObject* args, void* nothing)
|
||||
{
|
||||
int model;
|
||||
|
||||
if(!PyArg_Parse(args, "i:distance_model", &model))
|
||||
return -1;
|
||||
|
||||
try
|
||||
{
|
||||
AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device);
|
||||
if(device)
|
||||
{
|
||||
device->setDistanceModel(AUD_DistanceModel(model));
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
PyErr_SetString(AUDError, device_not_3d_error);
|
||||
}
|
||||
catch(AUD_Exception& e)
|
||||
{
|
||||
PyErr_SetString(AUDError, e.str);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static PyGetSetDef Device_properties[] = {
|
||||
{(char*)"rate", (getter)Device_get_rate, NULL,
|
||||
M_aud_Device_rate_doc, NULL },
|
||||
{(char*)"format", (getter)Device_get_format, NULL,
|
||||
M_aud_Device_format_doc, NULL },
|
||||
{(char*)"channels", (getter)Device_get_channels, NULL,
|
||||
M_aud_Device_channels_doc, NULL },
|
||||
{(char*)"volume", (getter)Device_get_volume, (setter)Device_set_volume,
|
||||
M_aud_Device_volume_doc, NULL },
|
||||
{(char*)"listener_location", (getter)Device_get_listener_location, (setter)Device_set_listener_location,
|
||||
M_aud_Device_listener_location_doc, NULL },
|
||||
{(char*)"listener_velocity", (getter)Device_get_listener_velocity, (setter)Device_set_listener_velocity,
|
||||
M_aud_Device_listener_velocity_doc, NULL },
|
||||
{(char*)"listener_orientation", (getter)Device_get_listener_orientation, (setter)Device_set_listener_orientation,
|
||||
M_aud_Device_listener_orientation_doc, NULL },
|
||||
{(char*)"speed_of_sound", (getter)Device_get_speed_of_sound, (setter)Device_set_speed_of_sound,
|
||||
M_aud_Device_speed_of_sound_doc, NULL },
|
||||
{(char*)"doppler_factor", (getter)Device_get_doppler_factor, (setter)Device_set_doppler_factor,
|
||||
M_aud_Device_doppler_factor_doc, NULL },
|
||||
{(char*)"distance_model", (getter)Device_get_distance_model, (setter)Device_set_distance_model,
|
||||
M_aud_Device_distance_model_doc, NULL },
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
PyDoc_STRVAR(M_aud_Device_doc,
|
||||
"Device objects represent an audio output backend like OpenAL or "
|
||||
"SDL, but might also represent a file output or RAM buffer "
|
||||
"output.");
|
||||
|
||||
static PyTypeObject DeviceType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"aud.Device", /* tp_name */
|
||||
sizeof(Device), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)Device_dealloc,/* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_reserved */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
M_aud_Device_doc, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
Device_methods, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
Device_properties, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
Device_new, /* tp_new */
|
||||
};
|
||||
|
||||
PyObject *
|
||||
Device_empty()
|
||||
{
|
||||
return DeviceType.tp_alloc(&DeviceType, 0);
|
||||
}
|
||||
|
||||
// ====================================================================
|
||||
|
||||
PyDoc_STRVAR(M_aud_doc,
|
||||
"This module provides access to the audaspace audio library.");
|
||||
|
||||
static struct PyModuleDef audmodule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"aud", /* name of module */
|
||||
M_aud_doc, /* module documentation */
|
||||
-1, /* size of per-interpreter state of the module,
|
||||
or -1 if the module keeps state in global variables. */
|
||||
NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit_aud(void)
|
||||
{
|
||||
PyObject* m;
|
||||
|
||||
if(PyType_Ready(&FactoryType) < 0)
|
||||
return NULL;
|
||||
|
||||
if(PyType_Ready(&DeviceType) < 0)
|
||||
return NULL;
|
||||
|
||||
if(PyType_Ready(&HandleType) < 0)
|
||||
return NULL;
|
||||
|
||||
m = PyModule_Create(&audmodule);
|
||||
if(m == NULL)
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(&FactoryType);
|
||||
PyModule_AddObject(m, "Factory", (PyObject*)&FactoryType);
|
||||
|
||||
Py_INCREF(&DeviceType);
|
||||
PyModule_AddObject(m, "Device", (PyObject*)&DeviceType);
|
||||
|
||||
Py_INCREF(&HandleType);
|
||||
PyModule_AddObject(m, "Handle", (PyObject*)&HandleType);
|
||||
|
||||
AUDError = PyErr_NewException("aud.error", NULL, NULL);
|
||||
Py_INCREF(AUDError);
|
||||
PyModule_AddObject(m, "error", AUDError);
|
||||
|
||||
// device constants
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_NULL);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_OPENAL);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_SDL);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_JACK);
|
||||
//PY_MODULE_ADD_CONSTANT(m, AUD_DEVICE_READ);
|
||||
// format constants
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT32);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_FLOAT64);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_INVALID);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S16);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S24);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_S32);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_FORMAT_U8);
|
||||
// status constants
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_INVALID);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PAUSED);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_STATUS_PLAYING);
|
||||
// distance model constants
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_EXPONENT_CLAMPED);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVERSE_CLAMPED);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_LINEAR_CLAMPED);
|
||||
PY_MODULE_ADD_CONSTANT(m, AUD_DISTANCE_MODEL_INVALID);
|
||||
|
||||
return m;
|
||||
}
|
||||
67
intern/audaspace/Python/AUD_PyAPI.h
Normal file
67
intern/audaspace/Python/AUD_PyAPI.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* $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_PYAPI
|
||||
#define AUD_PYAPI
|
||||
|
||||
#include "Python.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#include "AUD_IDevice.h"
|
||||
#else
|
||||
typedef void AUD_IFactory;
|
||||
typedef void AUD_IDevice;
|
||||
typedef void AUD_Handle;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject* child_list;
|
||||
AUD_IFactory* factory;
|
||||
} Factory;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
AUD_Handle* handle;
|
||||
PyObject* device;
|
||||
} Handle;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
AUD_IDevice* device;
|
||||
} Device;
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit_aud(void);
|
||||
|
||||
extern PyObject *
|
||||
Device_empty();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //AUD_PYAPI
|
||||
@@ -36,6 +36,11 @@ if env['WITH_BF_FFTW3']:
|
||||
incs += ' fftw ' + env['BF_FFTW3_INC']
|
||||
defs.append('WITH_FFTW3')
|
||||
|
||||
if env['WITH_BF_PYTHON']:
|
||||
sources += env.Glob('Python/*.cpp')
|
||||
incs += ' Python ' + env['BF_PYTHON_INC']
|
||||
defs.append('WITH_PYTHON')
|
||||
|
||||
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
|
||||
incs += ' ' + env['BF_PTHREADS_INC']
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ void AUD_SDLDevice::SDL_mix(void *data, Uint8* buffer, int length)
|
||||
device->mix((data_t*)buffer,length/AUD_DEVICE_SAMPLE_SIZE(device->m_specs));
|
||||
}
|
||||
|
||||
static const char* open_error = "AUD_SDLDevice: Device couldn't be opened.";
|
||||
static const char* format_error = "AUD_SDLDevice: Obtained unsupported sample "
|
||||
"format.";
|
||||
|
||||
AUD_SDLDevice::AUD_SDLDevice(AUD_DeviceSpecs specs, int buffersize)
|
||||
{
|
||||
if(specs.channels == AUD_CHANNELS_INVALID)
|
||||
@@ -57,7 +61,7 @@ AUD_SDLDevice::AUD_SDLDevice(AUD_DeviceSpecs specs, int buffersize)
|
||||
format.userdata = this;
|
||||
|
||||
if(SDL_OpenAudio(&format, &obtained) != 0)
|
||||
AUD_THROW(AUD_ERROR_SDL);
|
||||
AUD_THROW(AUD_ERROR_SDL, open_error);
|
||||
|
||||
m_specs.rate = (AUD_SampleRate)obtained.freq;
|
||||
m_specs.channels = (AUD_Channels)obtained.channels;
|
||||
@@ -66,7 +70,10 @@ AUD_SDLDevice::AUD_SDLDevice(AUD_DeviceSpecs specs, int buffersize)
|
||||
else if(obtained.format == AUDIO_S16LSB || obtained.format == AUDIO_S16MSB)
|
||||
m_specs.format = AUD_FORMAT_S16;
|
||||
else
|
||||
AUD_THROW(AUD_ERROR_SDL);
|
||||
{
|
||||
SDL_CloseAudio();
|
||||
AUD_THROW(AUD_ERROR_SDL, format_error);
|
||||
}
|
||||
|
||||
create();
|
||||
}
|
||||
|
||||
@@ -44,6 +44,10 @@ private:
|
||||
*/
|
||||
static void SDL_mix(void *data, Uint8* buffer, int length);
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SDLDevice(const AUD_SDLDevice&);
|
||||
AUD_SDLDevice& operator=(const AUD_SDLDevice&);
|
||||
|
||||
protected:
|
||||
virtual void playing(bool playing);
|
||||
|
||||
|
||||
@@ -26,28 +26,18 @@
|
||||
#include "AUD_SRCResampleFactory.h"
|
||||
#include "AUD_SRCResampleReader.h"
|
||||
|
||||
AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IReader* reader,
|
||||
AUD_DeviceSpecs specs) :
|
||||
AUD_ResampleFactory(reader, specs) {}
|
||||
|
||||
AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IFactory* factory,
|
||||
AUD_DeviceSpecs specs) :
|
||||
AUD_ResampleFactory(factory, specs) {}
|
||||
AUD_ResampleFactory(factory, specs)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_DeviceSpecs specs) :
|
||||
AUD_ResampleFactory(specs) {}
|
||||
|
||||
AUD_IReader* AUD_SRCResampleFactory::createReader()
|
||||
AUD_IReader* AUD_SRCResampleFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
if(reader->getSpecs().rate != m_specs.rate)
|
||||
{
|
||||
reader = new AUD_SRCResampleReader(reader, m_specs.specs);
|
||||
AUD_NEW("reader")
|
||||
}
|
||||
}
|
||||
if(reader->getSpecs().rate != m_specs.rate)
|
||||
reader = new AUD_SRCResampleReader(reader, m_specs.specs);
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
@@ -34,12 +34,15 @@
|
||||
*/
|
||||
class AUD_SRCResampleFactory : public AUD_ResampleFactory
|
||||
{
|
||||
public:
|
||||
AUD_SRCResampleFactory(AUD_IReader* reader, AUD_DeviceSpecs specs);
|
||||
AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
|
||||
AUD_SRCResampleFactory(AUD_DeviceSpecs specs);
|
||||
private:
|
||||
// hide copy constructor and operator=
|
||||
AUD_SRCResampleFactory(const AUD_SRCResampleFactory&);
|
||||
AUD_SRCResampleFactory& operator=(const AUD_SRCResampleFactory&);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
public:
|
||||
AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_SRCRESAMPLEFACTORY
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
*/
|
||||
|
||||
#include "AUD_SRCResampleReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
@@ -35,16 +34,18 @@ static long src_callback(void *cb_data, float **data)
|
||||
return ((AUD_SRCResampleReader*)cb_data)->doCallback(data);
|
||||
}
|
||||
|
||||
static const char* state_error = "AUD_SRCResampleReader: SRC State couldn't be "
|
||||
"created.";
|
||||
|
||||
AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader,
|
||||
AUD_Specs specs) :
|
||||
AUD_EffectReader(reader)
|
||||
AUD_EffectReader(reader),
|
||||
m_sspecs(reader->getSpecs()),
|
||||
m_factor(double(specs.rate) / double(m_sspecs.rate)),
|
||||
m_tspecs(specs),
|
||||
m_position(0)
|
||||
{
|
||||
m_sspecs = reader->getSpecs();
|
||||
|
||||
m_tspecs = specs;
|
||||
m_tspecs.channels = m_sspecs.channels;
|
||||
m_factor = (double)m_tspecs.rate / (double)m_sspecs.rate;
|
||||
m_position = 0;
|
||||
|
||||
int error;
|
||||
m_src = src_callback_new(src_callback,
|
||||
@@ -56,23 +57,18 @@ AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader,
|
||||
if(!m_src)
|
||||
{
|
||||
// XXX printf("%s\n", src_strerror(error));
|
||||
delete m_reader; AUD_DELETE("reader")
|
||||
AUD_THROW(AUD_ERROR_READER);
|
||||
AUD_THROW(AUD_ERROR_SRC, state_error);
|
||||
}
|
||||
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
}
|
||||
|
||||
AUD_SRCResampleReader::~AUD_SRCResampleReader()
|
||||
{
|
||||
src_delete(m_src);
|
||||
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
}
|
||||
|
||||
long AUD_SRCResampleReader::doCallback(float** data)
|
||||
{
|
||||
int length = m_buffer->getSize() / AUD_SAMPLE_SIZE(m_tspecs);
|
||||
int length = m_buffer.getSize() / AUD_SAMPLE_SIZE(m_tspecs);
|
||||
sample_t* buffer;
|
||||
|
||||
m_reader->read(length, buffer);
|
||||
@@ -88,17 +84,17 @@ void AUD_SRCResampleReader::seek(int position)
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
int AUD_SRCResampleReader::getLength()
|
||||
int AUD_SRCResampleReader::getLength() const
|
||||
{
|
||||
return m_reader->getLength() * m_factor;
|
||||
}
|
||||
|
||||
int AUD_SRCResampleReader::getPosition()
|
||||
int AUD_SRCResampleReader::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
AUD_Specs AUD_SRCResampleReader::getSpecs()
|
||||
AUD_Specs AUD_SRCResampleReader::getSpecs() const
|
||||
{
|
||||
return m_tspecs;
|
||||
}
|
||||
@@ -107,10 +103,10 @@ void AUD_SRCResampleReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
int size = length * AUD_SAMPLE_SIZE(m_tspecs);
|
||||
|
||||
if(m_buffer->getSize() < size)
|
||||
m_buffer->resize(size);
|
||||
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, buffer);
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#define AUD_SRCRESAMPLEREADER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <samplerate.h>
|
||||
|
||||
@@ -37,26 +37,26 @@ class AUD_Buffer;
|
||||
class AUD_SRCResampleReader : public AUD_EffectReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The sample specification of the source.
|
||||
*/
|
||||
const AUD_Specs m_sspecs;
|
||||
|
||||
/**
|
||||
* The resampling factor.
|
||||
*/
|
||||
double m_factor;
|
||||
const double m_factor;
|
||||
|
||||
/**
|
||||
* The sound output buffer.
|
||||
*/
|
||||
AUD_Buffer *m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The target specification.
|
||||
*/
|
||||
AUD_Specs m_tspecs;
|
||||
|
||||
/**
|
||||
* The sample specification of the source.
|
||||
*/
|
||||
AUD_Specs m_sspecs;
|
||||
|
||||
/**
|
||||
* The src state structure.
|
||||
*/
|
||||
@@ -67,14 +67,17 @@ private:
|
||||
*/
|
||||
int m_position;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SRCResampleReader(const AUD_SRCResampleReader&);
|
||||
AUD_SRCResampleReader& operator=(const AUD_SRCResampleReader&);
|
||||
|
||||
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.
|
||||
* resampled to the target specification.
|
||||
*/
|
||||
AUD_SRCResampleReader(AUD_IReader* reader, AUD_Specs specs);
|
||||
|
||||
@@ -92,9 +95,9 @@ public:
|
||||
long doCallback(float** data);
|
||||
|
||||
virtual void seek(int position);
|
||||
virtual int getLength();
|
||||
virtual int getPosition();
|
||||
virtual AUD_Specs getSpecs();
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -24,45 +24,29 @@
|
||||
*/
|
||||
|
||||
// needed for INT64_C
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include "AUD_FFMPEGFactory.h"
|
||||
#include "AUD_FFMPEGReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
AUD_FFMPEGFactory::AUD_FFMPEGFactory(const char* filename)
|
||||
AUD_FFMPEGFactory::AUD_FFMPEGFactory(std::string filename) :
|
||||
m_filename(filename)
|
||||
{
|
||||
if(filename != NULL)
|
||||
{
|
||||
m_filename = new char[strlen(filename)+1]; AUD_NEW("string")
|
||||
strcpy(m_filename, filename);
|
||||
}
|
||||
else
|
||||
m_filename = NULL;
|
||||
}
|
||||
|
||||
AUD_FFMPEGFactory::AUD_FFMPEGFactory(unsigned char* buffer, int size)
|
||||
AUD_FFMPEGFactory::AUD_FFMPEGFactory(const data_t* buffer, int size) :
|
||||
m_buffer(new AUD_Buffer(size))
|
||||
{
|
||||
m_filename = NULL;
|
||||
m_buffer = AUD_Reference<AUD_Buffer>(new AUD_Buffer(size));
|
||||
memcpy(m_buffer.get()->getBuffer(), buffer, size);
|
||||
}
|
||||
|
||||
AUD_FFMPEGFactory::~AUD_FFMPEGFactory()
|
||||
AUD_IReader* AUD_FFMPEGFactory::createReader() const
|
||||
{
|
||||
if(m_filename)
|
||||
{
|
||||
delete[] m_filename; AUD_DELETE("string")
|
||||
}
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_FFMPEGFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader;
|
||||
if(m_filename)
|
||||
reader = new AUD_FFMPEGReader(m_filename);
|
||||
if(m_buffer.get())
|
||||
return new AUD_FFMPEGReader(m_buffer);
|
||||
else
|
||||
reader = new AUD_FFMPEGReader(m_buffer);
|
||||
AUD_NEW("reader")
|
||||
return reader;
|
||||
return new AUD_FFMPEGReader(m_filename);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "AUD_Reference.h"
|
||||
class AUD_Buffer;
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* This factory reads a sound file via ffmpeg.
|
||||
* \warning Notice that the needed formats and codecs have to be registered
|
||||
@@ -41,33 +43,32 @@ private:
|
||||
/**
|
||||
* The filename of the sound source file.
|
||||
*/
|
||||
char* m_filename;
|
||||
const std::string m_filename;
|
||||
|
||||
/**
|
||||
* The buffer to read from.
|
||||
*/
|
||||
AUD_Reference<AUD_Buffer> m_buffer;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_FFMPEGFactory(const AUD_FFMPEGFactory&);
|
||||
AUD_FFMPEGFactory& operator=(const AUD_FFMPEGFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new factory.
|
||||
* \param filename The sound file path.
|
||||
*/
|
||||
AUD_FFMPEGFactory(const char* filename);
|
||||
AUD_FFMPEGFactory(std::string filename);
|
||||
|
||||
/**
|
||||
* Creates a new factory.
|
||||
* \param buffer The buffer to read from.
|
||||
* \param size The size of the buffer.
|
||||
*/
|
||||
AUD_FFMPEGFactory(unsigned char* buffer, int size);
|
||||
AUD_FFMPEGFactory(const data_t* buffer, int size);
|
||||
|
||||
/**
|
||||
* Destroys the factory.
|
||||
*/
|
||||
~AUD_FFMPEGFactory();
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_FFMPEGFACTORY
|
||||
|
||||
@@ -24,23 +24,24 @@
|
||||
*/
|
||||
|
||||
// needed for INT64_C
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include "AUD_FFMPEGReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
}
|
||||
|
||||
int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer)
|
||||
int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer& buffer)
|
||||
{
|
||||
// save packet parameters
|
||||
uint8_t *audio_pkg_data = packet->data;
|
||||
int audio_pkg_size = packet->size;
|
||||
|
||||
int buf_size = buffer->getSize();
|
||||
int buf_size = buffer.getSize();
|
||||
int buf_pos = 0;
|
||||
|
||||
int read_length, data_size;
|
||||
@@ -51,21 +52,16 @@ int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer)
|
||||
// resize buffer if needed
|
||||
if(buf_size - buf_pos < AVCODEC_MAX_AUDIO_FRAME_SIZE)
|
||||
{
|
||||
buffer->resize(buf_size + AVCODEC_MAX_AUDIO_FRAME_SIZE, true);
|
||||
buffer.resize(buf_size + AVCODEC_MAX_AUDIO_FRAME_SIZE, true);
|
||||
buf_size += AVCODEC_MAX_AUDIO_FRAME_SIZE;
|
||||
}
|
||||
|
||||
// read samples from the packet
|
||||
data_size = buf_size - buf_pos;
|
||||
/*read_length = avcodec_decode_audio3(m_codecCtx,
|
||||
(int16_t*)(((data_t*)buffer->getBuffer())+buf_pos),
|
||||
read_length = avcodec_decode_audio3(m_codecCtx,
|
||||
(int16_t*)(((data_t*)buffer.getBuffer())+buf_pos),
|
||||
&data_size,
|
||||
packet);*/
|
||||
read_length = avcodec_decode_audio2(m_codecCtx,
|
||||
(int16_t*)(((data_t*)buffer->getBuffer())+buf_pos),
|
||||
&data_size,
|
||||
audio_pkg_data,
|
||||
audio_pkg_size);
|
||||
packet);
|
||||
|
||||
// read error, next packet!
|
||||
if(read_length < 0)
|
||||
@@ -81,36 +77,50 @@ int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer)
|
||||
return buf_pos;
|
||||
}
|
||||
|
||||
static const char* streaminfo_error = "AUD_FFMPEGReader: Stream info couldn't "
|
||||
"be found.";
|
||||
static const char* noaudio_error = "AUD_FFMPEGReader: File doesn't include an "
|
||||
"audio stream.";
|
||||
static const char* nodecoder_error = "AUD_FFMPEGReader: No decoder found for "
|
||||
"the audio stream.";
|
||||
static const char* codecopen_error = "AUD_FFMPEGReader: Codec couldn't be "
|
||||
"opened.";
|
||||
static const char* format_error = "AUD_FFMPEGReader: Unsupported sample "
|
||||
"format.";
|
||||
|
||||
void AUD_FFMPEGReader::init()
|
||||
{
|
||||
m_position = 0;
|
||||
m_pkgbuf_left = 0;
|
||||
|
||||
if(av_find_stream_info(m_formatCtx)<0)
|
||||
AUD_THROW(AUD_ERROR_FFMPEG);
|
||||
AUD_THROW(AUD_ERROR_FFMPEG, streaminfo_error);
|
||||
|
||||
// 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);
|
||||
AUD_THROW(AUD_ERROR_FFMPEG, noaudio_error);
|
||||
|
||||
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);
|
||||
AUD_THROW(AUD_ERROR_FFMPEG, nodecoder_error);
|
||||
|
||||
if(avcodec_open(m_codecCtx, aCodec)<0)
|
||||
AUD_THROW(AUD_ERROR_FFMPEG);
|
||||
AUD_THROW(AUD_ERROR_FFMPEG, codecopen_error);
|
||||
|
||||
// XXX this prints file information to stdout:
|
||||
//dump_format(m_formatCtx, 0, NULL, 0);
|
||||
@@ -140,45 +150,49 @@ void AUD_FFMPEGReader::init()
|
||||
m_specs.format = AUD_FORMAT_FLOAT64;
|
||||
break;
|
||||
default:
|
||||
AUD_THROW(AUD_ERROR_FILE);
|
||||
AUD_THROW(AUD_ERROR_FFMPEG, format_error);
|
||||
}
|
||||
|
||||
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;
|
||||
static const char* fileopen_error = "AUD_FFMPEGReader: File couldn't be "
|
||||
"opened.";
|
||||
|
||||
AUD_FFMPEGReader::AUD_FFMPEGReader(std::string filename) :
|
||||
m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1),
|
||||
m_byteiocontext(NULL)
|
||||
{
|
||||
// open file
|
||||
if(av_open_input_file(&m_formatCtx, filename, NULL, 0, NULL)!=0)
|
||||
AUD_THROW(AUD_ERROR_FILE);
|
||||
if(av_open_input_file(&m_formatCtx, filename.c_str(), NULL, 0, NULL)!=0)
|
||||
AUD_THROW(AUD_ERROR_FILE, fileopen_error);
|
||||
|
||||
try
|
||||
{
|
||||
init();
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
av_close_input_file(m_formatCtx);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer)
|
||||
static const char* streamopen_error = "AUD_FFMPEGReader: Stream couldn't be "
|
||||
"opened.";
|
||||
|
||||
AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) :
|
||||
m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1),
|
||||
m_membuffer(buffer)
|
||||
{
|
||||
m_byteiocontext = (ByteIOContext*)av_mallocz(sizeof(ByteIOContext));
|
||||
AUD_NEW("byteiocontext")
|
||||
m_membuffer = buffer;
|
||||
|
||||
if(init_put_byte(m_byteiocontext, (data_t*)buffer.get()->getBuffer(),
|
||||
buffer.get()->getSize(), 0, NULL, NULL, NULL, NULL) != 0)
|
||||
AUD_THROW(AUD_ERROR_FILE);
|
||||
{
|
||||
av_free(m_byteiocontext);
|
||||
AUD_THROW(AUD_ERROR_FILE, fileopen_error);
|
||||
}
|
||||
|
||||
AVProbeData probe_data;
|
||||
probe_data.filename = "";
|
||||
@@ -188,16 +202,19 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer)
|
||||
|
||||
// open stream
|
||||
if(av_open_input_stream(&m_formatCtx, m_byteiocontext, "", fmt, NULL)!=0)
|
||||
AUD_THROW(AUD_ERROR_FILE);
|
||||
{
|
||||
av_free(m_byteiocontext);
|
||||
AUD_THROW(AUD_ERROR_FILE, streamopen_error);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
init();
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
av_close_input_stream(m_formatCtx);
|
||||
av_free(m_byteiocontext); AUD_DELETE("byteiocontext")
|
||||
av_free(m_byteiocontext);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -209,16 +226,13 @@ AUD_FFMPEGReader::~AUD_FFMPEGReader()
|
||||
if(m_byteiocontext)
|
||||
{
|
||||
av_close_input_stream(m_formatCtx);
|
||||
av_free(m_byteiocontext); AUD_DELETE("byteiocontext")
|
||||
av_free(m_byteiocontext);
|
||||
}
|
||||
else
|
||||
av_close_input_file(m_formatCtx);
|
||||
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
delete m_pkgbuf; AUD_DELETE("buffer")
|
||||
}
|
||||
|
||||
bool AUD_FFMPEGReader::isSeekable()
|
||||
bool AUD_FFMPEGReader::isSeekable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -260,9 +274,17 @@ void AUD_FFMPEGReader::seek(int position)
|
||||
|
||||
if(m_position < position)
|
||||
{
|
||||
sample_t* buf;
|
||||
int length = position - m_position;
|
||||
read(length, buf);
|
||||
// read until we're at the right position
|
||||
int length = AUD_DEFAULT_BUFFER_SIZE;
|
||||
sample_t* buffer;
|
||||
for(int len = position - m_position;
|
||||
length == AUD_DEFAULT_BUFFER_SIZE;
|
||||
len -= AUD_DEFAULT_BUFFER_SIZE)
|
||||
{
|
||||
if(len < AUD_DEFAULT_BUFFER_SIZE)
|
||||
length = len;
|
||||
read(length, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -276,33 +298,23 @@ void AUD_FFMPEGReader::seek(int position)
|
||||
}
|
||||
}
|
||||
|
||||
int AUD_FFMPEGReader::getLength()
|
||||
int AUD_FFMPEGReader::getLength() const
|
||||
{
|
||||
// return approximated remaning size
|
||||
return (int)((m_formatCtx->duration * m_codecCtx->sample_rate)
|
||||
/ AV_TIME_BASE)-m_position;
|
||||
}
|
||||
|
||||
int AUD_FFMPEGReader::getPosition()
|
||||
int AUD_FFMPEGReader::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
AUD_Specs AUD_FFMPEGReader::getSpecs()
|
||||
AUD_Specs AUD_FFMPEGReader::getSpecs() const
|
||||
{
|
||||
return m_specs.specs;
|
||||
}
|
||||
|
||||
AUD_ReaderType AUD_FFMPEGReader::getType()
|
||||
{
|
||||
return AUD_TYPE_STREAM;
|
||||
}
|
||||
|
||||
bool AUD_FFMPEGReader::notify(AUD_Message &message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
// read packages and decode them
|
||||
@@ -313,10 +325,10 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
|
||||
int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs);
|
||||
|
||||
// resize output buffer if necessary
|
||||
if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(m_specs))
|
||||
m_buffer->resize(length * AUD_SAMPLE_SIZE(m_specs));
|
||||
if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(m_specs))
|
||||
m_buffer.resize(length * AUD_SAMPLE_SIZE(m_specs));
|
||||
|
||||
buffer = m_buffer->getBuffer();
|
||||
buffer = m_buffer.getBuffer();
|
||||
pkgbuf_pos = m_pkgbuf_left;
|
||||
m_pkgbuf_left = 0;
|
||||
|
||||
@@ -324,7 +336,7 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
|
||||
if(pkgbuf_pos > 0)
|
||||
{
|
||||
data_size = AUD_MIN(pkgbuf_pos, left * sample_size);
|
||||
m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(),
|
||||
m_convert((data_t*) buffer, (data_t*) m_pkgbuf.getBuffer(),
|
||||
data_size / AUD_FORMAT_SIZE(m_specs.format));
|
||||
buffer += data_size / AUD_FORMAT_SIZE(m_specs.format);
|
||||
left -= data_size/sample_size;
|
||||
@@ -341,7 +353,7 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
|
||||
|
||||
// copy to output buffer
|
||||
data_size = AUD_MIN(pkgbuf_pos, left * sample_size);
|
||||
m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(),
|
||||
m_convert((data_t*) buffer, (data_t*) m_pkgbuf.getBuffer(),
|
||||
data_size / AUD_FORMAT_SIZE(m_specs.format));
|
||||
buffer += data_size / AUD_FORMAT_SIZE(m_specs.format);
|
||||
left -= data_size/sample_size;
|
||||
@@ -352,12 +364,12 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
|
||||
if(pkgbuf_pos > data_size)
|
||||
{
|
||||
m_pkgbuf_left = pkgbuf_pos-data_size;
|
||||
memmove(m_pkgbuf->getBuffer(),
|
||||
((data_t*)m_pkgbuf->getBuffer())+data_size,
|
||||
memmove(m_pkgbuf.getBuffer(),
|
||||
((data_t*)m_pkgbuf.getBuffer())+data_size,
|
||||
pkgbuf_pos-data_size);
|
||||
}
|
||||
|
||||
buffer = m_buffer->getBuffer();
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
if(left > 0)
|
||||
length -= left;
|
||||
|
||||
@@ -29,7 +29,9 @@
|
||||
#include "AUD_ConverterFunctions.h"
|
||||
#include "AUD_IReader.h"
|
||||
#include "AUD_Reference.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
struct AVCodecContext;
|
||||
extern "C" {
|
||||
@@ -55,7 +57,7 @@ private:
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer *m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The specification of the audio data.
|
||||
@@ -65,7 +67,7 @@ private:
|
||||
/**
|
||||
* The buffer for package reading.
|
||||
*/
|
||||
AUD_Buffer *m_pkgbuf;
|
||||
AUD_Buffer m_pkgbuf;
|
||||
|
||||
/**
|
||||
* The count of samples still available from the last read package.
|
||||
@@ -108,13 +110,17 @@ private:
|
||||
* \param buffer The target buffer.
|
||||
* \return The count of read bytes.
|
||||
*/
|
||||
int decode(AVPacket* packet, AUD_Buffer* buffer);
|
||||
int decode(AVPacket* packet, AUD_Buffer& buffer);
|
||||
|
||||
/**
|
||||
* Initializes the object.
|
||||
*/
|
||||
void init();
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_FFMPEGReader(const AUD_FFMPEGReader&);
|
||||
AUD_FFMPEGReader& operator=(const AUD_FFMPEGReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new reader.
|
||||
@@ -122,7 +128,7 @@ public:
|
||||
* \exception AUD_Exception Thrown if the file specified does not exist or
|
||||
* cannot be read with ffmpeg.
|
||||
*/
|
||||
AUD_FFMPEGReader(const char* filename);
|
||||
AUD_FFMPEGReader(std::string filename);
|
||||
|
||||
/**
|
||||
* Creates a new reader.
|
||||
@@ -137,13 +143,11 @@ public:
|
||||
*/
|
||||
virtual ~AUD_FFMPEGReader();
|
||||
|
||||
virtual bool isSeekable();
|
||||
virtual bool isSeekable() const;
|
||||
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 int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -83,7 +83,6 @@ public:
|
||||
* \param reader The reader to read from.
|
||||
* \param low The lowest passed frequency.
|
||||
* \param high The highest passed frequency.
|
||||
* \exception AUD_Exception Thrown if the reader specified is NULL.
|
||||
*/
|
||||
AUD_BandPassReader(AUD_IReader* reader, float low, float high);
|
||||
|
||||
|
||||
189
intern/audaspace/intern/AUD_3DMath.h
Normal file
189
intern/audaspace/intern/AUD_3DMath.h
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* $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_3DMATH
|
||||
#define AUD_3DMATH
|
||||
|
||||
class AUD_Quaternion
|
||||
{
|
||||
private:
|
||||
union
|
||||
{
|
||||
float m_v[4];
|
||||
struct
|
||||
{
|
||||
const float m_w;
|
||||
const float m_x;
|
||||
const float m_y;
|
||||
const float m_z;
|
||||
};
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new quaternion.
|
||||
* \param w The w component.
|
||||
* \param x The x component.
|
||||
* \param y The y component.
|
||||
* \param z The z component.
|
||||
*/
|
||||
inline AUD_Quaternion(float w, float x, float y, float z) :
|
||||
m_w(w), m_x(x), m_y(y), m_z(z)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the w component of the quarternion.
|
||||
* \return The w component.
|
||||
*/
|
||||
inline const float& w() const
|
||||
{
|
||||
return m_w;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the x component of the quarternion.
|
||||
* \return The x component.
|
||||
*/
|
||||
inline const float& x() const
|
||||
{
|
||||
return m_x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the y component of the quarternion.
|
||||
* \return The y component.
|
||||
*/
|
||||
inline const float& y() const
|
||||
{
|
||||
return m_y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the z component of the quarternion.
|
||||
* \return The z component.
|
||||
*/
|
||||
inline const float& z() const
|
||||
{
|
||||
return m_z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the components of the vector.
|
||||
* \param destination Where the 4 float values should be saved to.
|
||||
*/
|
||||
inline void get(float* destination) const
|
||||
{
|
||||
destination[0] = m_w;
|
||||
destination[1] = m_x;
|
||||
destination[2] = m_y;
|
||||
destination[3] = m_z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the components of the vector.
|
||||
* \return The components as float[4].
|
||||
*/
|
||||
inline const float* get() const
|
||||
{
|
||||
return m_v;
|
||||
}
|
||||
};
|
||||
|
||||
class AUD_Vector3
|
||||
{
|
||||
private:
|
||||
union
|
||||
{
|
||||
float m_v[3];
|
||||
struct
|
||||
{
|
||||
const float m_x;
|
||||
const float m_y;
|
||||
const float m_z;
|
||||
};
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new 3 dimensional vector.
|
||||
* \param x The x component.
|
||||
* \param y The y component.
|
||||
* \param z The z component.
|
||||
*/
|
||||
inline AUD_Vector3(float x, float y, float z) :
|
||||
m_x(x), m_y(y), m_z(z)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the x component of the vector.
|
||||
* \return The x component.
|
||||
*/
|
||||
inline const float& x() const
|
||||
{
|
||||
return m_x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the y component of the vector.
|
||||
* \return The y component.
|
||||
*/
|
||||
inline const float& y() const
|
||||
{
|
||||
return m_y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the z component of the vector.
|
||||
* \return The z component.
|
||||
*/
|
||||
inline const float& z() const
|
||||
{
|
||||
return m_z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the components of the vector.
|
||||
* \param destination Where the 3 float values should be saved to.
|
||||
*/
|
||||
inline void get(float* destination) const
|
||||
{
|
||||
destination[0] = m_x;
|
||||
destination[1] = m_y;
|
||||
destination[2] = m_z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the components of the vector.
|
||||
* \return The components as float[3].
|
||||
*/
|
||||
inline const float* get() const
|
||||
{
|
||||
return m_v;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //AUD_3DMATH
|
||||
@@ -34,34 +34,37 @@
|
||||
AUD_Buffer::AUD_Buffer(int size)
|
||||
{
|
||||
m_size = size;
|
||||
m_buffer = (data_t*) malloc(size+16); AUD_NEW("buffer")
|
||||
m_buffer = (data_t*) malloc(size+16);
|
||||
}
|
||||
|
||||
AUD_Buffer::~AUD_Buffer()
|
||||
{
|
||||
free(m_buffer); AUD_DELETE("buffer")
|
||||
free(m_buffer);
|
||||
}
|
||||
|
||||
sample_t* AUD_Buffer::getBuffer()
|
||||
sample_t* AUD_Buffer::getBuffer() const
|
||||
{
|
||||
return (sample_t*) AUD_ALIGN(m_buffer);
|
||||
}
|
||||
|
||||
int AUD_Buffer::getSize()
|
||||
int AUD_Buffer::getSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void AUD_Buffer::resize(int size, bool keep)
|
||||
{
|
||||
data_t* buffer = (data_t*) malloc(size+16); AUD_NEW("buffer")
|
||||
|
||||
// copy old data over if wanted
|
||||
if(keep)
|
||||
{
|
||||
data_t* buffer = (data_t*) malloc(size + 16);
|
||||
|
||||
memcpy(AUD_ALIGN(buffer), AUD_ALIGN(m_buffer), AUD_MIN(size, m_size));
|
||||
|
||||
free(m_buffer); AUD_DELETE("buffer")
|
||||
free(m_buffer);
|
||||
m_buffer = buffer;
|
||||
}
|
||||
else
|
||||
m_buffer = (data_t*) realloc(m_buffer, size + 16);
|
||||
|
||||
m_buffer = buffer;
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,10 @@ private:
|
||||
/// The pointer to the buffer memory.
|
||||
data_t* m_buffer;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_Buffer(const AUD_Buffer&);
|
||||
AUD_Buffer& operator=(const AUD_Buffer&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new buffer.
|
||||
@@ -56,12 +60,12 @@ public:
|
||||
/**
|
||||
* Returns the pointer to the buffer in memory.
|
||||
*/
|
||||
sample_t* getBuffer();
|
||||
sample_t* getBuffer() const;
|
||||
|
||||
/**
|
||||
* Returns the size of the buffer in bytes.
|
||||
*/
|
||||
int getSize();
|
||||
int getSize() const;
|
||||
|
||||
/**
|
||||
* Resizes the buffer.
|
||||
|
||||
@@ -28,53 +28,36 @@
|
||||
#include "AUD_Space.h"
|
||||
|
||||
AUD_BufferReader::AUD_BufferReader(AUD_Reference<AUD_Buffer> buffer,
|
||||
AUD_Specs specs)
|
||||
AUD_Specs specs) :
|
||||
m_position(0), m_buffer(buffer), m_specs(specs)
|
||||
{
|
||||
m_position = 0;
|
||||
m_buffer = buffer;
|
||||
m_specs = specs;
|
||||
}
|
||||
|
||||
bool AUD_BufferReader::isSeekable()
|
||||
bool AUD_BufferReader::isSeekable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void AUD_BufferReader::seek(int position)
|
||||
{
|
||||
if(position < 0)
|
||||
m_position = 0;
|
||||
else if(position > m_buffer.get()->getSize() / AUD_SAMPLE_SIZE(m_specs))
|
||||
m_position = m_buffer.get()->getSize() / AUD_SAMPLE_SIZE(m_specs);
|
||||
else
|
||||
m_position = position;
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
int AUD_BufferReader::getLength()
|
||||
int AUD_BufferReader::getLength() const
|
||||
{
|
||||
return m_buffer.get()->getSize()/AUD_SAMPLE_SIZE(m_specs);
|
||||
return m_buffer.get()->getSize() / AUD_SAMPLE_SIZE(m_specs);
|
||||
}
|
||||
|
||||
int AUD_BufferReader::getPosition()
|
||||
int AUD_BufferReader::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
AUD_Specs AUD_BufferReader::getSpecs()
|
||||
AUD_Specs AUD_BufferReader::getSpecs() const
|
||||
{
|
||||
return m_specs;
|
||||
}
|
||||
|
||||
AUD_ReaderType AUD_BufferReader::getType()
|
||||
{
|
||||
return AUD_TYPE_BUFFER;
|
||||
}
|
||||
|
||||
bool AUD_BufferReader::notify(AUD_Message &message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void AUD_BufferReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
int sample_size = AUD_SAMPLE_SIZE(m_specs);
|
||||
|
||||
@@ -53,6 +53,10 @@ private:
|
||||
*/
|
||||
AUD_Specs m_specs;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_BufferReader(const AUD_BufferReader&);
|
||||
AUD_BufferReader& operator=(const AUD_BufferReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new buffer reader.
|
||||
@@ -61,13 +65,11 @@ public:
|
||||
*/
|
||||
AUD_BufferReader(AUD_Reference<AUD_Buffer> buffer, AUD_Specs specs);
|
||||
|
||||
virtual bool isSeekable();
|
||||
virtual bool isSeekable() const;
|
||||
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 int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -23,11 +23,18 @@
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
#include "AUD_PyAPI.h"
|
||||
|
||||
Device* g_device;
|
||||
bool g_pyinitialized = false;
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
#ifdef WITH_FFMPEG
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
// needed for INT64_C
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
@@ -51,9 +58,9 @@
|
||||
#include "AUD_ChannelMapperFactory.h"
|
||||
#include "AUD_Buffer.h"
|
||||
#include "AUD_ReadDevice.h"
|
||||
#include "AUD_SourceCaps.h"
|
||||
#include "AUD_IReader.h"
|
||||
#include "AUD_SequencerFactory.h"
|
||||
#include "AUD_SilenceFactory.h"
|
||||
|
||||
#ifdef WITH_SDL
|
||||
#include "AUD_SDLDevice.h"
|
||||
@@ -78,6 +85,7 @@ extern "C" {
|
||||
|
||||
typedef AUD_IFactory AUD_Sound;
|
||||
typedef AUD_ReadDevice AUD_Device;
|
||||
typedef AUD_Handle AUD_Channel;
|
||||
|
||||
#define AUD_CAPI_IMPLEMENTATION
|
||||
#include "AUD_C-API.h"
|
||||
@@ -123,7 +131,7 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize)
|
||||
#endif
|
||||
#ifdef WITH_JACK
|
||||
case AUD_JACK_DEVICE:
|
||||
dev = new AUD_JackDevice(specs, buffersize);
|
||||
dev = new AUD_JackDevice("Blender", specs, buffersize);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -131,12 +139,22 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize)
|
||||
}
|
||||
|
||||
AUD_device = dev;
|
||||
if(AUD_device->checkCapability(AUD_CAPS_3D_DEVICE))
|
||||
AUD_3ddevice = dynamic_cast<AUD_I3DDevice*>(AUD_device);
|
||||
AUD_3ddevice = dynamic_cast<AUD_I3DDevice*>(AUD_device);
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
if(g_pyinitialized)
|
||||
{
|
||||
g_device = (Device*)Device_empty();
|
||||
if(g_device != NULL)
|
||||
{
|
||||
g_device->device = dev;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -160,13 +178,55 @@ int* AUD_enumDevices()
|
||||
|
||||
void AUD_exit()
|
||||
{
|
||||
#ifdef WITH_PYTHON
|
||||
if(g_device)
|
||||
{
|
||||
Py_XDECREF(g_device);
|
||||
g_device = NULL;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(AUD_device)
|
||||
delete AUD_device;
|
||||
AUD_device = NULL;
|
||||
AUD_3ddevice = NULL;
|
||||
}
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
static PyObject* AUD_getCDevice(PyObject* self)
|
||||
{
|
||||
if(g_device)
|
||||
{
|
||||
Py_INCREF(g_device);
|
||||
return (PyObject*)g_device;
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyMethodDef meth_getcdevice[] = {{ "device", (PyCFunction)AUD_getCDevice, METH_NOARGS,
|
||||
"device()\n\n"
|
||||
"Returns the application's :class:`Device`.\n\n"
|
||||
":return: The application's :class:`Device`.\n"
|
||||
":rtype: :class:`Device`"}};
|
||||
|
||||
PyObject* AUD_initPython()
|
||||
{
|
||||
PyObject* module = PyInit_aud();
|
||||
PyModule_AddObject(module, "device", (PyObject *)PyCFunction_New(meth_getcdevice, NULL));
|
||||
PyDict_SetItemString(PySys_GetObject("modules"), "aud", module);
|
||||
if(AUD_device)
|
||||
{
|
||||
delete AUD_device;
|
||||
AUD_device = NULL;
|
||||
AUD_3ddevice = NULL;
|
||||
g_device = (Device*)Device_empty();
|
||||
if(g_device != NULL)
|
||||
{
|
||||
g_device->device = AUD_device;
|
||||
}
|
||||
}
|
||||
g_pyinitialized = true;
|
||||
|
||||
return module;
|
||||
}
|
||||
#endif
|
||||
|
||||
void AUD_lock()
|
||||
{
|
||||
@@ -223,7 +283,7 @@ AUD_Sound* AUD_bufferSound(AUD_Sound* sound)
|
||||
{
|
||||
return new AUD_StreamBufferFactory(sound);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -237,7 +297,7 @@ AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay)
|
||||
{
|
||||
return new AUD_DelayFactory(sound, delay);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -251,7 +311,7 @@ AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end)
|
||||
{
|
||||
return new AUD_LimiterFactory(sound, start, end);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -265,7 +325,7 @@ AUD_Sound* AUD_pingpongSound(AUD_Sound* sound)
|
||||
{
|
||||
return new AUD_PingPongFactory(sound);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -279,26 +339,21 @@ AUD_Sound* AUD_loopSound(AUD_Sound* sound)
|
||||
{
|
||||
return new AUD_LoopFactory(sound);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int AUD_setLoop(AUD_Handle* handle, int loops, float time)
|
||||
int AUD_setLoop(AUD_Channel* handle, int loops)
|
||||
{
|
||||
if(handle)
|
||||
{
|
||||
AUD_Message message;
|
||||
message.type = AUD_MSG_LOOP;
|
||||
message.loopcount = loops;
|
||||
message.time = time;
|
||||
|
||||
try
|
||||
{
|
||||
return AUD_device->sendMessage(handle, message);
|
||||
return AUD_device->setLoopCount(handle, loops);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -313,7 +368,7 @@ AUD_Sound* AUD_rectifySound(AUD_Sound* sound)
|
||||
{
|
||||
return new AUD_RectifyFactory(sound);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -325,7 +380,7 @@ void AUD_unload(AUD_Sound* sound)
|
||||
delete sound;
|
||||
}
|
||||
|
||||
AUD_Handle* AUD_play(AUD_Sound* sound, int keep)
|
||||
AUD_Channel* AUD_play(AUD_Sound* sound, int keep)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(sound);
|
||||
@@ -333,140 +388,311 @@ AUD_Handle* AUD_play(AUD_Sound* sound, int keep)
|
||||
{
|
||||
return AUD_device->play(sound, keep);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int AUD_pause(AUD_Handle* handle)
|
||||
int AUD_pause(AUD_Channel* handle)
|
||||
{
|
||||
assert(AUD_device);
|
||||
return AUD_device->pause(handle);
|
||||
}
|
||||
|
||||
int AUD_resume(AUD_Handle* handle)
|
||||
int AUD_resume(AUD_Channel* handle)
|
||||
{
|
||||
assert(AUD_device);
|
||||
return AUD_device->resume(handle);
|
||||
}
|
||||
|
||||
int AUD_stop(AUD_Handle* handle)
|
||||
int AUD_stop(AUD_Channel* handle)
|
||||
{
|
||||
if(AUD_device)
|
||||
return AUD_device->stop(handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setKeep(AUD_Handle* handle, int keep)
|
||||
int AUD_setKeep(AUD_Channel* handle, int keep)
|
||||
{
|
||||
assert(AUD_device);
|
||||
return AUD_device->setKeep(handle, keep);
|
||||
}
|
||||
|
||||
int AUD_seek(AUD_Handle* handle, float seekTo)
|
||||
int AUD_seek(AUD_Channel* handle, float seekTo)
|
||||
{
|
||||
assert(AUD_device);
|
||||
return AUD_device->seek(handle, seekTo);
|
||||
}
|
||||
|
||||
float AUD_getPosition(AUD_Handle* handle)
|
||||
float AUD_getPosition(AUD_Channel* handle)
|
||||
{
|
||||
assert(AUD_device);
|
||||
return AUD_device->getPosition(handle);
|
||||
}
|
||||
|
||||
AUD_Status AUD_getStatus(AUD_Handle* handle)
|
||||
AUD_Status AUD_getStatus(AUD_Channel* handle)
|
||||
{
|
||||
assert(AUD_device);
|
||||
return AUD_device->getStatus(handle);
|
||||
}
|
||||
|
||||
AUD_Handle* AUD_play3D(AUD_Sound* sound, int keep)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(sound);
|
||||
|
||||
try
|
||||
{
|
||||
if(AUD_3ddevice)
|
||||
return AUD_3ddevice->play3D(sound, keep);
|
||||
else
|
||||
return AUD_device->play(sound, keep);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int AUD_updateListener(AUD_3DData* data)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(data);
|
||||
|
||||
try
|
||||
{
|
||||
if(AUD_3ddevice)
|
||||
return AUD_3ddevice->updateListener(*data);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_set3DSetting(AUD_3DSetting setting, float value)
|
||||
int AUD_setListenerLocation(const float* location)
|
||||
{
|
||||
assert(AUD_device);
|
||||
|
||||
try
|
||||
{
|
||||
if(AUD_3ddevice)
|
||||
return AUD_3ddevice->setSetting(setting, value);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
AUD_Vector3 v(location[0], location[1], location[2]);
|
||||
AUD_3ddevice->setListenerLocation(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
float AUD_get3DSetting(AUD_3DSetting setting)
|
||||
int AUD_setListenerVelocity(const float* velocity)
|
||||
{
|
||||
assert(AUD_device);
|
||||
|
||||
try
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
if(AUD_3ddevice)
|
||||
return AUD_3ddevice->getSetting(setting);
|
||||
AUD_Vector3 v(velocity[0], velocity[1], velocity[2]);
|
||||
AUD_3ddevice->setListenerVelocity(v);
|
||||
return true;
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
{
|
||||
}
|
||||
return 0.0f;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_update3DSource(AUD_Handle* handle, AUD_3DData* data)
|
||||
int AUD_setListenerOrientation(const float* orientation)
|
||||
{
|
||||
assert(AUD_device);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
AUD_Quaternion q(orientation[0], orientation[1], orientation[2], orientation[3]);
|
||||
AUD_3ddevice->setListenerOrientation(q);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setSpeedOfSound(float speed)
|
||||
{
|
||||
assert(AUD_device);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
AUD_3ddevice->setSpeedOfSound(speed);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setDopplerFactor(float factor)
|
||||
{
|
||||
assert(AUD_device);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
AUD_3ddevice->setDopplerFactor(factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setDistanceModel(AUD_DistanceModel model)
|
||||
{
|
||||
assert(AUD_device);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
AUD_3ddevice->setDistanceModel(model);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setSourceLocation(AUD_Channel* handle, const float* location)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(handle);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
AUD_Vector3 v(location[0], location[1], location[2]);
|
||||
return AUD_3ddevice->setSourceLocation(handle, v);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(handle);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
AUD_Vector3 v(velocity[0], velocity[1], velocity[2]);
|
||||
return AUD_3ddevice->setSourceVelocity(handle, v);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(handle);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
AUD_Quaternion q(orientation[0], orientation[1], orientation[2], orientation[3]);
|
||||
return AUD_3ddevice->setSourceOrientation(handle, q);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setRelative(AUD_Channel* handle, int relative)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(handle);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
return AUD_3ddevice->setRelative(handle, relative);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setVolumeMaximum(AUD_Channel* handle, float volume)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(handle);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
return AUD_3ddevice->setVolumeMaximum(handle, volume);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setVolumeMinimum(AUD_Channel* handle, float volume)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(handle);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
return AUD_3ddevice->setVolumeMinimum(handle, volume);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setDistanceMaximum(AUD_Channel* handle, float distance)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(handle);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
return AUD_3ddevice->setDistanceMaximum(handle, distance);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setDistanceReference(AUD_Channel* handle, float distance)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(handle);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
return AUD_3ddevice->setDistanceReference(handle, distance);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setAttenuation(AUD_Channel* handle, float factor)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(handle);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
return AUD_3ddevice->setAttenuation(handle, factor);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setConeAngleOuter(AUD_Channel* handle, float angle)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(handle);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
return AUD_3ddevice->setConeAngleOuter(handle, angle);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setConeAngleInner(AUD_Channel* handle, float angle)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(handle);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
return AUD_3ddevice->setConeAngleInner(handle, angle);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(handle);
|
||||
|
||||
if(AUD_3ddevice)
|
||||
{
|
||||
return AUD_3ddevice->setConeVolumeOuter(handle, volume);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setSoundVolume(AUD_Channel* handle, float volume)
|
||||
{
|
||||
if(handle)
|
||||
{
|
||||
assert(AUD_device);
|
||||
assert(data);
|
||||
|
||||
try
|
||||
{
|
||||
if(AUD_3ddevice)
|
||||
return AUD_3ddevice->updateSource(handle, *data);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
{
|
||||
return AUD_device->setVolume(handle, volume);
|
||||
}
|
||||
catch(AUD_Exception&) {}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_set3DSourceSetting(AUD_Handle* handle,
|
||||
AUD_3DSourceSetting setting, float value)
|
||||
int AUD_setSoundPitch(AUD_Channel* handle, float pitch)
|
||||
{
|
||||
if(handle)
|
||||
{
|
||||
@@ -474,66 +700,9 @@ int AUD_set3DSourceSetting(AUD_Handle* handle,
|
||||
|
||||
try
|
||||
{
|
||||
if(AUD_3ddevice)
|
||||
return AUD_3ddevice->setSourceSetting(handle, setting, value);
|
||||
return AUD_device->setPitch(handle, pitch);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
float AUD_get3DSourceSetting(AUD_Handle* handle, AUD_3DSourceSetting setting)
|
||||
{
|
||||
if(handle)
|
||||
{
|
||||
assert(AUD_device);
|
||||
|
||||
try
|
||||
{
|
||||
if(AUD_3ddevice)
|
||||
return AUD_3ddevice->getSourceSetting(handle, setting);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
int AUD_setSoundVolume(AUD_Handle* handle, float volume)
|
||||
{
|
||||
if(handle)
|
||||
{
|
||||
assert(AUD_device);
|
||||
AUD_SourceCaps caps;
|
||||
caps.handle = handle;
|
||||
caps.value = volume;
|
||||
|
||||
try
|
||||
{
|
||||
return AUD_device->setCapability(AUD_CAPS_SOURCE_VOLUME, &caps);
|
||||
}
|
||||
catch(AUD_Exception) {}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setSoundPitch(AUD_Handle* handle, float pitch)
|
||||
{
|
||||
if(handle)
|
||||
{
|
||||
assert(AUD_device);
|
||||
AUD_SourceCaps caps;
|
||||
caps.handle = handle;
|
||||
caps.value = pitch;
|
||||
|
||||
try
|
||||
{
|
||||
return AUD_device->setCapability(AUD_CAPS_SOURCE_PITCH, &caps);
|
||||
}
|
||||
catch(AUD_Exception) {}
|
||||
catch(AUD_Exception&) {}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -544,24 +713,24 @@ AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs)
|
||||
{
|
||||
return new AUD_ReadDevice(specs);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
|
||||
AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek)
|
||||
{
|
||||
assert(device);
|
||||
assert(sound);
|
||||
|
||||
try
|
||||
{
|
||||
AUD_Handle* handle = device->play(sound);
|
||||
AUD_Channel* handle = device->play(sound);
|
||||
device->seek(handle, seek);
|
||||
return handle;
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -573,28 +742,26 @@ int AUD_setDeviceVolume(AUD_Device* device, float volume)
|
||||
|
||||
try
|
||||
{
|
||||
return device->setCapability(AUD_CAPS_VOLUME, &volume);
|
||||
device->setVolume(volume);
|
||||
return true;
|
||||
}
|
||||
catch(AUD_Exception) {}
|
||||
catch(AUD_Exception&) {}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Handle* handle,
|
||||
int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Channel* handle,
|
||||
float volume)
|
||||
{
|
||||
if(handle)
|
||||
{
|
||||
assert(device);
|
||||
AUD_SourceCaps caps;
|
||||
caps.handle = handle;
|
||||
caps.value = volume;
|
||||
|
||||
try
|
||||
{
|
||||
return device->setCapability(AUD_CAPS_SOURCE_VOLUME, &caps);
|
||||
return device->setVolume(handle, volume);
|
||||
}
|
||||
catch(AUD_Exception) {}
|
||||
catch(AUD_Exception&) {}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -608,7 +775,7 @@ int AUD_readDevice(AUD_Device* device, data_t* buffer, int length)
|
||||
{
|
||||
return device->read(buffer, length);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -622,7 +789,7 @@ void AUD_closeReadDevice(AUD_Device* device)
|
||||
{
|
||||
delete device;
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -679,6 +846,32 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high,
|
||||
return result;
|
||||
}
|
||||
|
||||
static void pauseSound(AUD_Channel* handle)
|
||||
{
|
||||
assert(AUD_device);
|
||||
|
||||
AUD_device->pause(handle);
|
||||
}
|
||||
|
||||
AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds)
|
||||
{
|
||||
assert(AUD_device);
|
||||
|
||||
AUD_SilenceFactory silence;
|
||||
AUD_LimiterFactory limiter(&silence, 0, seconds);
|
||||
|
||||
try
|
||||
{
|
||||
AUD_Channel* channel = AUD_device->play(&limiter);
|
||||
AUD_device->setStopCallback(channel, (stopCallback)pauseSound, handle);
|
||||
return channel;
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume)
|
||||
{
|
||||
/* AUD_XXX should be this: but AUD_createSequencer is called before the device
|
||||
@@ -721,23 +914,16 @@ void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, char mut
|
||||
|
||||
int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
|
||||
{
|
||||
AUD_IReader* reader = sound->createReader();
|
||||
AUD_DeviceSpecs specs;
|
||||
sample_t* buf;
|
||||
|
||||
specs.specs = reader->getSpecs();
|
||||
specs.rate = AUD_RATE_INVALID;
|
||||
specs.channels = AUD_CHANNELS_MONO;
|
||||
specs.format = AUD_FORMAT_FLOAT32;
|
||||
specs.format = AUD_FORMAT_INVALID;
|
||||
|
||||
AUD_ChannelMapperFactory mapper(reader, specs);
|
||||
AUD_ChannelMapperFactory mapper(sound, specs);
|
||||
|
||||
if(!reader || reader->getType() != AUD_TYPE_BUFFER)
|
||||
return -1;
|
||||
|
||||
reader = mapper.createReader();
|
||||
|
||||
if(!reader)
|
||||
return -1;
|
||||
AUD_IReader* reader = mapper.createReader();
|
||||
|
||||
int len = reader->getLength();
|
||||
float samplejump = (float)len / (float)length;
|
||||
@@ -766,7 +952,7 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length)
|
||||
}
|
||||
}
|
||||
|
||||
delete reader; AUD_DELETE("reader")
|
||||
delete reader;
|
||||
|
||||
return length;
|
||||
}
|
||||
@@ -789,7 +975,7 @@ void AUD_stopPlayback()
|
||||
#endif
|
||||
}
|
||||
|
||||
void AUD_seekSequencer(AUD_Handle* handle, float time)
|
||||
void AUD_seekSequencer(AUD_Channel* handle, float time)
|
||||
{
|
||||
#ifdef WITH_JACK
|
||||
AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
|
||||
@@ -802,7 +988,7 @@ void AUD_seekSequencer(AUD_Handle* handle, float time)
|
||||
}
|
||||
}
|
||||
|
||||
float AUD_getSequencerPosition(AUD_Handle* handle)
|
||||
float AUD_getSequencerPosition(AUD_Channel* handle)
|
||||
{
|
||||
#ifdef WITH_JACK
|
||||
AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device);
|
||||
@@ -833,16 +1019,3 @@ int AUD_doesPlayback()
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef AUD_DEBUG_MEMORY
|
||||
int AUD_References(int count, const char* text)
|
||||
{
|
||||
static int m_count = 0;
|
||||
m_count += count;
|
||||
if(count > 0)
|
||||
printf("+%s\n", text);
|
||||
if(count < 0)
|
||||
printf("-%s\n", text);
|
||||
return m_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
#ifndef AUD_CAPI
|
||||
#define AUD_CAPI
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
#include "Python.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -48,7 +52,7 @@ typedef struct
|
||||
|
||||
#ifndef AUD_CAPI_IMPLEMENTATION
|
||||
typedef void AUD_Sound;
|
||||
typedef void AUD_Handle;
|
||||
typedef void AUD_Channel;
|
||||
typedef void AUD_Device;
|
||||
typedef void AUD_SequencerEntry;
|
||||
typedef float (*AUD_volumeFunction)(void*, void*, float);
|
||||
@@ -80,6 +84,13 @@ extern int* AUD_enumDevices();
|
||||
*/
|
||||
extern void AUD_exit();
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
/**
|
||||
* Initalizes the Python module.
|
||||
*/
|
||||
extern PyObject* AUD_initPython();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Locks the playback device.
|
||||
*/
|
||||
@@ -154,10 +165,9 @@ extern AUD_Sound* AUD_loopSound(AUD_Sound* sound);
|
||||
* Sets a remaining loop count of a looping sound that currently plays.
|
||||
* \param handle The playback handle.
|
||||
* \param loops The count of remaining loops, -1 for infinity.
|
||||
* \param time The time after which playback should stop, -1 for infinity.
|
||||
* \return Whether the handle is valid.
|
||||
*/
|
||||
extern int AUD_setLoop(AUD_Handle* handle, int loops, float time);
|
||||
extern int AUD_setLoop(AUD_Channel* handle, int loops);
|
||||
|
||||
/**
|
||||
* Rectifies a sound.
|
||||
@@ -179,28 +189,28 @@ extern void AUD_unload(AUD_Sound* sound);
|
||||
* paused when its end has been reached.
|
||||
* \return A handle to the played back sound.
|
||||
*/
|
||||
extern AUD_Handle* AUD_play(AUD_Sound* sound, int keep);
|
||||
extern AUD_Channel* AUD_play(AUD_Sound* sound, int keep);
|
||||
|
||||
/**
|
||||
* Pauses a played back sound.
|
||||
* \param handle The handle to the sound.
|
||||
* \return Whether the handle has been playing or not.
|
||||
*/
|
||||
extern int AUD_pause(AUD_Handle* handle);
|
||||
extern int AUD_pause(AUD_Channel* handle);
|
||||
|
||||
/**
|
||||
* Resumes a paused sound.
|
||||
* \param handle The handle to the sound.
|
||||
* \return Whether the handle has been paused or not.
|
||||
*/
|
||||
extern int AUD_resume(AUD_Handle* handle);
|
||||
extern int AUD_resume(AUD_Channel* handle);
|
||||
|
||||
/**
|
||||
* Stops a playing or paused sound.
|
||||
* \param handle The handle to the sound.
|
||||
* \return Whether the handle has been valid or not.
|
||||
*/
|
||||
extern int AUD_stop(AUD_Handle* handle);
|
||||
extern int AUD_stop(AUD_Channel* handle);
|
||||
|
||||
/**
|
||||
* Sets the end behaviour of a playing or paused sound.
|
||||
@@ -209,7 +219,7 @@ extern int AUD_stop(AUD_Handle* handle);
|
||||
* paused when its end has been reached.
|
||||
* \return Whether the handle has been valid or not.
|
||||
*/
|
||||
extern int AUD_setKeep(AUD_Handle* handle, int keep);
|
||||
extern int AUD_setKeep(AUD_Channel* handle, int keep);
|
||||
|
||||
/**
|
||||
* Seeks a playing or paused sound.
|
||||
@@ -217,7 +227,7 @@ extern int AUD_setKeep(AUD_Handle* handle, int keep);
|
||||
* \param seekTo From where the sound file should be played back in seconds.
|
||||
* \return Whether the handle has been valid or not.
|
||||
*/
|
||||
extern int AUD_seek(AUD_Handle* handle, float seekTo);
|
||||
extern int AUD_seek(AUD_Channel* handle, float seekTo);
|
||||
|
||||
/**
|
||||
* Retrieves the playback position of a handle.
|
||||
@@ -225,74 +235,155 @@ extern int AUD_seek(AUD_Handle* handle, float seekTo);
|
||||
* \return The current playback position in seconds or 0.0 if the handle is
|
||||
* invalid.
|
||||
*/
|
||||
extern float AUD_getPosition(AUD_Handle* handle);
|
||||
extern float AUD_getPosition(AUD_Channel* handle);
|
||||
|
||||
/**
|
||||
* Returns the status of a playing, paused or stopped sound.
|
||||
* \param handle The handle to the sound.
|
||||
* \return The status of the sound behind the handle.
|
||||
*/
|
||||
extern AUD_Status AUD_getStatus(AUD_Handle* handle);
|
||||
extern AUD_Status AUD_getStatus(AUD_Channel* handle);
|
||||
|
||||
/**
|
||||
* Plays a 3D sound.
|
||||
* \param sound The handle of the sound file.
|
||||
* \param keep When keep is true the sound source will not be deleted but set to
|
||||
* paused when its end has been reached.
|
||||
* \return A handle to the played back sound.
|
||||
* \note The factory must provide a mono (single channel) source and the device
|
||||
* must support 3D audio, otherwise the sound is played back normally.
|
||||
* Sets the listener location.
|
||||
* \param location The new location.
|
||||
*/
|
||||
extern AUD_Handle* AUD_play3D(AUD_Sound* sound, int keep);
|
||||
extern int AUD_setListenerLocation(const float* location);
|
||||
|
||||
/**
|
||||
* Updates the listener 3D data.
|
||||
* \param data The 3D data.
|
||||
* Sets the listener velocity.
|
||||
* \param velocity The new velocity.
|
||||
*/
|
||||
extern int AUD_setListenerVelocity(const float* velocity);
|
||||
|
||||
/**
|
||||
* Sets the listener orientation.
|
||||
* \param orientation The new orientation as quaternion.
|
||||
*/
|
||||
extern int AUD_setListenerOrientation(const float* orientation);
|
||||
|
||||
/**
|
||||
* Sets the speed of sound.
|
||||
* This value is needed for doppler effect calculation.
|
||||
* \param speed The new speed of sound.
|
||||
*/
|
||||
extern int AUD_setSpeedOfSound(float speed);
|
||||
|
||||
/**
|
||||
* Sets the doppler factor.
|
||||
* This value is a scaling factor for the velocity vectors of sources and
|
||||
* listener which is used while calculating the doppler effect.
|
||||
* \param factor The new doppler factor.
|
||||
*/
|
||||
extern int AUD_setDopplerFactor(float factor);
|
||||
|
||||
/**
|
||||
* Sets the distance model.
|
||||
* \param model distance model.
|
||||
*/
|
||||
extern int AUD_setDistanceModel(AUD_DistanceModel model);
|
||||
|
||||
/**
|
||||
* Sets the location of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param location The new location.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_updateListener(AUD_3DData* data);
|
||||
extern int AUD_setSourceLocation(AUD_Channel* handle, const float* location);
|
||||
|
||||
/**
|
||||
* Sets a 3D device setting.
|
||||
* \param setting The setting type.
|
||||
* \param value The new setting value.
|
||||
* Sets the velocity of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param velocity The new velocity.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_set3DSetting(AUD_3DSetting setting, float value);
|
||||
extern int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity);
|
||||
|
||||
/**
|
||||
* Retrieves a 3D device setting.
|
||||
* \param setting The setting type.
|
||||
* \return The setting value.
|
||||
*/
|
||||
extern float AUD_get3DSetting(AUD_3DSetting setting);
|
||||
|
||||
/**
|
||||
* Updates a listeners 3D data.
|
||||
* \param handle The source handle.
|
||||
* \param data The 3D data.
|
||||
* Sets the orientation of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param orientation The new orientation as quaternion.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_update3DSource(AUD_Handle* handle, AUD_3DData* data);
|
||||
extern int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation);
|
||||
|
||||
/**
|
||||
* Sets a 3D source setting.
|
||||
* \param handle The source handle.
|
||||
* \param setting The setting type.
|
||||
* \param value The new setting value.
|
||||
* Sets whether the source location, velocity and orientation are relative
|
||||
* to the listener.
|
||||
* \param handle The handle of the source.
|
||||
* \param relative Whether the source is relative.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_set3DSourceSetting(AUD_Handle* handle,
|
||||
AUD_3DSourceSetting setting, float value);
|
||||
extern int AUD_setRelative(AUD_Channel* handle, int relative);
|
||||
|
||||
/**
|
||||
* Retrieves a 3D source setting.
|
||||
* \param handle The source handle.
|
||||
* \param setting The setting type.
|
||||
* \return The setting value.
|
||||
* Sets the maximum volume of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param volume The new maximum volume.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern float AUD_get3DSourceSetting(AUD_Handle* handle,
|
||||
AUD_3DSourceSetting setting);
|
||||
extern int AUD_setVolumeMaximum(AUD_Channel* handle, float volume);
|
||||
|
||||
/**
|
||||
* Sets the minimum volume of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param volume The new minimum volume.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setVolumeMinimum(AUD_Channel* handle, float volume);
|
||||
|
||||
/**
|
||||
* Sets the maximum distance of a source.
|
||||
* If a source is further away from the reader than this distance, the
|
||||
* volume will automatically be set to 0.
|
||||
* \param handle The handle of the source.
|
||||
* \param distance The new maximum distance.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setDistanceMaximum(AUD_Channel* handle, float distance);
|
||||
|
||||
/**
|
||||
* Sets the reference distance of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param distance The new reference distance.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setDistanceReference(AUD_Channel* handle, float distance);
|
||||
|
||||
/**
|
||||
* Sets the attenuation of a source.
|
||||
* This value is used for distance calculation.
|
||||
* \param handle The handle of the source.
|
||||
* \param factor The new attenuation.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setAttenuation(AUD_Channel* handle, float factor);
|
||||
|
||||
/**
|
||||
* Sets the outer angle of the cone of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param angle The new outer angle of the cone.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setConeAngleOuter(AUD_Channel* handle, float angle);
|
||||
|
||||
/**
|
||||
* Sets the inner angle of the cone of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param angle The new inner angle of the cone.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setConeAngleInner(AUD_Channel* handle, float angle);
|
||||
|
||||
/**
|
||||
* Sets the outer volume of the cone of a source.
|
||||
* The volume between inner and outer angle is interpolated between inner
|
||||
* volume and this value.
|
||||
* \param handle The handle of the source.
|
||||
* \param volume The new outer volume of the cone.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume);
|
||||
|
||||
/**
|
||||
* Sets the volume of a played back sound.
|
||||
@@ -300,7 +391,7 @@ extern float AUD_get3DSourceSetting(AUD_Handle* handle,
|
||||
* \param volume The new volume, must be between 0.0 and 1.0.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setSoundVolume(AUD_Handle* handle, float volume);
|
||||
extern int AUD_setSoundVolume(AUD_Channel* handle, float volume);
|
||||
|
||||
/**
|
||||
* Sets the pitch of a played back sound.
|
||||
@@ -308,7 +399,7 @@ extern int AUD_setSoundVolume(AUD_Handle* handle, float volume);
|
||||
* \param pitch The new pitch.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setSoundPitch(AUD_Handle* handle, float pitch);
|
||||
extern int AUD_setSoundPitch(AUD_Channel* handle, float pitch);
|
||||
|
||||
/**
|
||||
* Opens a read device, with which audio data can be read.
|
||||
@@ -332,7 +423,7 @@ extern int AUD_setDeviceVolume(AUD_Device* device, float volume);
|
||||
* \param seek The position where the sound should be seeked to.
|
||||
* \return A handle to the played back sound.
|
||||
*/
|
||||
extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek);
|
||||
extern AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek);
|
||||
|
||||
/**
|
||||
* Sets the volume of a played back sound of a read device.
|
||||
@@ -342,7 +433,7 @@ extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float se
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setDeviceSoundVolume(AUD_Device* device,
|
||||
AUD_Handle* handle,
|
||||
AUD_Channel* handle,
|
||||
float volume);
|
||||
|
||||
/**
|
||||
@@ -372,6 +463,14 @@ extern float* AUD_readSoundBuffer(const char* filename, float low, float high,
|
||||
float sthreshold, int samplerate,
|
||||
int* length);
|
||||
|
||||
/**
|
||||
* Pauses a playing sound after a specific amount of time.
|
||||
* \param handle The handle to the sound.
|
||||
* \param time The time in seconds.
|
||||
* \return The silence handle.
|
||||
*/
|
||||
extern AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds);
|
||||
|
||||
extern AUD_Sound* AUD_createSequencer(void* data, AUD_volumeFunction volume);
|
||||
|
||||
extern void AUD_destroySequencer(AUD_Sound* sequencer);
|
||||
@@ -393,9 +492,9 @@ extern void AUD_startPlayback();
|
||||
|
||||
extern void AUD_stopPlayback();
|
||||
|
||||
extern void AUD_seekSequencer(AUD_Handle* handle, float time);
|
||||
extern void AUD_seekSequencer(AUD_Channel* handle, float time);
|
||||
|
||||
extern float AUD_getSequencerPosition(AUD_Handle* handle);
|
||||
extern float AUD_getSequencerPosition(AUD_Channel* handle);
|
||||
|
||||
#ifdef WITH_JACK
|
||||
extern void AUD_setSyncCallback(AUD_syncFunction function, void* data);
|
||||
|
||||
@@ -28,13 +28,6 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IReader* reader,
|
||||
AUD_DeviceSpecs specs) :
|
||||
AUD_MixerFactory(reader, specs)
|
||||
{
|
||||
memset(m_mapping, 0, sizeof(m_mapping));
|
||||
}
|
||||
|
||||
AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IFactory* factory,
|
||||
AUD_DeviceSpecs specs) :
|
||||
AUD_MixerFactory(factory, specs)
|
||||
@@ -42,12 +35,6 @@ AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IFactory* factory,
|
||||
memset(m_mapping, 0, sizeof(m_mapping));
|
||||
}
|
||||
|
||||
AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_DeviceSpecs specs) :
|
||||
AUD_MixerFactory(specs)
|
||||
{
|
||||
memset(m_mapping, 0, sizeof(m_mapping));
|
||||
}
|
||||
|
||||
AUD_ChannelMapperFactory::~AUD_ChannelMapperFactory()
|
||||
{
|
||||
for(int i = 1; i < 10; i++)
|
||||
@@ -72,12 +59,12 @@ float** AUD_ChannelMapperFactory::getMapping(int ic)
|
||||
{
|
||||
int channels = m_specs.channels;
|
||||
|
||||
m_mapping[ic] = new float*[channels+1]; AUD_NEW("mapping")
|
||||
m_mapping[ic] = new float*[channels+1];
|
||||
m_mapping[ic][channels] = 0;
|
||||
|
||||
for(int i = 0; i < channels; i++)
|
||||
{
|
||||
m_mapping[ic][i] = new float[ic+1]; AUD_NEW("mapping")
|
||||
m_mapping[ic][i] = new float[ic+1];
|
||||
for(int j = 0; j <= ic; j++)
|
||||
m_mapping[ic][i][j] = ((i == j) || (channels == 1) ||
|
||||
(ic == 0)) ? 1.0f : 0.0f;
|
||||
@@ -99,27 +86,21 @@ void AUD_ChannelMapperFactory::deleteMapping(int ic)
|
||||
{
|
||||
if(m_mapping[ic][i] != 0)
|
||||
{
|
||||
delete[] m_mapping[ic][i]; AUD_DELETE("mapping")
|
||||
delete[] m_mapping[ic][i];
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
delete[] m_mapping[ic]; AUD_DELETE("mapping")
|
||||
delete[] m_mapping[ic];
|
||||
m_mapping[ic] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_ChannelMapperFactory::createReader()
|
||||
AUD_IReader* AUD_ChannelMapperFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
int ic = reader->getSpecs().channels;
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
int ic = reader->getSpecs().channels;
|
||||
|
||||
reader = new AUD_ChannelMapperReader(reader, getMapping(ic));
|
||||
AUD_NEW("reader")
|
||||
}
|
||||
|
||||
return reader;
|
||||
return new AUD_ChannelMapperReader(reader,
|
||||
const_cast<AUD_ChannelMapperFactory*>(this)->getMapping(ic));
|
||||
}
|
||||
|
||||
@@ -40,10 +40,12 @@ private:
|
||||
*/
|
||||
float **m_mapping[9];
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_ChannelMapperFactory(const AUD_ChannelMapperFactory&);
|
||||
AUD_ChannelMapperFactory& operator=(const AUD_ChannelMapperFactory&);
|
||||
|
||||
public:
|
||||
AUD_ChannelMapperFactory(AUD_IReader* reader, AUD_DeviceSpecs specs);
|
||||
AUD_ChannelMapperFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
|
||||
AUD_ChannelMapperFactory(AUD_DeviceSpecs specs);
|
||||
|
||||
virtual ~AUD_ChannelMapperFactory();
|
||||
|
||||
@@ -59,7 +61,7 @@ public:
|
||||
*/
|
||||
void deleteMapping(int ic);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_CHANNELMAPPERFACTORY
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
*/
|
||||
|
||||
#include "AUD_ChannelMapperReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader,
|
||||
float **mapping) :
|
||||
@@ -36,7 +35,7 @@ AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader,
|
||||
m_rch = m_specs.channels;
|
||||
while(mapping[++channels] != 0);
|
||||
|
||||
m_mapping = new float*[channels]; AUD_NEW("mapping")
|
||||
m_mapping = new float*[channels];
|
||||
m_specs.channels = (AUD_Channels)channels;
|
||||
|
||||
float sum;
|
||||
@@ -44,7 +43,7 @@ AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader,
|
||||
|
||||
while(channels--)
|
||||
{
|
||||
m_mapping[channels] = new float[m_rch]; AUD_NEW("mapping")
|
||||
m_mapping[channels] = new float[m_rch];
|
||||
sum = 0.0f;
|
||||
for(i=0; i < m_rch; i++)
|
||||
sum += mapping[channels][i];
|
||||
@@ -52,8 +51,6 @@ AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader,
|
||||
m_mapping[channels][i] = sum > 0.0f ?
|
||||
mapping[channels][i]/sum : 0.0f;
|
||||
}
|
||||
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
}
|
||||
|
||||
AUD_ChannelMapperReader::~AUD_ChannelMapperReader()
|
||||
@@ -62,42 +59,37 @@ AUD_ChannelMapperReader::~AUD_ChannelMapperReader()
|
||||
|
||||
while(channels--)
|
||||
{
|
||||
delete[] m_mapping[channels]; AUD_DELETE("mapping")
|
||||
delete[] m_mapping[channels];
|
||||
}
|
||||
|
||||
delete[] m_mapping; AUD_DELETE("mapping")
|
||||
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
delete[] m_mapping;
|
||||
}
|
||||
|
||||
AUD_Specs AUD_ChannelMapperReader::getSpecs()
|
||||
AUD_Specs AUD_ChannelMapperReader::getSpecs() const
|
||||
{
|
||||
return m_specs;
|
||||
}
|
||||
|
||||
void AUD_ChannelMapperReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
m_reader->read(length, buffer);
|
||||
|
||||
int channels = m_specs.channels;
|
||||
|
||||
if(m_buffer->getSize() < length * 4 * channels)
|
||||
m_buffer->resize(length * 4 * channels);
|
||||
|
||||
sample_t* in = buffer;
|
||||
sample_t* out = m_buffer->getBuffer();
|
||||
|
||||
m_reader->read(length, in);
|
||||
|
||||
if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(m_specs))
|
||||
m_buffer.resize(length * AUD_SAMPLE_SIZE(m_specs));
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
sample_t sum;
|
||||
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
for(int j = 0; j < channels; j++)
|
||||
for(int j = 0; j < m_specs.channels; j++)
|
||||
{
|
||||
sum = 0;
|
||||
for(int k = 0; k < m_rch; k++)
|
||||
sum += m_mapping[j][k] * in[i * m_rch + k];
|
||||
out[i * channels + j] = sum;
|
||||
buffer[i * m_specs.channels + j] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
buffer = m_buffer->getBuffer();
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#define AUD_CHANNELMAPPERREADER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
/**
|
||||
* This class maps a sound source's channels to a specific output channel count.
|
||||
@@ -39,7 +39,7 @@ private:
|
||||
/**
|
||||
* The sound output buffer.
|
||||
*/
|
||||
AUD_Buffer *m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The output specification.
|
||||
@@ -56,20 +56,24 @@ private:
|
||||
*/
|
||||
float **m_mapping;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_ChannelMapperReader(const AUD_ChannelMapperReader&);
|
||||
AUD_ChannelMapperReader& operator=(const AUD_ChannelMapperReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a channel mapper reader.
|
||||
* \param reader The reader to map.
|
||||
* \param mapping The mapping specification as two dimensional float array.
|
||||
* \exception AUD_Exception Thrown if the reader is NULL.
|
||||
*/
|
||||
AUD_ChannelMapperReader(AUD_IReader* reader, float **mapping);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
*/
|
||||
~AUD_ChannelMapperReader();
|
||||
|
||||
virtual AUD_Specs getSpecs();
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -26,29 +26,18 @@
|
||||
#include "AUD_ConverterFactory.h"
|
||||
#include "AUD_ConverterReader.h"
|
||||
|
||||
AUD_ConverterFactory::AUD_ConverterFactory(AUD_IReader* reader,
|
||||
AUD_DeviceSpecs specs) :
|
||||
AUD_MixerFactory(reader, specs) {}
|
||||
|
||||
AUD_ConverterFactory::AUD_ConverterFactory(AUD_IFactory* factory,
|
||||
AUD_DeviceSpecs specs) :
|
||||
AUD_MixerFactory(factory, specs) {}
|
||||
AUD_MixerFactory(factory, specs)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_ConverterFactory::AUD_ConverterFactory(AUD_DeviceSpecs specs) :
|
||||
AUD_MixerFactory(specs) {}
|
||||
|
||||
AUD_IReader* AUD_ConverterFactory::createReader()
|
||||
AUD_IReader* AUD_ConverterFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
if(m_specs.format != AUD_FORMAT_FLOAT32)
|
||||
{
|
||||
reader = new AUD_ConverterReader(reader, m_specs);
|
||||
AUD_NEW("reader")
|
||||
}
|
||||
}
|
||||
if(m_specs.format != AUD_FORMAT_FLOAT32)
|
||||
reader = new AUD_ConverterReader(reader, m_specs);
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
@@ -34,12 +34,15 @@
|
||||
*/
|
||||
class AUD_ConverterFactory : public AUD_MixerFactory
|
||||
{
|
||||
public:
|
||||
AUD_ConverterFactory(AUD_IReader* reader, AUD_DeviceSpecs specs);
|
||||
AUD_ConverterFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
|
||||
AUD_ConverterFactory(AUD_DeviceSpecs specs);
|
||||
private:
|
||||
// hide copy constructor and operator=
|
||||
AUD_ConverterFactory(const AUD_ConverterFactory&);
|
||||
AUD_ConverterFactory& operator=(const AUD_ConverterFactory&);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
public:
|
||||
AUD_ConverterFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_CONVERTERFACTORY
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
*/
|
||||
|
||||
#include "AUD_ConverterReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader,
|
||||
AUD_DeviceSpecs specs) :
|
||||
@@ -63,16 +62,9 @@ AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader,
|
||||
}
|
||||
|
||||
m_specs.format = specs.format;
|
||||
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
}
|
||||
|
||||
AUD_ConverterReader::~AUD_ConverterReader()
|
||||
{
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
}
|
||||
|
||||
AUD_Specs AUD_ConverterReader::getSpecs()
|
||||
AUD_Specs AUD_ConverterReader::getSpecs() const
|
||||
{
|
||||
return m_specs.specs;
|
||||
}
|
||||
@@ -83,11 +75,11 @@ void AUD_ConverterReader::read(int & length, sample_t* & buffer)
|
||||
|
||||
int samplesize = AUD_SAMPLE_SIZE(m_specs);
|
||||
|
||||
if(m_buffer->getSize() < length*samplesize)
|
||||
m_buffer->resize(length*samplesize);
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
m_buffer.resize(length * samplesize);
|
||||
|
||||
m_convert((data_t*)m_buffer->getBuffer(), (data_t*)buffer,
|
||||
m_convert((data_t*)m_buffer.getBuffer(), (data_t*)buffer,
|
||||
length * m_specs.channels);
|
||||
|
||||
buffer = m_buffer->getBuffer();
|
||||
buffer = m_buffer.getBuffer();
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
#include "AUD_ConverterFunctions.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
/**
|
||||
* This class converts a sound source from one to another format.
|
||||
@@ -39,7 +39,7 @@ private:
|
||||
/**
|
||||
* The sound output buffer.
|
||||
*/
|
||||
AUD_Buffer *m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The target specification.
|
||||
@@ -51,20 +51,19 @@ private:
|
||||
*/
|
||||
AUD_convert_f m_convert;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_ConverterReader(const AUD_ConverterReader&);
|
||||
AUD_ConverterReader& operator=(const AUD_ConverterReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a converter reader.
|
||||
* \param reader The reader to convert.
|
||||
* \param specs The target specification.
|
||||
* \exception AUD_Exception Thrown if the reader is NULL.
|
||||
*/
|
||||
AUD_ConverterReader(AUD_IReader* reader, AUD_DeviceSpecs specs);
|
||||
/**
|
||||
* Destroys the reader.
|
||||
*/
|
||||
~AUD_ConverterReader();
|
||||
|
||||
virtual AUD_Specs getSpecs();
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
63
intern/audaspace/intern/AUD_DefaultMixer.cpp
Normal file
63
intern/audaspace/intern/AUD_DefaultMixer.cpp
Normal 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_DefaultMixer.h"
|
||||
#include "AUD_SRCResampleReader.h"
|
||||
#include "AUD_ChannelMapperReader.h"
|
||||
#include "AUD_ChannelMapperFactory.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_DefaultMixer::AUD_DefaultMixer(AUD_DeviceSpecs specs) :
|
||||
AUD_Mixer(specs)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_DefaultMixer::prepare(AUD_IReader* reader)
|
||||
{
|
||||
// hacky for now, until a better channel mapper reader is available
|
||||
AUD_ChannelMapperFactory cmf(NULL, m_specs);
|
||||
|
||||
AUD_Specs specs = reader->getSpecs();
|
||||
|
||||
// if channel count is lower in output, rechannel before resampling
|
||||
if(specs.channels < m_specs.channels)
|
||||
{
|
||||
reader = new AUD_ChannelMapperReader(reader,
|
||||
cmf.getMapping(specs.channels));
|
||||
specs.channels = m_specs.channels;
|
||||
}
|
||||
|
||||
// resample
|
||||
if(specs.rate != m_specs.rate)
|
||||
reader = new AUD_SRCResampleReader(reader, m_specs.specs);
|
||||
|
||||
// rechannel
|
||||
if(specs.channels != m_specs.channels)
|
||||
reader = new AUD_ChannelMapperReader(reader,
|
||||
cmf.getMapping(specs.channels));
|
||||
|
||||
return reader;
|
||||
}
|
||||
@@ -23,42 +23,31 @@
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef AUD_SUMREADER
|
||||
#define AUD_SUMREADER
|
||||
#ifndef AUD_DEFAULTMIXER
|
||||
#define AUD_DEFAULTMIXER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Mixer.h"
|
||||
|
||||
/**
|
||||
* This class represents an summer.
|
||||
* This class is able to mix audiosignals of different channel count and sample
|
||||
* rate and convert it to a specific output format.
|
||||
* It uses a default ChannelMapperFactory and a SRCResampleFactory for
|
||||
* the perparation.
|
||||
*/
|
||||
class AUD_SumReader : public AUD_EffectReader
|
||||
class AUD_DefaultMixer : public AUD_Mixer
|
||||
{
|
||||
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.
|
||||
* Creates the mixer.
|
||||
*/
|
||||
AUD_SumReader(AUD_IReader* reader);
|
||||
AUD_DefaultMixer(AUD_DeviceSpecs specs);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
* This funuction prepares a reader for playback.
|
||||
* \param reader The reader to prepare.
|
||||
* \return The reader that should be used for playback.
|
||||
*/
|
||||
virtual ~AUD_SumReader();
|
||||
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual AUD_IReader* prepare(AUD_IReader* reader);
|
||||
};
|
||||
|
||||
#endif //AUD_SUMREADER
|
||||
#endif //AUD_DEFAULTMIXER
|
||||
@@ -30,7 +30,9 @@
|
||||
|
||||
#ifdef WITH_FFMPEG
|
||||
// needed for INT64_C
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include "AUD_FFMPEGReader.h"
|
||||
#endif
|
||||
@@ -38,61 +40,42 @@
|
||||
#include "AUD_SndFileReader.h"
|
||||
#endif
|
||||
|
||||
AUD_FileFactory::AUD_FileFactory(const char* filename)
|
||||
AUD_FileFactory::AUD_FileFactory(std::string filename) :
|
||||
m_filename(filename)
|
||||
{
|
||||
if(filename != NULL)
|
||||
{
|
||||
m_filename = new char[strlen(filename)+1]; AUD_NEW("string")
|
||||
strcpy(m_filename, filename);
|
||||
}
|
||||
else
|
||||
m_filename = NULL;
|
||||
}
|
||||
|
||||
AUD_FileFactory::AUD_FileFactory(unsigned char* buffer, int size)
|
||||
AUD_FileFactory::AUD_FileFactory(const data_t* buffer, int size) :
|
||||
m_buffer(new AUD_Buffer(size))
|
||||
{
|
||||
m_filename = NULL;
|
||||
m_buffer = AUD_Reference<AUD_Buffer>(new AUD_Buffer(size));
|
||||
memcpy(m_buffer.get()->getBuffer(), buffer, size);
|
||||
}
|
||||
|
||||
AUD_FileFactory::~AUD_FileFactory()
|
||||
{
|
||||
if(m_filename)
|
||||
{
|
||||
delete[] m_filename; AUD_DELETE("string")
|
||||
}
|
||||
}
|
||||
static const char* read_error = "AUD_FileFactory: File couldn't be read.";
|
||||
|
||||
AUD_IReader* AUD_FileFactory::createReader()
|
||||
AUD_IReader* AUD_FileFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader = 0;
|
||||
|
||||
#ifdef WITH_SNDFILE
|
||||
try
|
||||
{
|
||||
if(m_filename)
|
||||
reader = new AUD_SndFileReader(m_filename);
|
||||
if(m_buffer.get())
|
||||
return new AUD_SndFileReader(m_buffer);
|
||||
else
|
||||
reader = new AUD_SndFileReader(m_buffer);
|
||||
AUD_NEW("reader")
|
||||
return reader;
|
||||
return new AUD_SndFileReader(m_filename);
|
||||
}
|
||||
catch(AUD_Exception e) {}
|
||||
catch(AUD_Exception&) {}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_FFMPEG
|
||||
try
|
||||
{
|
||||
if(m_filename)
|
||||
reader = new AUD_FFMPEGReader(m_filename);
|
||||
if(m_buffer.get())
|
||||
return new AUD_FFMPEGReader(m_buffer);
|
||||
else
|
||||
reader = new AUD_FFMPEGReader(m_buffer);
|
||||
AUD_NEW("reader")
|
||||
return reader;
|
||||
return new AUD_FFMPEGReader(m_filename);
|
||||
}
|
||||
catch(AUD_Exception e) {}
|
||||
catch(AUD_Exception&) {}
|
||||
#endif
|
||||
|
||||
return reader;
|
||||
AUD_THROW(AUD_ERROR_FILE, read_error);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "AUD_Reference.h"
|
||||
class AUD_Buffer;
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* This factory tries to read a sound file via all available file readers.
|
||||
*/
|
||||
@@ -39,33 +41,32 @@ private:
|
||||
/**
|
||||
* The filename of the sound source file.
|
||||
*/
|
||||
char* m_filename;
|
||||
std::string m_filename;
|
||||
|
||||
/**
|
||||
* The buffer to read from.
|
||||
*/
|
||||
AUD_Reference<AUD_Buffer> m_buffer;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_FileFactory(const AUD_FileFactory&);
|
||||
AUD_FileFactory& operator=(const AUD_FileFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new factory.
|
||||
* \param filename The sound file path.
|
||||
*/
|
||||
AUD_FileFactory(const char* filename);
|
||||
AUD_FileFactory(std::string filename);
|
||||
|
||||
/**
|
||||
* Creates a new factory.
|
||||
* \param buffer The buffer to read from.
|
||||
* \param size The size of the buffer.
|
||||
*/
|
||||
AUD_FileFactory(unsigned char* buffer, int size);
|
||||
AUD_FileFactory(const data_t* buffer, int size);
|
||||
|
||||
/**
|
||||
* Destroys the factory.
|
||||
*/
|
||||
~AUD_FileFactory();
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_FILEFACTORY
|
||||
|
||||
@@ -27,77 +27,288 @@
|
||||
#define AUD_I3DDEVICE
|
||||
|
||||
#include "AUD_Space.h"
|
||||
#include "AUD_3DMath.h"
|
||||
|
||||
struct AUD_Handle;
|
||||
|
||||
/**
|
||||
* This class represents an output device for 3D sound.
|
||||
* Whether a normal device supports this or not can be checked with the
|
||||
* AUD_CAPS_3D_DEVICE capability.
|
||||
*/
|
||||
class AUD_I3DDevice
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Plays a 3D sound source.
|
||||
* \param factory The factory to create the reader for the sound source.
|
||||
* \param keep When keep is true the sound source will not be deleted but
|
||||
* set to paused when its end has been reached.
|
||||
* \return Returns a handle with which the playback can be controlled.
|
||||
* This is NULL if the sound couldn't be played back.
|
||||
* \exception AUD_Exception Thrown if there's an unexpected (from the
|
||||
* device side) error during creation of the reader.
|
||||
* \note The factory must provide a mono (single channel) source otherwise
|
||||
* the sound is played back normally.
|
||||
* Retrieves the listener location.
|
||||
* \return The listener location.
|
||||
*/
|
||||
virtual AUD_Handle* play3D(AUD_IFactory* factory, bool keep = false)=0;
|
||||
virtual AUD_Vector3 getListenerLocation() const=0;
|
||||
|
||||
/**
|
||||
* Updates a listeners 3D data.
|
||||
* \param data The 3D data.
|
||||
* Sets the listener location.
|
||||
* \param location The new location.
|
||||
*/
|
||||
virtual void setListenerLocation(const AUD_Vector3& location)=0;
|
||||
|
||||
/**
|
||||
* Retrieves the listener velocity.
|
||||
* \return The listener velocity.
|
||||
*/
|
||||
virtual AUD_Vector3 getListenerVelocity() const=0;
|
||||
|
||||
/**
|
||||
* Sets the listener velocity.
|
||||
* \param velocity The new velocity.
|
||||
*/
|
||||
virtual void setListenerVelocity(const AUD_Vector3& velocity)=0;
|
||||
|
||||
/**
|
||||
* Retrieves the listener orientation.
|
||||
* \return The listener orientation as quaternion.
|
||||
*/
|
||||
virtual AUD_Quaternion getListenerOrientation() const=0;
|
||||
|
||||
/**
|
||||
* Sets the listener orientation.
|
||||
* \param orientation The new orientation as quaternion.
|
||||
*/
|
||||
virtual void setListenerOrientation(const AUD_Quaternion& orientation)=0;
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the speed of sound.
|
||||
* This value is needed for doppler effect calculation.
|
||||
* \return The speed of sound.
|
||||
*/
|
||||
virtual float getSpeedOfSound() const=0;
|
||||
|
||||
/**
|
||||
* Sets the speed of sound.
|
||||
* This value is needed for doppler effect calculation.
|
||||
* \param speed The new speed of sound.
|
||||
*/
|
||||
virtual void setSpeedOfSound(float speed)=0;
|
||||
|
||||
/**
|
||||
* Retrieves the doppler factor.
|
||||
* This value is a scaling factor for the velocity vectors of sources and
|
||||
* listener which is used while calculating the doppler effect.
|
||||
* \return The doppler factor.
|
||||
*/
|
||||
virtual float getDopplerFactor() const=0;
|
||||
|
||||
/**
|
||||
* Sets the doppler factor.
|
||||
* This value is a scaling factor for the velocity vectors of sources and
|
||||
* listener which is used while calculating the doppler effect.
|
||||
* \param factor The new doppler factor.
|
||||
*/
|
||||
virtual void setDopplerFactor(float factor)=0;
|
||||
|
||||
/**
|
||||
* Retrieves the distance model.
|
||||
* \return The distance model.
|
||||
*/
|
||||
virtual AUD_DistanceModel getDistanceModel() const=0;
|
||||
|
||||
/**
|
||||
* Sets the distance model.
|
||||
* \param model distance model.
|
||||
*/
|
||||
virtual void setDistanceModel(AUD_DistanceModel model)=0;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the location of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \return The location.
|
||||
*/
|
||||
virtual AUD_Vector3 getSourceLocation(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the location of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param location The new location.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
virtual bool updateListener(AUD_3DData &data)=0;
|
||||
virtual bool setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location)=0;
|
||||
|
||||
/**
|
||||
* Sets a 3D device setting.
|
||||
* \param setting The setting type.
|
||||
* \param value The new setting value.
|
||||
* Retrieves the velocity of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \return The velocity.
|
||||
*/
|
||||
virtual AUD_Vector3 getSourceVelocity(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the velocity of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param velocity The new velocity.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
virtual bool setSetting(AUD_3DSetting setting, float value)=0;
|
||||
virtual bool setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity)=0;
|
||||
|
||||
/**
|
||||
* Retrieves a 3D device setting.
|
||||
* \param setting The setting type.
|
||||
* \return The setting value.
|
||||
* Retrieves the orientation of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \return The orientation as quaternion.
|
||||
*/
|
||||
virtual float getSetting(AUD_3DSetting setting)=0;
|
||||
virtual AUD_Quaternion getSourceOrientation(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Updates a listeners 3D data.
|
||||
* \param handle The source handle.
|
||||
* \param data The 3D data.
|
||||
* Sets the orientation of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param orientation The new orientation as quaternion.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
virtual bool updateSource(AUD_Handle* handle, AUD_3DData &data)=0;
|
||||
virtual bool setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation)=0;
|
||||
|
||||
|
||||
/**
|
||||
* Sets a 3D source setting.
|
||||
* \param handle The source handle.
|
||||
* \param setting The setting type.
|
||||
* \param value The new setting value.
|
||||
* Checks whether the source location, velocity and orientation are relative
|
||||
* to the listener.
|
||||
* \param handle The handle of the source.
|
||||
* \return Whether the source is relative.
|
||||
*/
|
||||
virtual bool isRelative(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets whether the source location, velocity and orientation are relative
|
||||
* to the listener.
|
||||
* \param handle The handle of the source.
|
||||
* \param relative Whether the source is relative.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
virtual bool setSourceSetting(AUD_Handle* handle,
|
||||
AUD_3DSourceSetting setting, float value)=0;
|
||||
virtual bool setRelative(AUD_Handle* handle, bool relative)=0;
|
||||
|
||||
/**
|
||||
* Retrieves a 3D source setting.
|
||||
* \param handle The source handle.
|
||||
* \param setting The setting type.
|
||||
* \return The setting value.
|
||||
* Retrieves the maximum volume of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \return The maximum volume.
|
||||
*/
|
||||
virtual float getSourceSetting(AUD_Handle* handle,
|
||||
AUD_3DSourceSetting setting)=0;
|
||||
virtual float getVolumeMaximum(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the maximum volume of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param volume The new maximum volume.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
virtual bool setVolumeMaximum(AUD_Handle* handle, float volume)=0;
|
||||
|
||||
/**
|
||||
* Retrieves the minimum volume of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \return The minimum volume.
|
||||
*/
|
||||
virtual float getVolumeMinimum(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the minimum volume of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param volume The new minimum volume.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
virtual bool setVolumeMinimum(AUD_Handle* handle, float volume)=0;
|
||||
|
||||
/**
|
||||
* Retrieves the maximum distance of a source.
|
||||
* If a source is further away from the reader than this distance, the
|
||||
* volume will automatically be set to 0.
|
||||
* \param handle The handle of the source.
|
||||
* \return The maximum distance.
|
||||
*/
|
||||
virtual float getDistanceMaximum(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the maximum distance of a source.
|
||||
* If a source is further away from the reader than this distance, the
|
||||
* volume will automatically be set to 0.
|
||||
* \param handle The handle of the source.
|
||||
* \param distance The new maximum distance.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
virtual bool setDistanceMaximum(AUD_Handle* handle, float distance)=0;
|
||||
|
||||
/**
|
||||
* Retrieves the reference distance of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \return The reference distance.
|
||||
*/
|
||||
virtual float getDistanceReference(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the reference distance of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param distance The new reference distance.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
virtual bool setDistanceReference(AUD_Handle* handle, float distance)=0;
|
||||
|
||||
/**
|
||||
* Retrieves the attenuation of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \return The attenuation.
|
||||
*/
|
||||
virtual float getAttenuation(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the attenuation of a source.
|
||||
* This value is used for distance calculation.
|
||||
* \param handle The handle of the source.
|
||||
* \param factor The new attenuation.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
virtual bool setAttenuation(AUD_Handle* handle, float factor)=0;
|
||||
|
||||
/**
|
||||
* Retrieves the outer angle of the cone of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \return The outer angle of the cone.
|
||||
*/
|
||||
virtual float getConeAngleOuter(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the outer angle of the cone of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param angle The new outer angle of the cone.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
virtual bool setConeAngleOuter(AUD_Handle* handle, float angle)=0;
|
||||
|
||||
/**
|
||||
* Retrieves the inner angle of the cone of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \return The inner angle of the cone.
|
||||
*/
|
||||
virtual float getConeAngleInner(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the inner angle of the cone of a source.
|
||||
* \param handle The handle of the source.
|
||||
* \param angle The new inner angle of the cone.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
virtual bool setConeAngleInner(AUD_Handle* handle, float angle)=0;
|
||||
|
||||
/**
|
||||
* Retrieves the outer volume of the cone of a source.
|
||||
* The volume between inner and outer angle is interpolated between inner
|
||||
* volume and this value.
|
||||
* \param handle The handle of the source.
|
||||
* \return The outer volume of the cone.
|
||||
*/
|
||||
virtual float getConeVolumeOuter(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the outer volume of the cone of a source.
|
||||
* The volume between inner and outer angle is interpolated between inner
|
||||
* volume and this value.
|
||||
* \param handle The handle of the source.
|
||||
* \param volume The new outer volume of the cone.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
virtual bool setConeVolumeOuter(AUD_Handle* handle, float volume)=0;
|
||||
};
|
||||
|
||||
#endif //AUD_I3DDEVICE
|
||||
|
||||
@@ -30,9 +30,11 @@
|
||||
class AUD_IFactory;
|
||||
|
||||
/// Handle structure, for inherition.
|
||||
typedef struct
|
||||
struct AUD_Handle
|
||||
{
|
||||
} AUD_Handle;
|
||||
};
|
||||
|
||||
typedef void (*stopCallback)(void*);
|
||||
|
||||
/**
|
||||
* This class represents an output device for sound sources.
|
||||
@@ -53,7 +55,7 @@ public:
|
||||
/**
|
||||
* Returns the specification of the device.
|
||||
*/
|
||||
virtual AUD_DeviceSpecs getSpecs()=0;
|
||||
virtual AUD_DeviceSpecs getSpecs() const=0;
|
||||
|
||||
/**
|
||||
* Plays a sound source.
|
||||
@@ -95,6 +97,16 @@ public:
|
||||
*/
|
||||
virtual bool stop(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Gets the behaviour of the device for a played back sound when the sound
|
||||
* doesn't return any more samples.
|
||||
* \param handle The handle returned by the play function.
|
||||
* \return
|
||||
* - true if the source will be paused when it's end is reached
|
||||
* - false if the handle won't kept or is invalid.
|
||||
*/
|
||||
virtual bool getKeep(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the behaviour of the device for a played back sound when the sound
|
||||
* doesn't return any more samples.
|
||||
@@ -106,16 +118,6 @@ public:
|
||||
*/
|
||||
virtual bool setKeep(AUD_Handle* handle, bool keep)=0;
|
||||
|
||||
/**
|
||||
* Sends a message to a sound or all sounds that are currently played or
|
||||
* paused.
|
||||
* \param handle The sound that should receive the message or NULL if all
|
||||
* sounds should receive it.
|
||||
* \param message The message.
|
||||
* \return True if the message has been read by at least one sound.
|
||||
*/
|
||||
virtual bool sendMessage(AUD_Handle* handle, AUD_Message &message)=0;
|
||||
|
||||
/**
|
||||
* Seeks in a played back sound.
|
||||
* \param handle The handle returned by the play function.
|
||||
@@ -163,29 +165,80 @@ public:
|
||||
virtual void unlock()=0;
|
||||
|
||||
/**
|
||||
* Checks if a specific capability as available on a device.
|
||||
* \param capability The capability.
|
||||
* \return Whether it is available or not.
|
||||
* Retrieves the overall device volume.
|
||||
* \return The overall device volume.
|
||||
*/
|
||||
virtual bool checkCapability(int capability)=0;
|
||||
virtual float getVolume() const=0;
|
||||
|
||||
/**
|
||||
* Set a value of a capability. The data behind the pointer depends on the
|
||||
* capability.
|
||||
* \param capability The capability.
|
||||
* \param value The value.
|
||||
* \return Whether the action succeeded or not.
|
||||
* Sets the overall device volume.
|
||||
* \param handle The sound handle.
|
||||
* \param volume The overall device volume.
|
||||
*/
|
||||
virtual bool setCapability(int capability, void *value)=0;
|
||||
virtual void setVolume(float volume)=0;
|
||||
|
||||
/**
|
||||
* Retrieves a value of a capability. The data behind the pointer depends on
|
||||
* the capability.
|
||||
* \param capability The capability.
|
||||
* \param value The value.
|
||||
* \return Whether the action succeeded or not.
|
||||
* Retrieves the volume of a playing sound.
|
||||
* \param handle The sound handle.
|
||||
* \return The volume.
|
||||
*/
|
||||
virtual bool getCapability(int capability, void *value)=0;
|
||||
virtual float getVolume(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the volume of a playing sound.
|
||||
* \param handle The sound handle.
|
||||
* \param volume The volume.
|
||||
* \return
|
||||
* - true if the handle is valid.
|
||||
* - false if the handle is invalid.
|
||||
*/
|
||||
virtual bool setVolume(AUD_Handle* handle, float volume)=0;
|
||||
|
||||
/**
|
||||
* Retrieves the pitch of a playing sound.
|
||||
* \return The pitch.
|
||||
*/
|
||||
virtual float getPitch(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the pitch of a playing sound.
|
||||
* \param handle The sound handle.
|
||||
* \param pitch The pitch.
|
||||
* \return
|
||||
* - true if the handle is valid.
|
||||
* - false if the handle is invalid.
|
||||
*/
|
||||
virtual bool setPitch(AUD_Handle* handle, float pitch)=0;
|
||||
|
||||
/**
|
||||
* Retrieves the loop count of a playing sound.
|
||||
* A negative value indicates infinity.
|
||||
* \return The remaining loop count.
|
||||
*/
|
||||
virtual int getLoopCount(AUD_Handle* handle)=0;
|
||||
|
||||
/**
|
||||
* Sets the loop count of a playing sound.
|
||||
* A negative value indicates infinity.
|
||||
* \param handle The sound handle.
|
||||
* \param count The new loop count.
|
||||
* \return
|
||||
* - true if the handle is valid.
|
||||
* - false if the handle is invalid.
|
||||
*/
|
||||
virtual bool setLoopCount(AUD_Handle* handle, int count)=0;
|
||||
|
||||
/**
|
||||
* Sets the callback function that's called when the end of a playing sound
|
||||
* is reached.
|
||||
* \param handle The sound handle.
|
||||
* \param callback The callback function.
|
||||
* \param data The data that should be passed to the callback function.
|
||||
* \return
|
||||
* - true if the handle is valid.
|
||||
* - false if the handle is invalid.
|
||||
*/
|
||||
virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = 0, void* data = 0)=0;
|
||||
};
|
||||
|
||||
#endif //AUD_IDevice
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
* \exception AUD_Exception An exception may be thrown if there has been
|
||||
* a more unexpected error during reader creation.
|
||||
*/
|
||||
virtual AUD_IReader* createReader()=0;
|
||||
virtual AUD_IReader* createReader() const=0;
|
||||
};
|
||||
|
||||
#endif //AUD_IFACTORY
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
* \return Always returns true for readers of the buffer type.
|
||||
* \see getType
|
||||
*/
|
||||
virtual bool isSeekable()=0;
|
||||
virtual bool isSeekable() const=0;
|
||||
|
||||
/**
|
||||
* Seeks to a specific position in the source.
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
* \return The length as sample count. May be negative if unknown.
|
||||
* \see getType
|
||||
*/
|
||||
virtual int getLength()=0;
|
||||
virtual int getLength() const=0;
|
||||
|
||||
/**
|
||||
* Returns the position of the source as a sample count value.
|
||||
@@ -76,30 +76,13 @@ public:
|
||||
* the buffer ones.
|
||||
* \see getType
|
||||
*/
|
||||
virtual int getPosition()=0;
|
||||
virtual int getPosition() const=0;
|
||||
|
||||
/**
|
||||
* Returns the specification of the reader.
|
||||
* \return The AUD_Specs structure.
|
||||
*/
|
||||
virtual AUD_Specs getSpecs()=0;
|
||||
|
||||
/**
|
||||
* Returns the type of the reader. There are special conditions for the
|
||||
* readers of the buffer type. Those have to return correct position and
|
||||
* length values as well as they must be seekable.
|
||||
* \return AUD_TYPE_BUFFER or AUD_TYPE_STREAM.
|
||||
*/
|
||||
virtual AUD_ReaderType getType()=0;
|
||||
|
||||
/**
|
||||
* Sends a message to this reader and if it has subreaders it broadcasts
|
||||
* the message to them.
|
||||
* \param message The message.
|
||||
* \return Whether the message has been read by the reader or one of his
|
||||
* subreaders.
|
||||
*/
|
||||
virtual bool notify(AUD_Message &message)=0;
|
||||
virtual AUD_Specs getSpecs() const=0;
|
||||
|
||||
/**
|
||||
* Request to read the next length samples out of the source.
|
||||
|
||||
@@ -26,28 +26,18 @@
|
||||
#include "AUD_LinearResampleFactory.h"
|
||||
#include "AUD_LinearResampleReader.h"
|
||||
|
||||
AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_IReader* reader,
|
||||
AUD_DeviceSpecs specs) :
|
||||
AUD_ResampleFactory(reader, specs) {}
|
||||
|
||||
AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_IFactory* factory,
|
||||
AUD_DeviceSpecs specs) :
|
||||
AUD_ResampleFactory(factory, specs) {}
|
||||
AUD_ResampleFactory(factory, specs)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_DeviceSpecs specs) :
|
||||
AUD_ResampleFactory(specs) {}
|
||||
|
||||
AUD_IReader* AUD_LinearResampleFactory::createReader()
|
||||
AUD_IReader* AUD_LinearResampleFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader != 0)
|
||||
{
|
||||
if(reader->getSpecs().rate != m_specs.rate)
|
||||
{
|
||||
reader = new AUD_LinearResampleReader(reader, m_specs.specs);
|
||||
AUD_NEW("reader")
|
||||
}
|
||||
}
|
||||
if(reader->getSpecs().rate != m_specs.rate)
|
||||
reader = new AUD_LinearResampleReader(reader, m_specs.specs);
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
@@ -33,12 +33,15 @@
|
||||
*/
|
||||
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);
|
||||
private:
|
||||
// hide copy constructor and operator=
|
||||
AUD_LinearResampleFactory(const AUD_LinearResampleFactory&);
|
||||
AUD_LinearResampleFactory& operator=(const AUD_LinearResampleFactory&);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
public:
|
||||
AUD_LinearResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_LINEARRESAMPLEFACTORY
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
*/
|
||||
|
||||
#include "AUD_LinearResampleReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
@@ -33,25 +32,15 @@
|
||||
|
||||
AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_IReader* reader,
|
||||
AUD_Specs specs) :
|
||||
AUD_EffectReader(reader)
|
||||
AUD_EffectReader(reader),
|
||||
m_sspecs(reader->getSpecs()),
|
||||
m_factor(float(specs.rate) / float(m_sspecs.rate)),
|
||||
m_tspecs(specs),
|
||||
m_position(0),
|
||||
m_sposition(0)
|
||||
{
|
||||
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")
|
||||
m_cache.resize(2 * AUD_SAMPLE_SIZE(m_tspecs));
|
||||
}
|
||||
|
||||
void AUD_LinearResampleReader::seek(int position)
|
||||
@@ -61,17 +50,17 @@ void AUD_LinearResampleReader::seek(int position)
|
||||
m_reader->seek(m_sposition);
|
||||
}
|
||||
|
||||
int AUD_LinearResampleReader::getLength()
|
||||
int AUD_LinearResampleReader::getLength() const
|
||||
{
|
||||
return m_reader->getLength() * m_factor;
|
||||
}
|
||||
|
||||
int AUD_LinearResampleReader::getPosition()
|
||||
int AUD_LinearResampleReader::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
AUD_Specs AUD_LinearResampleReader::getSpecs()
|
||||
AUD_Specs AUD_LinearResampleReader::getSpecs() const
|
||||
{
|
||||
return m_tspecs;
|
||||
}
|
||||
@@ -81,13 +70,13 @@ 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);
|
||||
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();
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
m_reader->read(len, buf);
|
||||
|
||||
@@ -106,9 +95,9 @@ void AUD_LinearResampleReader::read(int & length, sample_t* & buffer)
|
||||
|
||||
if(floor(spos) < 0)
|
||||
{
|
||||
low = m_cache->getBuffer()[(int)(floor(spos) + 2) * CC];
|
||||
low = m_cache.getBuffer()[(int)(floor(spos) + 2) * CC];
|
||||
if(ceil(spos) < 0)
|
||||
high = m_cache->getBuffer()[(int)(ceil(spos) + 2) * CC];
|
||||
high = m_cache.getBuffer()[(int)(ceil(spos) + 2) * CC];
|
||||
else
|
||||
high = buf[(int)ceil(spos) * CC];
|
||||
}
|
||||
@@ -122,11 +111,11 @@ void AUD_LinearResampleReader::read(int & length, sample_t* & buffer)
|
||||
}
|
||||
|
||||
if(len > 1)
|
||||
memcpy(m_cache->getBuffer(),
|
||||
memcpy(m_cache.getBuffer(),
|
||||
buf + (len - 2) * channels,
|
||||
2 * samplesize);
|
||||
else if(len == 1)
|
||||
memcpy(m_cache->getBuffer() + 1 * channels, buf, samplesize);
|
||||
memcpy(m_cache.getBuffer() + 1 * channels, buf, samplesize);
|
||||
|
||||
m_sposition += len;
|
||||
m_position += length;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#define AUD_LINEARRESAMPLEREADER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
/**
|
||||
* This resampling reader uses libsamplerate for resampling.
|
||||
@@ -35,10 +35,20 @@ class AUD_Buffer;
|
||||
class AUD_LinearResampleReader : public AUD_EffectReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The sample specification of the source.
|
||||
*/
|
||||
const AUD_Specs m_sspecs;
|
||||
|
||||
/**
|
||||
* The resampling factor.
|
||||
*/
|
||||
float m_factor;
|
||||
const float m_factor;
|
||||
|
||||
/**
|
||||
* The target specification.
|
||||
*/
|
||||
AUD_Specs m_tspecs;
|
||||
|
||||
/**
|
||||
* The current position.
|
||||
@@ -53,41 +63,29 @@ private:
|
||||
/**
|
||||
* The sound output buffer.
|
||||
*/
|
||||
AUD_Buffer *m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The input caching buffer.
|
||||
*/
|
||||
AUD_Buffer *m_cache;
|
||||
AUD_Buffer m_cache;
|
||||
|
||||
/**
|
||||
* The target specification.
|
||||
*/
|
||||
AUD_Specs m_tspecs;
|
||||
|
||||
/**
|
||||
* The sample specification of the source.
|
||||
*/
|
||||
AUD_Specs m_sspecs;
|
||||
// hide copy constructor and operator=
|
||||
AUD_LinearResampleReader(const AUD_LinearResampleReader&);
|
||||
AUD_LinearResampleReader& operator=(const AUD_LinearResampleReader&);
|
||||
|
||||
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 int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -24,72 +24,13 @@
|
||||
*/
|
||||
|
||||
#include "AUD_Mixer.h"
|
||||
#include "AUD_SRCResampleFactory.h"
|
||||
#include "AUD_LinearResampleFactory.h"
|
||||
#include "AUD_ChannelMapperFactory.h"
|
||||
#include "AUD_IReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_Mixer::AUD_Mixer()
|
||||
AUD_Mixer::AUD_Mixer(AUD_DeviceSpecs specs) :
|
||||
m_specs(specs)
|
||||
{
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
|
||||
m_resampler = NULL;
|
||||
m_mapper = NULL;
|
||||
}
|
||||
|
||||
AUD_Mixer::~AUD_Mixer()
|
||||
{
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
|
||||
|
||||
if(m_resampler)
|
||||
{
|
||||
delete m_resampler; AUD_DELETE("factory")
|
||||
}
|
||||
if(m_mapper)
|
||||
{
|
||||
delete m_mapper; AUD_DELETE("factory")
|
||||
}
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_Mixer::prepare(AUD_IReader* reader)
|
||||
{
|
||||
m_resampler->setReader(reader);
|
||||
reader = m_resampler->createReader();
|
||||
|
||||
if(reader != NULL && reader->getSpecs().channels != m_specs.channels)
|
||||
{
|
||||
m_mapper->setReader(reader);
|
||||
reader = m_mapper->createReader();
|
||||
}
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
AUD_DeviceSpecs AUD_Mixer::getSpecs()
|
||||
{
|
||||
return m_specs;
|
||||
}
|
||||
|
||||
void AUD_Mixer::setSpecs(AUD_DeviceSpecs specs)
|
||||
{
|
||||
m_specs = specs;
|
||||
|
||||
if(m_resampler)
|
||||
{
|
||||
delete m_resampler; AUD_DELETE("factory")
|
||||
}
|
||||
if(m_mapper)
|
||||
{
|
||||
delete m_mapper; AUD_DELETE("factory")
|
||||
}
|
||||
|
||||
m_resampler = new AUD_MIXER_RESAMPLER(specs); AUD_NEW("factory")
|
||||
m_mapper = new AUD_ChannelMapperFactory(specs); AUD_NEW("factory")
|
||||
|
||||
int bigendian = 1;
|
||||
bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
|
||||
|
||||
@@ -121,6 +62,11 @@ void AUD_Mixer::setSpecs(AUD_DeviceSpecs specs)
|
||||
}
|
||||
}
|
||||
|
||||
AUD_DeviceSpecs AUD_Mixer::getSpecs() const
|
||||
{
|
||||
return m_specs;
|
||||
}
|
||||
|
||||
void AUD_Mixer::add(sample_t* buffer, int start, int length, float volume)
|
||||
{
|
||||
AUD_MixerBuffer buf;
|
||||
@@ -137,10 +83,10 @@ void AUD_Mixer::superpose(data_t* buffer, int length, float volume)
|
||||
|
||||
int channels = m_specs.channels;
|
||||
|
||||
if(m_buffer->getSize() < length * channels * 4)
|
||||
m_buffer->resize(length * channels * 4);
|
||||
if(m_buffer.getSize() < length * channels * 4)
|
||||
m_buffer.resize(length * channels * 4);
|
||||
|
||||
sample_t* out = m_buffer->getBuffer();
|
||||
sample_t* out = m_buffer.getBuffer();
|
||||
sample_t* in;
|
||||
|
||||
memset(out, 0, length * channels * 4);
|
||||
|
||||
@@ -26,13 +26,8 @@
|
||||
#ifndef AUD_MIXER
|
||||
#define AUD_MIXER
|
||||
|
||||
#define AUD_MIXER_RESAMPLER AUD_SRCResampleFactory
|
||||
|
||||
#include "AUD_ConverterFunctions.h"
|
||||
class AUD_ConverterFactory;
|
||||
class AUD_MIXER_RESAMPLER;
|
||||
class AUD_ChannelMapperFactory;
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
class AUD_IReader;
|
||||
#include <list>
|
||||
|
||||
@@ -45,24 +40,12 @@ struct AUD_MixerBuffer
|
||||
};
|
||||
|
||||
/**
|
||||
* This class is able to mix audiosignals of different channel count and sample
|
||||
* rate and convert it to a specific output format.
|
||||
* It uses a default ChannelMapperFactory and a SRCResampleFactory for
|
||||
* the perparation.
|
||||
* This abstract class is able to mix audiosignals of different channel count
|
||||
* and sample rate and convert it to a specific output format.
|
||||
*/
|
||||
class AUD_Mixer
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The resampling factory that resamples all readers for superposition.
|
||||
*/
|
||||
AUD_MIXER_RESAMPLER* m_resampler;
|
||||
|
||||
/**
|
||||
* The channel mapper factory that maps all readers for superposition.
|
||||
*/
|
||||
AUD_ChannelMapperFactory* m_mapper;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The list of buffers to superpose.
|
||||
*/
|
||||
@@ -71,12 +54,12 @@ private:
|
||||
/**
|
||||
* The output specification.
|
||||
*/
|
||||
AUD_DeviceSpecs m_specs;
|
||||
const AUD_DeviceSpecs m_specs;
|
||||
|
||||
/**
|
||||
* The temporary mixing buffer.
|
||||
*/
|
||||
AUD_Buffer* m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* Converter function.
|
||||
@@ -87,31 +70,25 @@ public:
|
||||
/**
|
||||
* Creates the mixer.
|
||||
*/
|
||||
AUD_Mixer();
|
||||
AUD_Mixer(AUD_DeviceSpecs specs);
|
||||
|
||||
/**
|
||||
* Destroys the mixer.
|
||||
*/
|
||||
~AUD_Mixer();
|
||||
virtual ~AUD_Mixer() {}
|
||||
|
||||
/**
|
||||
* Returns the target specification for superposing.
|
||||
* \return The target specification.
|
||||
*/
|
||||
AUD_DeviceSpecs getSpecs() const;
|
||||
|
||||
/**
|
||||
* This funuction prepares a reader for playback.
|
||||
* \param reader The reader to prepare.
|
||||
* \return The reader that should be used for playback.
|
||||
*/
|
||||
AUD_IReader* prepare(AUD_IReader* reader);
|
||||
|
||||
/**
|
||||
* Returns the target specification for superposing.
|
||||
* \return The target specification.
|
||||
*/
|
||||
AUD_DeviceSpecs getSpecs();
|
||||
|
||||
/**
|
||||
* Sets the target specification for superposing.
|
||||
* \param specs The target specification.
|
||||
*/
|
||||
void setSpecs(AUD_DeviceSpecs specs);
|
||||
virtual AUD_IReader* prepare(AUD_IReader* reader)=0;
|
||||
|
||||
/**
|
||||
* Adds a buffer for superposition.
|
||||
@@ -120,7 +97,7 @@ public:
|
||||
* \param length The length of the buffer in samples.
|
||||
* \param volume The mixing volume. Must be a value between 0.0 and 1.0.
|
||||
*/
|
||||
void add(sample_t* buffer, int start, int length, float volume);
|
||||
virtual void add(sample_t* buffer, int start, int length, float volume);
|
||||
|
||||
/**
|
||||
* Superposes all added buffers into an output buffer.
|
||||
@@ -128,7 +105,7 @@ public:
|
||||
* \param length The length of the buffer in samples.
|
||||
* \param volume The mixing volume. Must be a value between 0.0 and 1.0.
|
||||
*/
|
||||
void superpose(data_t* buffer, int length, float volume);
|
||||
virtual void superpose(data_t* buffer, int length, float volume);
|
||||
};
|
||||
|
||||
#endif //AUD_MIXER
|
||||
|
||||
@@ -26,84 +26,23 @@
|
||||
#include "AUD_MixerFactory.h"
|
||||
#include "AUD_IReader.h"
|
||||
|
||||
AUD_IReader* AUD_MixerFactory::getReader()
|
||||
AUD_IReader* AUD_MixerFactory::getReader() const
|
||||
{
|
||||
AUD_IReader* reader;
|
||||
|
||||
// first check for an existing reader
|
||||
if(m_reader != 0)
|
||||
{
|
||||
reader = m_reader;
|
||||
m_reader = 0;
|
||||
return reader;
|
||||
}
|
||||
|
||||
// otherwise create a reader if there is a factory
|
||||
if(m_factory != 0)
|
||||
{
|
||||
reader = m_factory->createReader();
|
||||
return reader;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AUD_MixerFactory::AUD_MixerFactory(AUD_IReader* reader,
|
||||
AUD_DeviceSpecs specs)
|
||||
{
|
||||
m_specs = specs;
|
||||
m_reader = reader;
|
||||
m_factory = 0;
|
||||
return m_factory->createReader();
|
||||
}
|
||||
|
||||
AUD_MixerFactory::AUD_MixerFactory(AUD_IFactory* factory,
|
||||
AUD_DeviceSpecs specs)
|
||||
AUD_DeviceSpecs specs) :
|
||||
m_specs(specs), m_factory(factory)
|
||||
{
|
||||
m_specs = specs;
|
||||
m_reader = 0;
|
||||
m_factory = factory;
|
||||
}
|
||||
|
||||
AUD_MixerFactory::AUD_MixerFactory(AUD_DeviceSpecs specs)
|
||||
{
|
||||
m_specs = specs;
|
||||
m_reader = 0;
|
||||
m_factory = 0;
|
||||
}
|
||||
|
||||
AUD_MixerFactory::~AUD_MixerFactory()
|
||||
{
|
||||
if(m_reader != 0)
|
||||
{
|
||||
delete m_reader; AUD_DELETE("reader")
|
||||
}
|
||||
}
|
||||
|
||||
AUD_DeviceSpecs AUD_MixerFactory::getSpecs()
|
||||
AUD_DeviceSpecs AUD_MixerFactory::getSpecs() const
|
||||
{
|
||||
return m_specs;
|
||||
}
|
||||
|
||||
void AUD_MixerFactory::setSpecs(AUD_DeviceSpecs specs)
|
||||
{
|
||||
m_specs = specs;
|
||||
}
|
||||
|
||||
void AUD_MixerFactory::setReader(AUD_IReader* reader)
|
||||
{
|
||||
if(m_reader != 0)
|
||||
{
|
||||
delete m_reader; AUD_DELETE("reader")
|
||||
}
|
||||
m_reader = reader;
|
||||
}
|
||||
|
||||
void AUD_MixerFactory::setFactory(AUD_IFactory* factory)
|
||||
{
|
||||
m_factory = factory;
|
||||
}
|
||||
|
||||
AUD_IFactory* AUD_MixerFactory::getFactory()
|
||||
AUD_IFactory* AUD_MixerFactory::getFactory() const
|
||||
{
|
||||
return m_factory;
|
||||
}
|
||||
|
||||
@@ -35,9 +35,9 @@ class AUD_MixerFactory : public AUD_IFactory
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* The reader that should be mixed later.
|
||||
* The target specification for resampling.
|
||||
*/
|
||||
AUD_IReader* m_reader;
|
||||
const AUD_DeviceSpecs m_specs;
|
||||
|
||||
/**
|
||||
* If there is no reader it is created out of this factory.
|
||||
@@ -45,26 +45,14 @@ protected:
|
||||
AUD_IFactory* m_factory;
|
||||
|
||||
/**
|
||||
* The target specification for resampling.
|
||||
*/
|
||||
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.
|
||||
* This method can be used for the createReader function of the implementing
|
||||
* classes.
|
||||
* \return The reader to mix, or NULL if there is no reader or factory.
|
||||
* \return The reader to mix.
|
||||
*/
|
||||
AUD_IReader* getReader();
|
||||
AUD_IReader* getReader() const;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new factory.
|
||||
* \param reader The reader to mix.
|
||||
* \param specs The target specification.
|
||||
*/
|
||||
AUD_MixerFactory(AUD_IReader* reader, AUD_DeviceSpecs specs);
|
||||
|
||||
/**
|
||||
* Creates a new factory.
|
||||
* \param factory The factory to create the readers to mix out of.
|
||||
@@ -72,46 +60,16 @@ public:
|
||||
*/
|
||||
AUD_MixerFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
|
||||
|
||||
/**
|
||||
* Creates a new factory.
|
||||
* \param specs The target specification.
|
||||
*/
|
||||
AUD_MixerFactory(AUD_DeviceSpecs specs);
|
||||
|
||||
/**
|
||||
* Destroys the resampling factory.
|
||||
*/
|
||||
virtual ~AUD_MixerFactory();
|
||||
|
||||
/**
|
||||
* Returns the target specification for resampling.
|
||||
*/
|
||||
AUD_DeviceSpecs getSpecs();
|
||||
|
||||
/**
|
||||
* Sets the target specification for resampling.
|
||||
* \param specs The specification.
|
||||
*/
|
||||
void setSpecs(AUD_DeviceSpecs specs);
|
||||
|
||||
/**
|
||||
* Sets the reader for resampling.
|
||||
* If there has already been a reader, it will be deleted.
|
||||
* \param reader The reader that should be used as source for resampling.
|
||||
*/
|
||||
void setReader(AUD_IReader* reader);
|
||||
|
||||
/**
|
||||
* Sets the factory for resampling.
|
||||
* \param factory The factory that should be used as source for resampling.
|
||||
*/
|
||||
void setFactory(AUD_IFactory* factory);
|
||||
AUD_DeviceSpecs getSpecs() const;
|
||||
|
||||
/**
|
||||
* Returns the saved factory.
|
||||
* \return The factory or NULL if there has no factory been saved.
|
||||
* \return The factory.
|
||||
*/
|
||||
AUD_IFactory* getFactory();
|
||||
AUD_IFactory* getFactory() const;
|
||||
};
|
||||
|
||||
#endif //AUD_MIXERFACTORY
|
||||
|
||||
@@ -31,14 +31,15 @@
|
||||
|
||||
AUD_NULLDevice::AUD_NULLDevice()
|
||||
{
|
||||
m_specs.channels = AUD_CHANNELS_INVALID;
|
||||
m_specs.format = AUD_FORMAT_INVALID;
|
||||
m_specs.rate = AUD_RATE_INVALID;
|
||||
}
|
||||
|
||||
AUD_DeviceSpecs AUD_NULLDevice::getSpecs()
|
||||
AUD_DeviceSpecs AUD_NULLDevice::getSpecs() const
|
||||
{
|
||||
return m_specs;
|
||||
AUD_DeviceSpecs specs;
|
||||
specs.channels = AUD_CHANNELS_INVALID;
|
||||
specs.format = AUD_FORMAT_INVALID;
|
||||
specs.rate = AUD_RATE_INVALID;
|
||||
return specs;
|
||||
}
|
||||
|
||||
AUD_Handle* AUD_NULLDevice::play(AUD_IFactory* factory, bool keep)
|
||||
@@ -61,12 +62,12 @@ bool AUD_NULLDevice::stop(AUD_Handle* handle)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AUD_NULLDevice::setKeep(AUD_Handle* handle, bool keep)
|
||||
bool AUD_NULLDevice::getKeep(AUD_Handle* handle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AUD_NULLDevice::sendMessage(AUD_Handle* handle, AUD_Message &message)
|
||||
bool AUD_NULLDevice::setKeep(AUD_Handle* handle, bool keep)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -94,17 +95,46 @@ void AUD_NULLDevice::unlock()
|
||||
{
|
||||
}
|
||||
|
||||
bool AUD_NULLDevice::checkCapability(int capability)
|
||||
float AUD_NULLDevice::getVolume() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AUD_NULLDevice::setVolume(float volume)
|
||||
{
|
||||
}
|
||||
|
||||
float AUD_NULLDevice::getVolume(AUD_Handle* handle)
|
||||
{
|
||||
return std::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
|
||||
bool AUD_NULLDevice::setVolume(AUD_Handle* handle, float volume)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AUD_NULLDevice::setCapability(int capability, void *value)
|
||||
float AUD_NULLDevice::getPitch(AUD_Handle* handle)
|
||||
{
|
||||
return std::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
|
||||
bool AUD_NULLDevice::setPitch(AUD_Handle* handle, float pitch)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AUD_NULLDevice::getCapability(int capability, void *value)
|
||||
int AUD_NULLDevice::getLoopCount(AUD_Handle* handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AUD_NULLDevice::setLoopCount(AUD_Handle* handle, int count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AUD_NULLDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -33,33 +33,33 @@
|
||||
*/
|
||||
class AUD_NULLDevice : public AUD_IDevice
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The specs of the device.
|
||||
*/
|
||||
AUD_DeviceSpecs m_specs;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new NULL device.
|
||||
*/
|
||||
AUD_NULLDevice();
|
||||
|
||||
virtual AUD_DeviceSpecs getSpecs();
|
||||
virtual AUD_DeviceSpecs getSpecs() const;
|
||||
virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false);
|
||||
virtual bool pause(AUD_Handle* handle);
|
||||
virtual bool resume(AUD_Handle* handle);
|
||||
virtual bool stop(AUD_Handle* handle);
|
||||
virtual bool getKeep(AUD_Handle* handle);
|
||||
virtual bool setKeep(AUD_Handle* handle, bool keep);
|
||||
virtual bool sendMessage(AUD_Handle* handle, AUD_Message &message);
|
||||
virtual bool seek(AUD_Handle* handle, float position);
|
||||
virtual float getPosition(AUD_Handle* handle);
|
||||
virtual AUD_Status getStatus(AUD_Handle* handle);
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
virtual bool checkCapability(int capability);
|
||||
virtual bool setCapability(int capability, void *value);
|
||||
virtual bool getCapability(int capability, void *value);
|
||||
virtual float getVolume() const;
|
||||
virtual void setVolume(float volume);
|
||||
virtual float getVolume(AUD_Handle* handle);
|
||||
virtual bool setVolume(AUD_Handle* handle, float volume);
|
||||
virtual float getPitch(AUD_Handle* handle);
|
||||
virtual bool setPitch(AUD_Handle* handle, float pitch);
|
||||
virtual int getLoopCount(AUD_Handle* handle);
|
||||
virtual bool setLoopCount(AUD_Handle* handle, int count);
|
||||
virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = 0, void* data = 0);
|
||||
};
|
||||
|
||||
#endif //AUD_NULLDEVICE
|
||||
|
||||
@@ -23,21 +23,17 @@
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "AUD_Mixer.h"
|
||||
#include "AUD_DefaultMixer.h"
|
||||
#include "AUD_ReadDevice.h"
|
||||
#include "AUD_IReader.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_ReadDevice::AUD_ReadDevice(AUD_DeviceSpecs specs)
|
||||
AUD_ReadDevice::AUD_ReadDevice(AUD_DeviceSpecs specs) :
|
||||
m_playing(false)
|
||||
{
|
||||
m_specs = specs;
|
||||
|
||||
m_mixer = new AUD_Mixer(); AUD_NEW("mixer")
|
||||
m_mixer->setSpecs(m_specs);
|
||||
|
||||
m_playing = false;
|
||||
|
||||
create();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,15 +33,19 @@
|
||||
*/
|
||||
class AUD_ReadDevice : public AUD_SoftwareDevice
|
||||
{
|
||||
protected:
|
||||
virtual void playing(bool playing);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Whether the device currently.
|
||||
*/
|
||||
bool m_playing;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_ReadDevice(const AUD_ReadDevice&);
|
||||
AUD_ReadDevice& operator=(const AUD_ReadDevice&);
|
||||
|
||||
protected:
|
||||
virtual void playing(bool playing);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new read device.
|
||||
|
||||
@@ -45,12 +45,12 @@ public:
|
||||
AUD_Reference(T* reference = 0)
|
||||
{
|
||||
m_reference = reference;
|
||||
m_refcount = new int; AUD_NEW("int")
|
||||
m_refcount = new int;
|
||||
*m_refcount = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a AUD_Reference object.
|
||||
* Copies an AUD_Reference object.
|
||||
* \param ref The AUD_Reference object to copy.
|
||||
*/
|
||||
AUD_Reference(const AUD_Reference& ref)
|
||||
@@ -69,17 +69,17 @@ public:
|
||||
(*m_refcount)--;
|
||||
if(*m_refcount == 0)
|
||||
{
|
||||
if(m_reference != 0)
|
||||
if(m_reference)
|
||||
{
|
||||
delete m_reference; AUD_DELETE("buffer")
|
||||
delete m_reference;
|
||||
}
|
||||
delete m_refcount; AUD_DELETE("int")
|
||||
delete m_refcount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a AUD_Reference object.
|
||||
* \param ref The AUD_Reference object to copy.
|
||||
* Assigns an AUD_Reference to this object.
|
||||
* \param ref The AUD_Reference object to assign.
|
||||
*/
|
||||
AUD_Reference& operator=(const AUD_Reference& ref)
|
||||
{
|
||||
@@ -89,11 +89,11 @@ public:
|
||||
(*m_refcount)--;
|
||||
if(*m_refcount == 0)
|
||||
{
|
||||
if(m_reference != 0)
|
||||
if(m_reference)
|
||||
{
|
||||
delete m_reference; AUD_DELETE("buffer")
|
||||
delete m_reference;
|
||||
}
|
||||
delete m_refcount; AUD_DELETE("int")
|
||||
delete m_refcount;
|
||||
}
|
||||
|
||||
m_reference = ref.m_reference;
|
||||
@@ -106,7 +106,7 @@ public:
|
||||
/**
|
||||
* Returns the reference.
|
||||
*/
|
||||
T* get()
|
||||
T* get() const
|
||||
{
|
||||
return m_reference;
|
||||
}
|
||||
|
||||
@@ -28,11 +28,12 @@
|
||||
|
||||
typedef std::list<AUD_SequencerReader*>::iterator AUD_ReaderIterator;
|
||||
|
||||
AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, void* data, AUD_volumeFunction volume)
|
||||
AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, void* data,
|
||||
AUD_volumeFunction volume) :
|
||||
m_specs(specs),
|
||||
m_data(data),
|
||||
m_volume(volume)
|
||||
{
|
||||
m_specs = specs;
|
||||
m_data = data;
|
||||
m_volume = volume;
|
||||
}
|
||||
|
||||
AUD_SequencerFactory::~AUD_SequencerFactory()
|
||||
@@ -51,13 +52,23 @@ AUD_SequencerFactory::~AUD_SequencerFactory()
|
||||
{
|
||||
entry = m_entries.front();
|
||||
m_entries.pop_front();
|
||||
delete entry; AUD_DELETE("seqentry")
|
||||
delete entry;
|
||||
}
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_SequencerFactory::newReader()
|
||||
{
|
||||
AUD_SequencerReader* reader = new AUD_SequencerReader(this, m_entries,
|
||||
m_specs, m_data,
|
||||
m_volume);
|
||||
m_readers.push_front(reader);
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
AUD_SequencerEntry* AUD_SequencerFactory::add(AUD_IFactory** sound, float begin, float end, float skip, void* data)
|
||||
{
|
||||
AUD_SequencerEntry* entry = new AUD_SequencerEntry; AUD_NEW("seqentry")
|
||||
AUD_SequencerEntry* entry = new AUD_SequencerEntry;
|
||||
entry->sound = sound;
|
||||
entry->begin = begin;
|
||||
entry->skip = skip;
|
||||
@@ -80,7 +91,7 @@ void AUD_SequencerFactory::remove(AUD_SequencerEntry* entry)
|
||||
|
||||
m_entries.remove(entry);
|
||||
|
||||
delete entry; AUD_DELETE("seqentry")
|
||||
delete entry;
|
||||
}
|
||||
|
||||
void AUD_SequencerFactory::move(AUD_SequencerEntry* entry, float begin, float end, float skip)
|
||||
@@ -95,12 +106,9 @@ void AUD_SequencerFactory::mute(AUD_SequencerEntry* entry, bool mute)
|
||||
entry->muted = mute;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_SequencerFactory::createReader()
|
||||
AUD_IReader* AUD_SequencerFactory::createReader() const
|
||||
{
|
||||
AUD_SequencerReader* reader = new AUD_SequencerReader(this, m_entries, m_specs, m_data, m_volume); AUD_NEW("reader")
|
||||
m_readers.push_front(reader);
|
||||
|
||||
return reader;
|
||||
return const_cast<AUD_SequencerFactory*>(this)->newReader();
|
||||
}
|
||||
|
||||
void AUD_SequencerFactory::removeReader(AUD_SequencerReader* reader)
|
||||
|
||||
@@ -60,6 +60,12 @@ private:
|
||||
void* m_data;
|
||||
AUD_volumeFunction m_volume;
|
||||
|
||||
AUD_IReader* newReader();
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SequencerFactory(const AUD_SequencerFactory&);
|
||||
AUD_SequencerFactory& operator=(const AUD_SequencerFactory&);
|
||||
|
||||
public:
|
||||
AUD_SequencerFactory(AUD_Specs specs, void* data, AUD_volumeFunction volume);
|
||||
~AUD_SequencerFactory();
|
||||
@@ -69,7 +75,7 @@ public:
|
||||
void move(AUD_SequencerEntry* entry, float begin, float end, float skip);
|
||||
void mute(AUD_SequencerEntry* entry, bool mute);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
|
||||
void removeReader(AUD_SequencerReader* reader);
|
||||
};
|
||||
|
||||
@@ -24,20 +24,22 @@
|
||||
*/
|
||||
|
||||
#include "AUD_SequencerReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
#include "AUD_DefaultMixer.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
typedef std::list<AUD_SequencerStrip*>::iterator AUD_StripIterator;
|
||||
typedef std::list<AUD_SequencerEntry*>::iterator AUD_EntryIterator;
|
||||
|
||||
AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory, std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs, void* data, AUD_volumeFunction volume)
|
||||
AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory,
|
||||
std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs,
|
||||
void* data, AUD_volumeFunction volume)
|
||||
{
|
||||
AUD_DeviceSpecs dspecs;
|
||||
dspecs.specs = specs;
|
||||
dspecs.format = AUD_FORMAT_FLOAT32;
|
||||
|
||||
m_mixer.setSpecs(dspecs);
|
||||
m_mixer = new AUD_DefaultMixer(dspecs);
|
||||
m_factory = factory;
|
||||
m_data = data;
|
||||
m_volume = volume;
|
||||
@@ -46,12 +48,12 @@ AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory, std::lis
|
||||
|
||||
for(AUD_EntryIterator i = entries.begin(); i != entries.end(); i++)
|
||||
{
|
||||
strip = new AUD_SequencerStrip; AUD_NEW("seqstrip")
|
||||
strip = new AUD_SequencerStrip;
|
||||
strip->entry = *i;
|
||||
strip->old_sound = NULL;
|
||||
|
||||
if(strip->old_sound)
|
||||
strip->reader = m_mixer.prepare(strip->old_sound->createReader());
|
||||
strip->reader = m_mixer->prepare(strip->old_sound->createReader());
|
||||
else
|
||||
strip->reader = NULL;
|
||||
|
||||
@@ -59,7 +61,6 @@ AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory, std::lis
|
||||
}
|
||||
|
||||
m_position = 0;
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
}
|
||||
|
||||
AUD_SequencerReader::~AUD_SequencerReader()
|
||||
@@ -75,12 +76,12 @@ AUD_SequencerReader::~AUD_SequencerReader()
|
||||
m_strips.pop_front();
|
||||
if(strip->reader)
|
||||
{
|
||||
delete strip->reader; AUD_DELETE("reader")
|
||||
delete strip->reader;
|
||||
}
|
||||
delete strip; AUD_DELETE("seqstrip")
|
||||
delete strip;
|
||||
}
|
||||
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
delete m_mixer;
|
||||
}
|
||||
|
||||
void AUD_SequencerReader::destroy()
|
||||
@@ -92,19 +93,19 @@ void AUD_SequencerReader::destroy()
|
||||
{
|
||||
strip = m_strips.front();
|
||||
m_strips.pop_front();
|
||||
delete strip; AUD_DELETE("seqstrip")
|
||||
delete strip;
|
||||
}
|
||||
}
|
||||
|
||||
void AUD_SequencerReader::add(AUD_SequencerEntry* entry)
|
||||
{
|
||||
AUD_SequencerStrip* strip = new AUD_SequencerStrip; AUD_NEW("seqstrip")
|
||||
AUD_SequencerStrip* strip = new AUD_SequencerStrip;
|
||||
strip->entry = entry;
|
||||
|
||||
if(*strip->entry->sound)
|
||||
{
|
||||
strip->old_sound = *strip->entry->sound;
|
||||
strip->reader = m_mixer.prepare(strip->old_sound->createReader());
|
||||
strip->reader = m_mixer->prepare(strip->old_sound->createReader());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -125,16 +126,16 @@ void AUD_SequencerReader::remove(AUD_SequencerEntry* entry)
|
||||
i++;
|
||||
if(strip->reader)
|
||||
{
|
||||
delete strip->reader; AUD_DELETE("reader")
|
||||
delete strip->reader;
|
||||
}
|
||||
m_strips.remove(strip);
|
||||
delete strip; AUD_DELETE("seqstrip")
|
||||
delete strip;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AUD_SequencerReader::isSeekable()
|
||||
bool AUD_SequencerReader::isSeekable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -144,44 +145,24 @@ void AUD_SequencerReader::seek(int position)
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
int AUD_SequencerReader::getLength()
|
||||
int AUD_SequencerReader::getLength() const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int AUD_SequencerReader::getPosition()
|
||||
int AUD_SequencerReader::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
AUD_Specs AUD_SequencerReader::getSpecs()
|
||||
AUD_Specs AUD_SequencerReader::getSpecs() const
|
||||
{
|
||||
return m_mixer.getSpecs().specs;
|
||||
}
|
||||
|
||||
AUD_ReaderType AUD_SequencerReader::getType()
|
||||
{
|
||||
return AUD_TYPE_STREAM;
|
||||
}
|
||||
|
||||
bool AUD_SequencerReader::notify(AUD_Message &message)
|
||||
{
|
||||
bool result = false;
|
||||
AUD_SequencerStrip* strip;
|
||||
|
||||
for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
|
||||
{
|
||||
strip = *i;
|
||||
if(strip->reader)
|
||||
result |= (*i)->reader->notify(message);
|
||||
}
|
||||
|
||||
return result;
|
||||
return m_mixer->getSpecs().specs;
|
||||
}
|
||||
|
||||
void AUD_SequencerReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
AUD_DeviceSpecs specs = m_mixer.getSpecs();
|
||||
AUD_DeviceSpecs specs = m_mixer->getSpecs();
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
int rate = specs.rate;
|
||||
|
||||
@@ -191,9 +172,9 @@ void AUD_SequencerReader::read(int & length, sample_t* & buffer)
|
||||
AUD_SequencerStrip* strip;
|
||||
sample_t* buf;
|
||||
|
||||
if(m_buffer->getSize() < size)
|
||||
m_buffer->resize(size);
|
||||
buffer = m_buffer->getBuffer();
|
||||
if(m_buffer.getSize() < size)
|
||||
m_buffer.resize(size);
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++)
|
||||
{
|
||||
@@ -204,12 +185,10 @@ void AUD_SequencerReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
strip->old_sound = *strip->entry->sound;
|
||||
if(strip->reader)
|
||||
{
|
||||
delete strip->reader; AUD_DELETE("reader")
|
||||
}
|
||||
delete strip->reader;
|
||||
|
||||
if(strip->old_sound)
|
||||
strip->reader = m_mixer.prepare(strip->old_sound->createReader());
|
||||
strip->reader = m_mixer->prepare(strip->old_sound->createReader());
|
||||
else
|
||||
strip->reader = NULL;
|
||||
}
|
||||
@@ -236,14 +215,14 @@ void AUD_SequencerReader::read(int & length, sample_t* & buffer)
|
||||
if(strip->reader->getPosition() != current)
|
||||
strip->reader->seek(current);
|
||||
strip->reader->read(len, buf);
|
||||
m_mixer.add(buf, skip, len, m_volume(m_data, strip->entry->data, (float)m_position / (float)rate));
|
||||
m_mixer->add(buf, skip, len, m_volume(m_data, strip->entry->data, (float)m_position / (float)rate));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_mixer.superpose((data_t*)buffer, length, 1.0f);
|
||||
m_mixer->superpose((data_t*)buffer, length, 1.0f);
|
||||
|
||||
m_position += length;
|
||||
}
|
||||
|
||||
@@ -28,9 +28,8 @@
|
||||
|
||||
#include "AUD_IReader.h"
|
||||
#include "AUD_SequencerFactory.h"
|
||||
#include "AUD_Mixer.h"
|
||||
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
class AUD_Mixer;
|
||||
|
||||
struct AUD_SequencerStrip
|
||||
{
|
||||
@@ -53,12 +52,12 @@ private:
|
||||
/**
|
||||
* The sound output buffer.
|
||||
*/
|
||||
AUD_Buffer *m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The target specification.
|
||||
*/
|
||||
AUD_Mixer m_mixer;
|
||||
AUD_Mixer* m_mixer;
|
||||
|
||||
/**
|
||||
* Saves the SequencerFactory the reader belongs to.
|
||||
@@ -70,14 +69,17 @@ private:
|
||||
void* m_data;
|
||||
AUD_volumeFunction m_volume;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SequencerReader(const AUD_SequencerReader&);
|
||||
AUD_SequencerReader& operator=(const AUD_SequencerReader&);
|
||||
|
||||
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_SequencerReader(AUD_SequencerFactory* factory, std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs, void* data, AUD_volumeFunction volume);
|
||||
AUD_SequencerReader(AUD_SequencerFactory* factory, std::list<AUD_SequencerEntry*> &entries, const AUD_Specs specs, void* data, AUD_volumeFunction volume);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
@@ -89,13 +91,11 @@ public:
|
||||
void add(AUD_SequencerEntry* entry);
|
||||
void remove(AUD_SequencerEntry* entry);
|
||||
|
||||
virtual bool isSeekable();
|
||||
virtual bool isSeekable() const;
|
||||
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 int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -23,19 +23,15 @@
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef AUD_SOURCECAPS
|
||||
#define AUD_SOURCECAPS
|
||||
#include "AUD_SilenceFactory.h"
|
||||
#include "AUD_SilenceReader.h"
|
||||
#include "AUD_Space.h"
|
||||
|
||||
#include "AUD_IDevice.h"
|
||||
|
||||
/// The structure for source capabilities.
|
||||
typedef struct
|
||||
AUD_SilenceFactory::AUD_SilenceFactory()
|
||||
{
|
||||
/// The source to apply the capability on.
|
||||
AUD_Handle* handle;
|
||||
}
|
||||
|
||||
/// The value for the capability.
|
||||
float value;
|
||||
} AUD_SourceCaps;
|
||||
|
||||
#endif //AUD_SOURCECAPS
|
||||
AUD_IReader* AUD_SilenceFactory::createReader() const
|
||||
{
|
||||
return new AUD_SilenceReader();
|
||||
}
|
||||
@@ -23,37 +23,28 @@
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef AUD_RECTIFYREADER
|
||||
#define AUD_RECTIFYREADER
|
||||
#ifndef AUD_SILENCEFACTORY
|
||||
#define AUD_SILENCEFACTORY
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_IFactory.h"
|
||||
|
||||
/**
|
||||
* This class reads another reader and rectifies it.
|
||||
* This factory creates a reader that plays a sine tone.
|
||||
*/
|
||||
class AUD_RectifyReader : public AUD_EffectReader
|
||||
class AUD_SilenceFactory : public AUD_IFactory
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer *m_buffer;
|
||||
// hide copy constructor and operator=
|
||||
AUD_SilenceFactory(const AUD_SilenceFactory&);
|
||||
AUD_SilenceFactory& operator=(const AUD_SilenceFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new rectify reader.
|
||||
* \param reader The reader to read from.
|
||||
* \exception AUD_Exception Thrown if the reader specified is NULL.
|
||||
* Creates a new silence factory.
|
||||
*/
|
||||
AUD_RectifyReader(AUD_IReader* reader);
|
||||
AUD_SilenceFactory();
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
*/
|
||||
virtual ~AUD_RectifyReader();
|
||||
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_RECTIFYREADER
|
||||
#endif //AUD_SILENCEFACTORY
|
||||
@@ -23,41 +23,52 @@
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#include "AUD_SquareReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
#include "AUD_SilenceReader.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_SquareReader::AUD_SquareReader(AUD_IReader* reader, float threshold) :
|
||||
AUD_EffectReader(reader),
|
||||
m_threshold(threshold)
|
||||
AUD_SilenceReader::AUD_SilenceReader() :
|
||||
m_position(0)
|
||||
{
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
}
|
||||
|
||||
AUD_SquareReader::~AUD_SquareReader()
|
||||
bool AUD_SilenceReader::isSeekable() const
|
||||
{
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
return true;
|
||||
}
|
||||
|
||||
void AUD_SquareReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_SilenceReader::seek(int position)
|
||||
{
|
||||
sample_t* buf;
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
m_reader->read(length, buf);
|
||||
if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(specs))
|
||||
m_buffer->resize(length * AUD_SAMPLE_SIZE(specs));
|
||||
int AUD_SilenceReader::getLength() const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer = m_buffer->getBuffer();
|
||||
int AUD_SilenceReader::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
for(int i = 0; i < length * specs.channels; i++)
|
||||
AUD_Specs AUD_SilenceReader::getSpecs() const
|
||||
{
|
||||
AUD_Specs specs;
|
||||
specs.rate = AUD_RATE_44100;
|
||||
specs.channels = AUD_CHANNELS_MONO;
|
||||
return specs;
|
||||
}
|
||||
|
||||
void AUD_SilenceReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
// resize if necessary
|
||||
if(m_buffer.getSize() < length * sizeof(sample_t))
|
||||
{
|
||||
if(buf[i] >= m_threshold)
|
||||
buffer[i] = 1.0f;
|
||||
else if(buf[i] <= -m_threshold)
|
||||
buffer[i] = -1.0f;
|
||||
else
|
||||
buffer[i] = 0.0f;
|
||||
m_buffer.resize(length * sizeof(sample_t));
|
||||
memset(m_buffer.getBuffer(), 0, m_buffer.getSize());
|
||||
}
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
m_position += length;
|
||||
}
|
||||
@@ -23,61 +23,49 @@
|
||||
* ***** END LGPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
#ifndef AUD_LOWPASSREADER
|
||||
#define AUD_LOWPASSREADER
|
||||
#ifndef AUD_SILENCEREADER
|
||||
#define AUD_SILENCEREADER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
class AUD_Buffer;
|
||||
|
||||
#define AUD_LOWPASS_ORDER 3
|
||||
#include "AUD_IReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
/**
|
||||
* This class represents a lowpass filter.
|
||||
* This class is used for sine tone playback.
|
||||
* The output format is in the 16 bit format and stereo, the sample rate can be
|
||||
* specified.
|
||||
* As the two channels both play the same the output could also be mono, but
|
||||
* in most cases this will result in having to resample for output, so stereo
|
||||
* sound is created directly.
|
||||
*/
|
||||
class AUD_LowpassReader : public AUD_EffectReader
|
||||
class AUD_SilenceReader : public AUD_IReader
|
||||
{
|
||||
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.
|
||||
* The current position in samples.
|
||||
*/
|
||||
int m_position;
|
||||
|
||||
/**
|
||||
* Filter coefficients.
|
||||
* The playback buffer.
|
||||
*/
|
||||
float m_coeff[2][AUD_LOWPASS_ORDER];
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SilenceReader(const AUD_SilenceReader&);
|
||||
AUD_SilenceReader& operator=(const AUD_SilenceReader&);
|
||||
|
||||
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.
|
||||
* Creates a new reader.
|
||||
*/
|
||||
AUD_LowpassReader(AUD_IReader* reader, float frequency, float Q);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
*/
|
||||
virtual ~AUD_LowpassReader();
|
||||
AUD_SilenceReader();
|
||||
|
||||
virtual bool isSeekable() const;
|
||||
virtual void seek(int position);
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_LOWPASSREADER
|
||||
#endif //AUD_SILENCEREADER
|
||||
@@ -27,25 +27,18 @@
|
||||
#include "AUD_SinusReader.h"
|
||||
#include "AUD_Space.h"
|
||||
|
||||
AUD_SinusFactory::AUD_SinusFactory(double frequency, AUD_SampleRate sampleRate)
|
||||
AUD_SinusFactory::AUD_SinusFactory(float frequency, AUD_SampleRate sampleRate) :
|
||||
m_frequency(frequency),
|
||||
m_sampleRate(sampleRate)
|
||||
{
|
||||
m_frequency = frequency;
|
||||
m_sampleRate = sampleRate;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_SinusFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader = new AUD_SinusReader(m_frequency, m_sampleRate);
|
||||
AUD_NEW("reader")
|
||||
return reader;
|
||||
}
|
||||
|
||||
double AUD_SinusFactory::getFrequency()
|
||||
float AUD_SinusFactory::getFrequency() const
|
||||
{
|
||||
return m_frequency;
|
||||
}
|
||||
|
||||
void AUD_SinusFactory::setFrequency(double frequency)
|
||||
AUD_IReader* AUD_SinusFactory::createReader() const
|
||||
{
|
||||
m_frequency = frequency;
|
||||
return new AUD_SinusReader(m_frequency, m_sampleRate);
|
||||
}
|
||||
|
||||
@@ -37,12 +37,16 @@ private:
|
||||
/**
|
||||
* The frequence of the sine wave.
|
||||
*/
|
||||
double m_frequency;
|
||||
const float m_frequency;
|
||||
|
||||
/**
|
||||
* The target sample rate for output.
|
||||
*/
|
||||
AUD_SampleRate m_sampleRate;
|
||||
const AUD_SampleRate m_sampleRate;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SinusFactory(const AUD_SinusFactory&);
|
||||
AUD_SinusFactory& operator=(const AUD_SinusFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -50,21 +54,15 @@ public:
|
||||
* \param frequency The desired frequency.
|
||||
* \param sampleRate The target sample rate for playback.
|
||||
*/
|
||||
AUD_SinusFactory(double frequency,
|
||||
AUD_SinusFactory(float frequency,
|
||||
AUD_SampleRate sampleRate = AUD_RATE_44100);
|
||||
|
||||
/**
|
||||
* Returns the frequency of the sine wave.
|
||||
*/
|
||||
double getFrequency();
|
||||
float getFrequency() const;
|
||||
|
||||
/**
|
||||
* Sets the frequency.
|
||||
* \param frequency The new frequency.
|
||||
*/
|
||||
void setFrequency(double frequency);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_SINUSFACTORY
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
*/
|
||||
|
||||
#include "AUD_SinusReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@@ -32,20 +31,14 @@
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
AUD_SinusReader::AUD_SinusReader(double frequency, AUD_SampleRate sampleRate)
|
||||
AUD_SinusReader::AUD_SinusReader(float frequency, AUD_SampleRate sampleRate) :
|
||||
m_frequency(frequency),
|
||||
m_position(0),
|
||||
m_sampleRate(sampleRate)
|
||||
{
|
||||
m_frequency = frequency;
|
||||
m_position = 0;
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
m_sampleRate = sampleRate;
|
||||
}
|
||||
|
||||
AUD_SinusReader::~AUD_SinusReader()
|
||||
{
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
}
|
||||
|
||||
bool AUD_SinusReader::isSeekable()
|
||||
bool AUD_SinusReader::isSeekable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -55,17 +48,17 @@ void AUD_SinusReader::seek(int position)
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
int AUD_SinusReader::getLength()
|
||||
int AUD_SinusReader::getLength() const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int AUD_SinusReader::getPosition()
|
||||
int AUD_SinusReader::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
AUD_Specs AUD_SinusReader::getSpecs()
|
||||
AUD_Specs AUD_SinusReader::getSpecs() const
|
||||
{
|
||||
AUD_Specs specs;
|
||||
specs.rate = m_sampleRate;
|
||||
@@ -73,27 +66,17 @@ AUD_Specs AUD_SinusReader::getSpecs()
|
||||
return specs;
|
||||
}
|
||||
|
||||
AUD_ReaderType AUD_SinusReader::getType()
|
||||
{
|
||||
return AUD_TYPE_STREAM;
|
||||
}
|
||||
|
||||
bool AUD_SinusReader::notify(AUD_Message &message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void AUD_SinusReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
// resize if necessary
|
||||
if(m_buffer->getSize() < length * sizeof(sample_t))
|
||||
m_buffer->resize(length * sizeof(sample_t));
|
||||
if(m_buffer.getSize() < length * sizeof(sample_t))
|
||||
m_buffer.resize(length * sizeof(sample_t));
|
||||
|
||||
// fill with sine data
|
||||
buffer = m_buffer->getBuffer();
|
||||
buffer = m_buffer.getBuffer();
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
buffer[i] = sin((m_position + i) * 2.0f * M_PI * m_frequency /
|
||||
buffer[i] = sin((m_position + i) * 2 * M_PI * m_frequency /
|
||||
(float)m_sampleRate);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#define AUD_SINUSREADER
|
||||
|
||||
#include "AUD_IReader.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
/**
|
||||
* This class is used for sine tone playback.
|
||||
@@ -43,7 +43,7 @@ private:
|
||||
/**
|
||||
* The frequency of the sine wave.
|
||||
*/
|
||||
double m_frequency;
|
||||
const float m_frequency;
|
||||
|
||||
/**
|
||||
* The current position in samples.
|
||||
@@ -53,12 +53,16 @@ private:
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer* m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The sample rate for the output.
|
||||
*/
|
||||
AUD_SampleRate m_sampleRate;
|
||||
const AUD_SampleRate m_sampleRate;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SinusReader(const AUD_SinusReader&);
|
||||
AUD_SinusReader& operator=(const AUD_SinusReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -66,20 +70,13 @@ public:
|
||||
* \param frequency The frequency of the sine wave.
|
||||
* \param sampleRate The output sample rate.
|
||||
*/
|
||||
AUD_SinusReader(double frequency, AUD_SampleRate sampleRate);
|
||||
AUD_SinusReader(float frequency, AUD_SampleRate sampleRate);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
*/
|
||||
virtual ~AUD_SinusReader();
|
||||
|
||||
virtual bool isSeekable();
|
||||
virtual bool isSeekable() const;
|
||||
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 int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
|
||||
#include "AUD_SoftwareDevice.h"
|
||||
#include "AUD_IReader.h"
|
||||
#include "AUD_Mixer.h"
|
||||
#include "AUD_DefaultMixer.h"
|
||||
#include "AUD_IFactory.h"
|
||||
#include "AUD_SourceCaps.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
/// Saves the data for playback.
|
||||
struct AUD_SoftwareHandle : AUD_Handle
|
||||
@@ -42,18 +42,24 @@ struct AUD_SoftwareHandle : AUD_Handle
|
||||
|
||||
/// The volume of the source.
|
||||
float volume;
|
||||
|
||||
/// The loop count of the source.
|
||||
int loopcount;
|
||||
|
||||
/// The stop callback.
|
||||
stopCallback stop;
|
||||
|
||||
/// Stop callback data.
|
||||
void* stop_data;
|
||||
};
|
||||
|
||||
typedef std::list<AUD_SoftwareHandle*>::iterator AUD_HandleIterator;
|
||||
|
||||
void AUD_SoftwareDevice::create()
|
||||
{
|
||||
m_playingSounds = new std::list<AUD_SoftwareHandle*>(); AUD_NEW("list")
|
||||
m_pausedSounds = new std::list<AUD_SoftwareHandle*>(); AUD_NEW("list")
|
||||
m_playback = false;
|
||||
m_volume = 1.0f;
|
||||
m_mixer = new AUD_Mixer(); AUD_NEW("mixer")
|
||||
m_mixer->setSpecs(m_specs);
|
||||
m_mixer = new AUD_DefaultMixer(m_specs);
|
||||
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
@@ -69,25 +75,27 @@ void AUD_SoftwareDevice::destroy()
|
||||
if(m_playback)
|
||||
playing(m_playback = false);
|
||||
|
||||
delete m_mixer; AUD_DELETE("mixer")
|
||||
delete m_mixer;
|
||||
|
||||
AUD_SoftwareHandle* handle;
|
||||
|
||||
// delete all playing sounds
|
||||
while(m_playingSounds->begin() != m_playingSounds->end())
|
||||
while(!m_playingSounds.empty())
|
||||
{
|
||||
delete (*(m_playingSounds->begin()))->reader; AUD_DELETE("reader")
|
||||
delete *(m_playingSounds->begin()); AUD_DELETE("handle")
|
||||
m_playingSounds->erase(m_playingSounds->begin());
|
||||
handle = m_playingSounds.front();
|
||||
m_playingSounds.pop_front();
|
||||
delete handle->reader;
|
||||
delete handle;
|
||||
}
|
||||
delete m_playingSounds; AUD_DELETE("list")
|
||||
|
||||
// delete all paused sounds
|
||||
while(m_pausedSounds->begin() != m_pausedSounds->end())
|
||||
while(!m_pausedSounds.empty())
|
||||
{
|
||||
delete (*(m_pausedSounds->begin()))->reader; AUD_DELETE("reader")
|
||||
delete *(m_pausedSounds->begin()); AUD_DELETE("handle")
|
||||
m_pausedSounds->erase(m_pausedSounds->begin());
|
||||
handle = m_pausedSounds.front();
|
||||
m_pausedSounds.pop_front();
|
||||
delete handle->reader;
|
||||
delete handle;
|
||||
}
|
||||
delete m_pausedSounds; AUD_DELETE("list")
|
||||
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
}
|
||||
@@ -99,12 +107,16 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
|
||||
{
|
||||
AUD_SoftwareHandle* sound;
|
||||
int len;
|
||||
int pos;
|
||||
sample_t* buf;
|
||||
std::list<AUD_SoftwareHandle*> stopSounds;
|
||||
std::list<AUD_Buffer*> tempBufs;
|
||||
AUD_Buffer* tempbuf;
|
||||
int samplesize = AUD_SAMPLE_SIZE(m_specs);
|
||||
|
||||
// for all sounds
|
||||
AUD_HandleIterator it = m_playingSounds->begin();
|
||||
while(it != m_playingSounds->end())
|
||||
AUD_HandleIterator it = m_playingSounds.begin();
|
||||
while(it != m_playingSounds.end())
|
||||
{
|
||||
sound = *it;
|
||||
// increment the iterator to make sure it's valid,
|
||||
@@ -112,14 +124,42 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
|
||||
++it;
|
||||
|
||||
// get the buffer from the source
|
||||
pos = 0;
|
||||
len = length;
|
||||
sound->reader->read(len, buf);
|
||||
|
||||
m_mixer->add(buf, 0, len, sound->volume);
|
||||
// in case of looping
|
||||
while(pos + len < length && sound->loopcount)
|
||||
{
|
||||
tempbuf = new AUD_Buffer(len * samplesize);
|
||||
memcpy(tempbuf->getBuffer(), buf, len * samplesize);
|
||||
tempBufs.push_back(tempbuf);
|
||||
m_mixer->add(tempbuf->getBuffer(), pos, len, sound->volume);
|
||||
|
||||
pos += len;
|
||||
|
||||
if(sound->loopcount > 0)
|
||||
sound->loopcount--;
|
||||
|
||||
sound->reader->seek(0);
|
||||
|
||||
len = length - pos;
|
||||
sound->reader->read(len, buf);
|
||||
|
||||
// prevent endless loop
|
||||
if(!len)
|
||||
break;
|
||||
}
|
||||
|
||||
m_mixer->add(buf, pos, len, sound->volume);
|
||||
pos += len;
|
||||
|
||||
// in case the end of the sound is reached
|
||||
if(len < length)
|
||||
if(pos < length)
|
||||
{
|
||||
if(sound->stop)
|
||||
sound->stop(sound->stop_data);
|
||||
|
||||
if(sound->keep)
|
||||
pause(sound);
|
||||
else
|
||||
@@ -130,12 +170,20 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
|
||||
// superpose
|
||||
m_mixer->superpose(buffer, length, m_volume);
|
||||
|
||||
// cleanup
|
||||
while(!stopSounds.empty())
|
||||
{
|
||||
sound = stopSounds.front();
|
||||
stopSounds.pop_front();
|
||||
stop(sound);
|
||||
}
|
||||
|
||||
while(!tempBufs.empty())
|
||||
{
|
||||
tempbuf = tempBufs.front();
|
||||
tempBufs.pop_front();
|
||||
delete tempbuf;
|
||||
}
|
||||
}
|
||||
|
||||
unlock();
|
||||
@@ -143,18 +191,18 @@ void AUD_SoftwareDevice::mix(data_t* buffer, int length)
|
||||
|
||||
bool AUD_SoftwareDevice::isValid(AUD_Handle* handle)
|
||||
{
|
||||
for(AUD_HandleIterator i = m_playingSounds->begin();
|
||||
i != m_playingSounds->end(); i++)
|
||||
for(AUD_HandleIterator i = m_playingSounds.begin();
|
||||
i != m_playingSounds.end(); i++)
|
||||
if(*i == handle)
|
||||
return true;
|
||||
for(AUD_HandleIterator i = m_pausedSounds->begin();
|
||||
i != m_pausedSounds->end(); i++)
|
||||
for(AUD_HandleIterator i = m_pausedSounds.begin();
|
||||
i != m_pausedSounds.end(); i++)
|
||||
if(*i == handle)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs()
|
||||
AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const
|
||||
{
|
||||
return m_specs;
|
||||
}
|
||||
@@ -163,24 +211,22 @@ AUD_Handle* AUD_SoftwareDevice::play(AUD_IFactory* factory, bool keep)
|
||||
{
|
||||
AUD_IReader* reader = factory->createReader();
|
||||
|
||||
if(reader == NULL)
|
||||
AUD_THROW(AUD_ERROR_READER);
|
||||
|
||||
// prepare the reader
|
||||
reader = m_mixer->prepare(reader);
|
||||
if(reader == NULL)
|
||||
return NULL;
|
||||
|
||||
AUD_Specs rs = reader->getSpecs();
|
||||
|
||||
// play sound
|
||||
AUD_SoftwareHandle* sound = new AUD_SoftwareHandle; AUD_NEW("handle")
|
||||
AUD_SoftwareHandle* sound = new AUD_SoftwareHandle;
|
||||
sound->keep = keep;
|
||||
sound->reader = reader;
|
||||
sound->volume = 1.0f;
|
||||
sound->loopcount = 0;
|
||||
sound->stop = NULL;
|
||||
sound->stop_data = NULL;
|
||||
|
||||
lock();
|
||||
m_playingSounds->push_back(sound);
|
||||
m_playingSounds.push_back(sound);
|
||||
|
||||
if(!m_playback)
|
||||
playing(m_playback = true);
|
||||
@@ -196,14 +242,14 @@ bool AUD_SoftwareDevice::pause(AUD_Handle* handle)
|
||||
lock();
|
||||
|
||||
// only songs that are played can be paused
|
||||
for(AUD_HandleIterator i = m_playingSounds->begin();
|
||||
i != m_playingSounds->end(); i++)
|
||||
for(AUD_HandleIterator i = m_playingSounds.begin();
|
||||
i != m_playingSounds.end(); i++)
|
||||
{
|
||||
if(*i == handle)
|
||||
{
|
||||
m_pausedSounds->push_back(*i);
|
||||
m_playingSounds->erase(i);
|
||||
if(m_playingSounds->empty())
|
||||
m_pausedSounds.push_back(*i);
|
||||
m_playingSounds.erase(i);
|
||||
if(m_playingSounds.empty())
|
||||
playing(m_playback = false);
|
||||
result = true;
|
||||
break;
|
||||
@@ -222,13 +268,13 @@ bool AUD_SoftwareDevice::resume(AUD_Handle* handle)
|
||||
lock();
|
||||
|
||||
// only songs that are paused can be resumed
|
||||
for(AUD_HandleIterator i = m_pausedSounds->begin();
|
||||
i != m_pausedSounds->end(); i++)
|
||||
for(AUD_HandleIterator i = m_pausedSounds.begin();
|
||||
i != m_pausedSounds.end(); i++)
|
||||
{
|
||||
if(*i == handle)
|
||||
{
|
||||
m_playingSounds->push_back(*i);
|
||||
m_pausedSounds->erase(i);
|
||||
m_playingSounds.push_back(*i);
|
||||
m_pausedSounds.erase(i);
|
||||
if(!m_playback)
|
||||
playing(m_playback = true);
|
||||
result = true;
|
||||
@@ -247,15 +293,15 @@ bool AUD_SoftwareDevice::stop(AUD_Handle* handle)
|
||||
|
||||
lock();
|
||||
|
||||
for(AUD_HandleIterator i = m_playingSounds->begin();
|
||||
i != m_playingSounds->end(); i++)
|
||||
for(AUD_HandleIterator i = m_playingSounds.begin();
|
||||
i != m_playingSounds.end(); i++)
|
||||
{
|
||||
if(*i == handle)
|
||||
{
|
||||
delete (*i)->reader; AUD_DELETE("reader")
|
||||
delete *i; AUD_DELETE("handle")
|
||||
m_playingSounds->erase(i);
|
||||
if(m_playingSounds->empty())
|
||||
delete (*i)->reader;
|
||||
delete *i;
|
||||
m_playingSounds.erase(i);
|
||||
if(m_playingSounds.empty())
|
||||
playing(m_playback = false);
|
||||
result = true;
|
||||
break;
|
||||
@@ -263,14 +309,14 @@ bool AUD_SoftwareDevice::stop(AUD_Handle* handle)
|
||||
}
|
||||
if(!result)
|
||||
{
|
||||
for(AUD_HandleIterator i = m_pausedSounds->begin();
|
||||
i != m_pausedSounds->end(); i++)
|
||||
for(AUD_HandleIterator i = m_pausedSounds.begin();
|
||||
i != m_pausedSounds.end(); i++)
|
||||
{
|
||||
if(*i == handle)
|
||||
{
|
||||
delete (*i)->reader; AUD_DELETE("reader")
|
||||
delete *i; AUD_DELETE("handle")
|
||||
m_pausedSounds->erase(i);
|
||||
delete (*i)->reader;
|
||||
delete *i;
|
||||
m_pausedSounds.erase(i);
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
@@ -282,6 +328,20 @@ bool AUD_SoftwareDevice::stop(AUD_Handle* handle)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_SoftwareDevice::getKeep(AUD_Handle* handle)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
lock();
|
||||
|
||||
if(isValid(handle))
|
||||
result = ((AUD_SoftwareHandle*)handle)->keep;
|
||||
|
||||
unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_SoftwareDevice::setKeep(AUD_Handle* handle, bool keep)
|
||||
{
|
||||
bool result = false;
|
||||
@@ -299,27 +359,6 @@ bool AUD_SoftwareDevice::setKeep(AUD_Handle* handle, bool keep)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_SoftwareDevice::sendMessage(AUD_Handle* handle, AUD_Message &message)
|
||||
{
|
||||
lock();
|
||||
|
||||
bool result = false;
|
||||
|
||||
if(handle == 0)
|
||||
{
|
||||
for(AUD_HandleIterator i = m_playingSounds->begin();
|
||||
i != m_playingSounds->end(); i++)
|
||||
result |= (*i)->reader->notify(message);
|
||||
for(AUD_HandleIterator i = m_pausedSounds->begin();
|
||||
i != m_pausedSounds->end(); i++)
|
||||
result |= (*i)->reader->notify(message);
|
||||
}
|
||||
else if(isValid(handle))
|
||||
result = ((AUD_SoftwareHandle*)handle)->reader->notify(message);
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_SoftwareDevice::seek(AUD_Handle* handle, float position)
|
||||
{
|
||||
lock();
|
||||
@@ -361,8 +400,8 @@ AUD_Status AUD_SoftwareDevice::getStatus(AUD_Handle* handle)
|
||||
|
||||
lock();
|
||||
|
||||
for(AUD_HandleIterator i = m_playingSounds->begin();
|
||||
i != m_playingSounds->end(); i++)
|
||||
for(AUD_HandleIterator i = m_playingSounds.begin();
|
||||
i != m_playingSounds.end(); i++)
|
||||
{
|
||||
if(*i == handle)
|
||||
{
|
||||
@@ -372,8 +411,8 @@ AUD_Status AUD_SoftwareDevice::getStatus(AUD_Handle* handle)
|
||||
}
|
||||
if(status == AUD_STATUS_INVALID)
|
||||
{
|
||||
for(AUD_HandleIterator i = m_pausedSounds->begin();
|
||||
i != m_pausedSounds->end(); i++)
|
||||
for(AUD_HandleIterator i = m_pausedSounds.begin();
|
||||
i != m_pausedSounds.end(); i++)
|
||||
{
|
||||
if(*i == handle)
|
||||
{
|
||||
@@ -398,77 +437,76 @@ void AUD_SoftwareDevice::unlock()
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
}
|
||||
|
||||
bool AUD_SoftwareDevice::checkCapability(int capability)
|
||||
float AUD_SoftwareDevice::getVolume() const
|
||||
{
|
||||
return capability == AUD_CAPS_SOFTWARE_DEVICE ||
|
||||
capability == AUD_CAPS_VOLUME ||
|
||||
capability == AUD_CAPS_SOURCE_VOLUME;
|
||||
return m_volume;
|
||||
}
|
||||
|
||||
bool AUD_SoftwareDevice::setCapability(int capability, void *value)
|
||||
void AUD_SoftwareDevice::setVolume(float volume)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
switch(capability)
|
||||
{
|
||||
case AUD_CAPS_VOLUME:
|
||||
lock();
|
||||
m_volume = *((float*)value);
|
||||
if(m_volume > 1.0f)
|
||||
m_volume = 1.0f;
|
||||
else if(m_volume < 0.0f)
|
||||
m_volume = 0.0f;
|
||||
unlock();
|
||||
return true;
|
||||
case AUD_CAPS_SOURCE_VOLUME:
|
||||
{
|
||||
AUD_SourceCaps* caps = (AUD_SourceCaps*) value;
|
||||
lock();
|
||||
if(isValid(caps->handle))
|
||||
{
|
||||
AUD_SoftwareHandle* handle = (AUD_SoftwareHandle*)caps->handle;
|
||||
handle->volume = caps->value;
|
||||
if(handle->volume > 1.0f)
|
||||
handle->volume = 1.0f;
|
||||
else if(handle->volume < 0.0f)
|
||||
handle->volume = 0.0f;
|
||||
result = true;
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return result;;
|
||||
m_volume = volume;
|
||||
}
|
||||
|
||||
bool AUD_SoftwareDevice::getCapability(int capability, void *value)
|
||||
float AUD_SoftwareDevice::getVolume(AUD_Handle* handle)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
switch(capability)
|
||||
{
|
||||
case AUD_CAPS_VOLUME:
|
||||
lock();
|
||||
*((float*)value) = m_volume;
|
||||
unlock();
|
||||
return true;
|
||||
case AUD_CAPS_SOURCE_VOLUME:
|
||||
{
|
||||
AUD_SourceCaps* caps = (AUD_SourceCaps*) value;
|
||||
|
||||
lock();
|
||||
|
||||
if(isValid(caps->handle))
|
||||
{
|
||||
caps->value = ((AUD_SoftwareHandle*)caps->handle)->volume;
|
||||
result = true;
|
||||
}
|
||||
|
||||
unlock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
lock();
|
||||
float result = std::numeric_limits<float>::quiet_NaN();
|
||||
if(isValid(handle))
|
||||
result = ((AUD_SoftwareHandle*)handle)->volume;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_SoftwareDevice::setVolume(AUD_Handle* handle, float volume)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
if(result)
|
||||
((AUD_SoftwareHandle*)handle)->volume = volume;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
float AUD_SoftwareDevice::getPitch(AUD_Handle* handle)
|
||||
{
|
||||
return std::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
|
||||
bool AUD_SoftwareDevice::setPitch(AUD_Handle* handle, float pitch)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int AUD_SoftwareDevice::getLoopCount(AUD_Handle* handle)
|
||||
{
|
||||
lock();
|
||||
int result = 0;
|
||||
if(isValid(handle))
|
||||
result = ((AUD_SoftwareHandle*)handle)->loopcount;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_SoftwareDevice::setLoopCount(AUD_Handle* handle, int count)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
if(result)
|
||||
((AUD_SoftwareHandle*)handle)->loopcount = count;
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AUD_SoftwareDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data)
|
||||
{
|
||||
lock();
|
||||
bool result = isValid(handle);
|
||||
if(result)
|
||||
{
|
||||
AUD_SoftwareHandle* h = (AUD_SoftwareHandle*)handle;
|
||||
h->stop = callback;
|
||||
h->stop_data = data;
|
||||
}
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "AUD_IDevice.h"
|
||||
struct AUD_SoftwareHandle;
|
||||
class AUD_Mixer;
|
||||
class AUD_Buffer;
|
||||
|
||||
#include <list>
|
||||
#include <pthread.h>
|
||||
@@ -81,12 +82,12 @@ private:
|
||||
/**
|
||||
* The list of sounds that are currently playing.
|
||||
*/
|
||||
std::list<AUD_SoftwareHandle*>* m_playingSounds;
|
||||
std::list<AUD_SoftwareHandle*> m_playingSounds;
|
||||
|
||||
/**
|
||||
* The list of sounds that are currently paused.
|
||||
*/
|
||||
std::list<AUD_SoftwareHandle*>* m_pausedSounds;
|
||||
std::list<AUD_SoftwareHandle*> m_pausedSounds;
|
||||
|
||||
/**
|
||||
* Whether there is currently playback.
|
||||
@@ -111,21 +112,27 @@ private:
|
||||
bool isValid(AUD_Handle* handle);
|
||||
|
||||
public:
|
||||
virtual AUD_DeviceSpecs getSpecs();
|
||||
virtual AUD_DeviceSpecs getSpecs() const;
|
||||
virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false);
|
||||
virtual bool pause(AUD_Handle* handle);
|
||||
virtual bool resume(AUD_Handle* handle);
|
||||
virtual bool stop(AUD_Handle* handle);
|
||||
virtual bool getKeep(AUD_Handle* handle);
|
||||
virtual bool setKeep(AUD_Handle* handle, bool keep);
|
||||
virtual bool sendMessage(AUD_Handle* handle, AUD_Message &message);
|
||||
virtual bool seek(AUD_Handle* handle, float position);
|
||||
virtual float getPosition(AUD_Handle* handle);
|
||||
virtual AUD_Status getStatus(AUD_Handle* handle);
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
virtual bool checkCapability(int capability);
|
||||
virtual bool setCapability(int capability, void *value);
|
||||
virtual bool getCapability(int capability, void *value);
|
||||
virtual float getVolume() const;
|
||||
virtual void setVolume(float volume);
|
||||
virtual float getVolume(AUD_Handle* handle);
|
||||
virtual bool setVolume(AUD_Handle* handle, float volume);
|
||||
virtual float getPitch(AUD_Handle* handle);
|
||||
virtual bool setPitch(AUD_Handle* handle, float pitch);
|
||||
virtual int getLoopCount(AUD_Handle* handle);
|
||||
virtual bool setLoopCount(AUD_Handle* handle, int count);
|
||||
virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = NULL, void* data = NULL);
|
||||
};
|
||||
|
||||
#endif //AUD_SOFTWAREDEVICE
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
/// The size of a sample in the specified format in bytes.
|
||||
#define AUD_SAMPLE_SIZE(specs) (specs.channels * sizeof(sample_t))
|
||||
/// Throws a AUD_Exception with the provided error code.
|
||||
#define AUD_THROW(exception) { AUD_Exception e; e.error = exception; throw e; }
|
||||
#define AUD_THROW(exception, errorstr) { AUD_Exception e; e.error = exception; e.str = errorstr; throw e; }
|
||||
|
||||
/// Returns the smaller of the two values.
|
||||
#define AUD_MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
@@ -47,64 +47,6 @@
|
||||
/// The default playback buffer size of a device.
|
||||
#define AUD_DEFAULT_BUFFER_SIZE 1024
|
||||
|
||||
// Capability defines
|
||||
|
||||
/// This capability checks whether a device is a 3D device. See AUD_I3DDevice.h.
|
||||
#define AUD_CAPS_3D_DEVICE 0x0001
|
||||
|
||||
/**
|
||||
* This capability checks whether a device is a software device. See
|
||||
* AUD_SoftwareDevice.
|
||||
*/
|
||||
#define AUD_CAPS_SOFTWARE_DEVICE 0x0002
|
||||
|
||||
/**
|
||||
* This capability enables the user to set the overall volume of the device.
|
||||
* You can set and get it with the pointer pointing to a float value between
|
||||
* 0.0 (muted) and 1.0 (maximum volume).
|
||||
*/
|
||||
#define AUD_CAPS_VOLUME 0x0101
|
||||
|
||||
/**
|
||||
* This capability enables the user to set the volume of a source.
|
||||
* You can set and get it with the pointer pointing to a AUD_SourceValue
|
||||
* structure defined in AUD_SourceCaps.h.
|
||||
*/
|
||||
#define AUD_CAPS_SOURCE_VOLUME 0x1001
|
||||
|
||||
/**
|
||||
* This capability enables the user to set the pitch of a source.
|
||||
* You can set and get it with the pointer pointing to a AUD_SourceValue
|
||||
* structure defined in AUD_SourceCaps.h.
|
||||
*/
|
||||
#define AUD_CAPS_SOURCE_PITCH 0x1002
|
||||
|
||||
/**
|
||||
* This capability enables the user to buffer a factory into the device.
|
||||
* Setting with the factory as pointer loads the factory into a device internal
|
||||
* buffer. Play function calls with the buffered factory as argument result in
|
||||
* the internal buffer being played back, so there's no reader created, what
|
||||
* also results in not being able to send messages to that handle.
|
||||
* A repeated call with the same factory doesn't do anything.
|
||||
* A set call with a NULL pointer results in all buffered factories being
|
||||
* deleted.
|
||||
* \note This is only possible with factories that create readers of the buffer
|
||||
* type.
|
||||
*/
|
||||
#define AUD_CAPS_BUFFERED_FACTORY 0x2001
|
||||
|
||||
// Used for debugging memory leaks.
|
||||
//#define AUD_DEBUG_MEMORY
|
||||
|
||||
#ifdef AUD_DEBUG_MEMORY
|
||||
extern int AUD_References(int count, const char* text);
|
||||
#define AUD_NEW(text) AUD_References(1, text);
|
||||
#define AUD_DELETE(text) AUD_References(-1, text);
|
||||
#else
|
||||
#define AUD_NEW(text)
|
||||
#define AUD_DELETE(text)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The format of a sample.
|
||||
* The last 4 bit save the byte count of the format.
|
||||
@@ -154,17 +96,6 @@ typedef enum
|
||||
AUD_RATE_192000 = 192000 /// 192000 Hz.
|
||||
} AUD_SampleRate;
|
||||
|
||||
/**
|
||||
* Type of a reader.
|
||||
* @see AUD_IReader for details.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
AUD_TYPE_INVALID = 0, /// Invalid reader type.
|
||||
AUD_TYPE_BUFFER, /// Reader reads from a buffer.
|
||||
AUD_TYPE_STREAM /// Reader reads from a stream.
|
||||
} AUD_ReaderType;
|
||||
|
||||
/// Status of a playback handle.
|
||||
typedef enum
|
||||
{
|
||||
@@ -177,23 +108,16 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
AUD_NO_ERROR = 0,
|
||||
AUD_ERROR_READER,
|
||||
AUD_ERROR_FACTORY,
|
||||
AUD_ERROR_SPECS,
|
||||
AUD_ERROR_PROPS,
|
||||
AUD_ERROR_FILE,
|
||||
AUD_ERROR_SRC,
|
||||
AUD_ERROR_FFMPEG,
|
||||
AUD_ERROR_SDL,
|
||||
AUD_ERROR_OPENAL,
|
||||
AUD_ERROR_JACK
|
||||
AUD_ERROR_SDL,
|
||||
AUD_ERROR_JACK,
|
||||
} AUD_Error;
|
||||
|
||||
/// Message codes.
|
||||
typedef enum
|
||||
{
|
||||
AUD_MSG_INVALID = 0, /// Invalid message.
|
||||
AUD_MSG_LOOP, /// Loop reader message.
|
||||
AUD_MSG_VOLUME /// Volume reader message.
|
||||
} AUD_MessageType;
|
||||
|
||||
/// Fading types.
|
||||
typedef enum
|
||||
{
|
||||
@@ -201,39 +125,17 @@ typedef enum
|
||||
AUD_FADE_OUT
|
||||
} AUD_FadeType;
|
||||
|
||||
/// 3D device settings.
|
||||
typedef enum
|
||||
{
|
||||
AUD_3DS_NONE, /// No setting.
|
||||
AUD_3DS_SPEED_OF_SOUND, /// Speed of sound.
|
||||
AUD_3DS_DOPPLER_FACTOR, /// Doppler factor.
|
||||
AUD_3DS_DISTANCE_MODEL /// Distance model.
|
||||
} AUD_3DSetting;
|
||||
|
||||
/// Possible distance models for the 3D device.
|
||||
#define AUD_DISTANCE_MODEL_NONE 0.0f
|
||||
#define AUD_DISTANCE_MODEL_INVERSE 1.0f
|
||||
#define AUD_DISTANCE_MODEL_INVERSE_CLAMPED 2.0f
|
||||
#define AUD_DISTANCE_MODEL_LINEAR 3.0f
|
||||
#define AUD_DISTANCE_MODEL_LINEAR_CLAMPED 4.0f
|
||||
#define AUD_DISTANCE_MODEL_EXPONENT 5.0f
|
||||
#define AUD_DISTANCE_MODEL_EXPONENT_CLAMPED 6.0f
|
||||
|
||||
/// 3D source settings.
|
||||
typedef enum
|
||||
{
|
||||
AUD_3DSS_NONE, /// No setting.
|
||||
AUD_3DSS_IS_RELATIVE, /// > 0 tells that the sound source is
|
||||
/// relative to the listener
|
||||
AUD_3DSS_MIN_GAIN, /// Minimum gain.
|
||||
AUD_3DSS_MAX_GAIN, /// Maximum gain.
|
||||
AUD_3DSS_REFERENCE_DISTANCE, /// Reference distance.
|
||||
AUD_3DSS_MAX_DISTANCE, /// Maximum distance.
|
||||
AUD_3DSS_ROLLOFF_FACTOR, /// Rolloff factor.
|
||||
AUD_3DSS_CONE_INNER_ANGLE, /// Cone inner angle.
|
||||
AUD_3DSS_CONE_OUTER_ANGLE, /// Cone outer angle.
|
||||
AUD_3DSS_CONE_OUTER_GAIN /// Cone outer gain.
|
||||
} AUD_3DSourceSetting;
|
||||
AUD_DISTANCE_MODEL_INVALID = 0,
|
||||
AUD_DISTANCE_MODEL_INVERSE,
|
||||
AUD_DISTANCE_MODEL_INVERSE_CLAMPED,
|
||||
AUD_DISTANCE_MODEL_LINEAR,
|
||||
AUD_DISTANCE_MODEL_LINEAR_CLAMPED,
|
||||
AUD_DISTANCE_MODEL_EXPONENT,
|
||||
AUD_DISTANCE_MODEL_EXPONENT_CLAMPED,
|
||||
} AUD_DistanceModel;
|
||||
|
||||
/// Sample type.(float samples)
|
||||
typedef float sample_t;
|
||||
@@ -280,42 +182,12 @@ typedef struct
|
||||
*/
|
||||
AUD_Error error;
|
||||
|
||||
/**
|
||||
* Error string.
|
||||
*/
|
||||
const char* str;
|
||||
|
||||
// void* userData; - for the case it is needed someday
|
||||
} AUD_Exception;
|
||||
|
||||
/// Message structure.
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
* The message type.
|
||||
*/
|
||||
AUD_MessageType type;
|
||||
|
||||
union
|
||||
{
|
||||
// loop reader
|
||||
struct
|
||||
{
|
||||
int loopcount;
|
||||
float time;
|
||||
};
|
||||
|
||||
// volume reader
|
||||
float volume;
|
||||
};
|
||||
} AUD_Message;
|
||||
|
||||
/// Handle structure, for inherition.
|
||||
typedef struct
|
||||
{
|
||||
/// x, y and z coordinates of the object.
|
||||
float position[3];
|
||||
|
||||
/// x, y and z coordinates telling the velocity and direction of the object.
|
||||
float velocity[3];
|
||||
|
||||
/// 3x3 matrix telling the orientation of the object.
|
||||
float orientation[9];
|
||||
} AUD_3DData;
|
||||
|
||||
#endif //AUD_SPACE
|
||||
|
||||
@@ -29,15 +29,12 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory)
|
||||
AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory) :
|
||||
m_buffer(new AUD_Buffer())
|
||||
{
|
||||
AUD_IReader* reader = factory->createReader();
|
||||
|
||||
if(reader == NULL)
|
||||
AUD_THROW(AUD_ERROR_READER);
|
||||
|
||||
m_specs = reader->getSpecs();
|
||||
m_buffer = AUD_Reference<AUD_Buffer>(new AUD_Buffer()); AUD_NEW("buffer")
|
||||
|
||||
int sample_size = AUD_SAMPLE_SIZE(m_specs);
|
||||
int length;
|
||||
@@ -68,13 +65,11 @@ AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory)
|
||||
index += length;
|
||||
}
|
||||
|
||||
m_buffer.get()->resize(index*sample_size, true);
|
||||
delete reader; AUD_DELETE("reader")
|
||||
m_buffer.get()->resize(index * sample_size, true);
|
||||
delete reader;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_StreamBufferFactory::createReader()
|
||||
AUD_IReader* AUD_StreamBufferFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader = new AUD_BufferReader(m_buffer, m_specs);
|
||||
AUD_NEW("reader")
|
||||
return reader;
|
||||
return new AUD_BufferReader(m_buffer, m_specs);
|
||||
}
|
||||
|
||||
@@ -47,6 +47,10 @@ private:
|
||||
*/
|
||||
AUD_Specs m_specs;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_StreamBufferFactory(const AUD_StreamBufferFactory&);
|
||||
AUD_StreamBufferFactory& operator=(const AUD_StreamBufferFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates the factory and reads the reader created by the factory supplied
|
||||
@@ -56,7 +60,7 @@ public:
|
||||
*/
|
||||
AUD_StreamBufferFactory(AUD_IFactory* factory);
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_STREAMBUFFERFACTORY
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "AUD_Mixer.h"
|
||||
#include "AUD_JackDevice.h"
|
||||
#include "AUD_IReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -43,8 +42,8 @@ void AUD_JackDevice::updateRingBuffers()
|
||||
unsigned int samplesize = AUD_SAMPLE_SIZE(m_specs);
|
||||
unsigned int i, j;
|
||||
unsigned int channels = m_specs.channels;
|
||||
sample_t* buffer = m_buffer->getBuffer();
|
||||
float* deinterleave = m_deinterleavebuf->getBuffer();
|
||||
sample_t* buffer = m_buffer.getBuffer();
|
||||
float* deinterleave = m_deinterleavebuf.getBuffer();
|
||||
jack_transport_state_t state;
|
||||
jack_position_t position;
|
||||
|
||||
@@ -173,7 +172,13 @@ void AUD_JackDevice::jack_shutdown(void *data)
|
||||
device->m_valid = false;
|
||||
}
|
||||
|
||||
AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize)
|
||||
static const char* clientopen_error = "AUD_JackDevice: Couldn't connect to "
|
||||
"jack server.";
|
||||
static const char* port_error = "AUD_JackDevice: Couldn't create output port.";
|
||||
static const char* activate_error = "AUD_JackDevice: Couldn't activate the "
|
||||
"client.";
|
||||
|
||||
AUD_JackDevice::AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buffersize)
|
||||
{
|
||||
if(specs.channels == AUD_CHANNELS_INVALID)
|
||||
specs.channels = AUD_CHANNELS_STEREO;
|
||||
@@ -186,9 +191,9 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize)
|
||||
jack_status_t status;
|
||||
|
||||
// open client
|
||||
m_client = jack_client_open("Blender", options, &status);
|
||||
m_client = jack_client_open(name.c_str(), options, &status);
|
||||
if(m_client == NULL)
|
||||
AUD_THROW(AUD_ERROR_JACK);
|
||||
AUD_THROW(AUD_ERROR_JACK, clientopen_error);
|
||||
|
||||
// set callbacks
|
||||
jack_set_process_callback(m_client, AUD_JackDevice::jack_mix, this);
|
||||
@@ -196,7 +201,7 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize)
|
||||
jack_set_sync_callback(m_client, AUD_JackDevice::jack_sync, this);
|
||||
|
||||
// register our output channels which are called ports in jack
|
||||
m_ports = new jack_port_t*[m_specs.channels]; AUD_NEW("jack_port")
|
||||
m_ports = new jack_port_t*[m_specs.channels];
|
||||
|
||||
try
|
||||
{
|
||||
@@ -208,25 +213,25 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize)
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput, 0);
|
||||
if(m_ports[i] == NULL)
|
||||
AUD_THROW(AUD_ERROR_JACK);
|
||||
AUD_THROW(AUD_ERROR_JACK, port_error);
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
jack_client_close(m_client);
|
||||
delete[] m_ports; AUD_DELETE("jack_port")
|
||||
delete[] m_ports;
|
||||
throw;
|
||||
}
|
||||
|
||||
m_specs.rate = (AUD_SampleRate)jack_get_sample_rate(m_client);
|
||||
|
||||
buffersize *= sizeof(sample_t);
|
||||
m_ringbuffers = new jack_ringbuffer_t*[specs.channels]; AUD_NEW("jack_buffers")
|
||||
m_ringbuffers = new jack_ringbuffer_t*[specs.channels];
|
||||
for(unsigned int i = 0; i < specs.channels; i++)
|
||||
m_ringbuffers[i] = jack_ringbuffer_create(buffersize);
|
||||
buffersize *= specs.channels;
|
||||
m_buffer = new AUD_Buffer(buffersize); AUD_NEW("buffer");
|
||||
m_deinterleavebuf = new AUD_Buffer(buffersize); AUD_NEW("buffer");
|
||||
m_deinterleavebuf.resize(buffersize);
|
||||
m_buffer.resize(buffersize);
|
||||
|
||||
create();
|
||||
|
||||
@@ -238,25 +243,19 @@ AUD_JackDevice::AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize)
|
||||
pthread_mutex_init(&m_mixingLock, NULL);
|
||||
pthread_cond_init(&m_mixingCondition, NULL);
|
||||
|
||||
try
|
||||
{
|
||||
// activate the client
|
||||
if(jack_activate(m_client))
|
||||
AUD_THROW(AUD_ERROR_JACK);
|
||||
}
|
||||
catch(AUD_Exception)
|
||||
// activate the client
|
||||
if(jack_activate(m_client))
|
||||
{
|
||||
jack_client_close(m_client);
|
||||
delete[] m_ports; AUD_DELETE("jack_port")
|
||||
delete m_buffer; AUD_DELETE("buffer");
|
||||
delete m_deinterleavebuf; AUD_DELETE("buffer");
|
||||
delete[] m_ports;
|
||||
for(unsigned int i = 0; i < specs.channels; i++)
|
||||
jack_ringbuffer_free(m_ringbuffers[i]);
|
||||
delete[] m_ringbuffers; AUD_DELETE("jack_buffers")
|
||||
delete[] m_ringbuffers;
|
||||
pthread_mutex_destroy(&m_mixingLock);
|
||||
pthread_cond_destroy(&m_mixingCondition);
|
||||
destroy();
|
||||
throw;
|
||||
|
||||
AUD_THROW(AUD_ERROR_JACK, activate_error);
|
||||
}
|
||||
|
||||
const char** ports = jack_get_ports(m_client, NULL, NULL,
|
||||
@@ -284,7 +283,7 @@ AUD_JackDevice::~AUD_JackDevice()
|
||||
jack_client_close(m_client);
|
||||
m_valid = false;
|
||||
|
||||
delete[] m_ports; AUD_DELETE("jack_port")
|
||||
delete[] m_ports;
|
||||
|
||||
pthread_mutex_lock(&m_mixingLock);
|
||||
pthread_cond_signal(&m_mixingCondition);
|
||||
@@ -293,11 +292,9 @@ AUD_JackDevice::~AUD_JackDevice()
|
||||
|
||||
pthread_cond_destroy(&m_mixingCondition);
|
||||
pthread_mutex_destroy(&m_mixingLock);
|
||||
delete m_buffer; AUD_DELETE("buffer");
|
||||
delete m_deinterleavebuf; AUD_DELETE("buffer");
|
||||
for(unsigned int i = 0; i < m_specs.channels; i++)
|
||||
jack_ringbuffer_free(m_ringbuffers[i]);
|
||||
delete[] m_ringbuffers; AUD_DELETE("jack_buffers")
|
||||
delete[] m_ringbuffers;
|
||||
|
||||
destroy();
|
||||
}
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
|
||||
|
||||
#include "AUD_SoftwareDevice.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <jack.h>
|
||||
#include <ringbuffer.h>
|
||||
@@ -54,9 +56,12 @@ private:
|
||||
/**
|
||||
* The output buffer.
|
||||
*/
|
||||
AUD_Buffer* m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
AUD_Buffer* m_deinterleavebuf;
|
||||
/**
|
||||
* The deinterleaving buffer.
|
||||
*/
|
||||
AUD_Buffer m_deinterleavebuf;
|
||||
|
||||
jack_ringbuffer_t** m_ringbuffers;
|
||||
|
||||
@@ -114,16 +119,23 @@ private:
|
||||
|
||||
void updateRingBuffers();
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_JackDevice(const AUD_JackDevice&);
|
||||
AUD_JackDevice& operator=(const AUD_JackDevice&);
|
||||
|
||||
protected:
|
||||
virtual void playing(bool playing);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a Jack client for audio output.
|
||||
* \param specs The wanted audio specification, where only the channel count is important.
|
||||
* \param name The client name.
|
||||
* \param specs The wanted audio specification, where only the channel count
|
||||
* is important.
|
||||
* \param buffersize The size of the internal buffer.
|
||||
* \exception AUD_Exception Thrown if the audio device cannot be opened.
|
||||
*/
|
||||
AUD_JackDevice(AUD_DeviceSpecs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE);
|
||||
AUD_JackDevice(std::string name, AUD_DeviceSpecs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE);
|
||||
|
||||
/**
|
||||
* Closes the Jack client.
|
||||
|
||||
@@ -29,39 +29,21 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_SndFileFactory::AUD_SndFileFactory(const char* filename)
|
||||
AUD_SndFileFactory::AUD_SndFileFactory(std::string filename) :
|
||||
m_filename(filename)
|
||||
{
|
||||
if(filename != NULL)
|
||||
{
|
||||
m_filename = new char[strlen(filename)+1]; AUD_NEW("string")
|
||||
strcpy(m_filename, filename);
|
||||
}
|
||||
else
|
||||
m_filename = NULL;
|
||||
}
|
||||
|
||||
AUD_SndFileFactory::AUD_SndFileFactory(unsigned char* buffer, int size)
|
||||
AUD_SndFileFactory::AUD_SndFileFactory(const data_t* buffer, int size) :
|
||||
m_buffer(new AUD_Buffer(size))
|
||||
{
|
||||
m_filename = NULL;
|
||||
m_buffer = AUD_Reference<AUD_Buffer>(new AUD_Buffer(size));
|
||||
memcpy(m_buffer.get()->getBuffer(), buffer, size);
|
||||
}
|
||||
|
||||
AUD_SndFileFactory::~AUD_SndFileFactory()
|
||||
AUD_IReader* AUD_SndFileFactory::createReader() const
|
||||
{
|
||||
if(m_filename)
|
||||
{
|
||||
delete[] m_filename; AUD_DELETE("string")
|
||||
}
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_SndFileFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader;
|
||||
if(m_filename)
|
||||
reader = new AUD_SndFileReader(m_filename);
|
||||
if(m_buffer.get())
|
||||
return new AUD_SndFileReader(m_buffer);
|
||||
else
|
||||
reader = new AUD_SndFileReader(m_buffer);
|
||||
AUD_NEW("reader")
|
||||
return reader;
|
||||
return new AUD_SndFileReader(m_filename);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "AUD_Reference.h"
|
||||
class AUD_Buffer;
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* This factory reads a sound file via libsndfile.
|
||||
*/
|
||||
@@ -39,33 +41,32 @@ private:
|
||||
/**
|
||||
* The filename of the sound source file.
|
||||
*/
|
||||
char* m_filename;
|
||||
std::string m_filename;
|
||||
|
||||
/**
|
||||
* The buffer to read from.
|
||||
*/
|
||||
AUD_Reference<AUD_Buffer> m_buffer;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SndFileFactory(const AUD_SndFileFactory&);
|
||||
AUD_SndFileFactory& operator=(const AUD_SndFileFactory&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new factory.
|
||||
* \param filename The sound file path.
|
||||
*/
|
||||
AUD_SndFileFactory(const char* filename);
|
||||
AUD_SndFileFactory(std::string filename);
|
||||
|
||||
/**
|
||||
* Creates a new factory.
|
||||
* \param buffer The buffer to read from.
|
||||
* \param size The size of the buffer.
|
||||
*/
|
||||
AUD_SndFileFactory(unsigned char* buffer, int size);
|
||||
AUD_SndFileFactory(const data_t* buffer, int size);
|
||||
|
||||
/**
|
||||
* Destroys the factory.
|
||||
*/
|
||||
~AUD_SndFileFactory();
|
||||
|
||||
virtual AUD_IReader* createReader();
|
||||
virtual AUD_IReader* createReader() const;
|
||||
};
|
||||
|
||||
#endif //AUD_SNDFILEFACTORY
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
*/
|
||||
|
||||
#include "AUD_SndFileReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
@@ -77,30 +76,31 @@ sf_count_t AUD_SndFileReader::vio_tell(void *user_data)
|
||||
return reader->m_memoffset;
|
||||
}
|
||||
|
||||
AUD_SndFileReader::AUD_SndFileReader(const char* filename)
|
||||
static const char* fileopen_error = "AUD_SndFileReader: File couldn't be "
|
||||
"read.";
|
||||
|
||||
AUD_SndFileReader::AUD_SndFileReader(std::string filename) :
|
||||
m_position(0)
|
||||
{
|
||||
SF_INFO sfinfo;
|
||||
|
||||
sfinfo.format = 0;
|
||||
m_sndfile = sf_open(filename, SFM_READ, &sfinfo);
|
||||
m_sndfile = sf_open(filename.c_str(), SFM_READ, &sfinfo);
|
||||
|
||||
if(!m_sndfile)
|
||||
AUD_THROW(AUD_ERROR_FILE);
|
||||
AUD_THROW(AUD_ERROR_FILE, fileopen_error);
|
||||
|
||||
m_specs.channels = (AUD_Channels) sfinfo.channels;
|
||||
m_specs.rate = (AUD_SampleRate) sfinfo.samplerate;
|
||||
m_length = sfinfo.frames;
|
||||
m_seekable = sfinfo.seekable;
|
||||
m_position = 0;
|
||||
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
}
|
||||
|
||||
AUD_SndFileReader::AUD_SndFileReader(AUD_Reference<AUD_Buffer> buffer)
|
||||
AUD_SndFileReader::AUD_SndFileReader(AUD_Reference<AUD_Buffer> buffer) :
|
||||
m_position(0),
|
||||
m_membuffer(buffer),
|
||||
m_memoffset(0)
|
||||
{
|
||||
m_membuffer = buffer;
|
||||
m_memoffset = 0;
|
||||
|
||||
m_vio.get_filelen = vio_get_filelen;
|
||||
m_vio.read = vio_read;
|
||||
m_vio.seek = vio_seek;
|
||||
@@ -113,25 +113,20 @@ AUD_SndFileReader::AUD_SndFileReader(AUD_Reference<AUD_Buffer> buffer)
|
||||
m_sndfile = sf_open_virtual(&m_vio, SFM_READ, &sfinfo, this);
|
||||
|
||||
if(!m_sndfile)
|
||||
AUD_THROW(AUD_ERROR_FILE);
|
||||
AUD_THROW(AUD_ERROR_FILE, fileopen_error);
|
||||
|
||||
m_specs.channels = (AUD_Channels) sfinfo.channels;
|
||||
m_specs.rate = (AUD_SampleRate) sfinfo.samplerate;
|
||||
m_length = sfinfo.frames;
|
||||
m_seekable = sfinfo.seekable;
|
||||
m_position = 0;
|
||||
|
||||
m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
|
||||
}
|
||||
|
||||
AUD_SndFileReader::~AUD_SndFileReader()
|
||||
{
|
||||
sf_close(m_sndfile);
|
||||
|
||||
delete m_buffer; AUD_DELETE("buffer")
|
||||
}
|
||||
|
||||
bool AUD_SndFileReader::isSeekable()
|
||||
bool AUD_SndFileReader::isSeekable() const
|
||||
{
|
||||
return m_seekable;
|
||||
}
|
||||
@@ -145,40 +140,30 @@ void AUD_SndFileReader::seek(int position)
|
||||
}
|
||||
}
|
||||
|
||||
int AUD_SndFileReader::getLength()
|
||||
int AUD_SndFileReader::getLength() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
int AUD_SndFileReader::getPosition()
|
||||
int AUD_SndFileReader::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
AUD_Specs AUD_SndFileReader::getSpecs()
|
||||
AUD_Specs AUD_SndFileReader::getSpecs() const
|
||||
{
|
||||
return m_specs;
|
||||
}
|
||||
|
||||
AUD_ReaderType AUD_SndFileReader::getType()
|
||||
{
|
||||
return AUD_TYPE_STREAM;
|
||||
}
|
||||
|
||||
bool AUD_SndFileReader::notify(AUD_Message &message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void AUD_SndFileReader::read(int & length, sample_t* & buffer)
|
||||
{
|
||||
int sample_size = AUD_SAMPLE_SIZE(m_specs);
|
||||
|
||||
// resize output buffer if necessary
|
||||
if(m_buffer->getSize() < length*sample_size)
|
||||
m_buffer->resize(length*sample_size);
|
||||
if(m_buffer.getSize() < length*sample_size)
|
||||
m_buffer.resize(length*sample_size);
|
||||
|
||||
buffer = m_buffer->getBuffer();
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
length = sf_readf_float(m_sndfile, buffer, length);
|
||||
|
||||
|
||||
@@ -28,8 +28,9 @@
|
||||
|
||||
#include "AUD_IReader.h"
|
||||
#include "AUD_Reference.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <string>
|
||||
#include <sndfile.h>
|
||||
|
||||
typedef sf_count_t (*sf_read_f)(SNDFILE *sndfile, void *ptr, sf_count_t frames);
|
||||
@@ -63,7 +64,7 @@ private:
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer* m_buffer;
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The sndfile.
|
||||
@@ -91,6 +92,10 @@ private:
|
||||
static sf_count_t vio_read(void *ptr, sf_count_t count, void *user_data);
|
||||
static sf_count_t vio_tell(void *user_data);
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SndFileReader(const AUD_SndFileReader&);
|
||||
AUD_SndFileReader& operator=(const AUD_SndFileReader&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new reader.
|
||||
@@ -98,7 +103,7 @@ public:
|
||||
* \exception AUD_Exception Thrown if the file specified does not exist or
|
||||
* cannot be read with libsndfile.
|
||||
*/
|
||||
AUD_SndFileReader(const char* filename);
|
||||
AUD_SndFileReader(std::string filename);
|
||||
|
||||
/**
|
||||
* Creates a new reader.
|
||||
@@ -113,13 +118,11 @@ public:
|
||||
*/
|
||||
virtual ~AUD_SndFileReader();
|
||||
|
||||
virtual bool isSeekable();
|
||||
virtual bool isSeekable() const;
|
||||
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 int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
};
|
||||
|
||||
|
||||
@@ -382,10 +382,8 @@ void sound_move_scene_sound(struct Scene *scene, void* handle, int startframe, i
|
||||
|
||||
void sound_start_play_scene(struct Scene *scene)
|
||||
{
|
||||
AUD_Sound* sound;
|
||||
sound = AUD_loopSound(scene->sound_scene);
|
||||
scene->sound_scene_handle = AUD_play(sound, 1);
|
||||
AUD_unload(sound);
|
||||
scene->sound_scene_handle = AUD_play(scene->sound_scene, 1);
|
||||
AUD_setLoop(scene->sound_scene_handle, -1);
|
||||
}
|
||||
|
||||
void sound_play_scene(struct Scene *scene)
|
||||
@@ -398,8 +396,6 @@ void sound_play_scene(struct Scene *scene)
|
||||
if(status == AUD_STATUS_INVALID)
|
||||
sound_start_play_scene(scene);
|
||||
|
||||
AUD_setLoop(scene->sound_scene_handle, -1, -1);
|
||||
|
||||
if(status != AUD_STATUS_PLAYING)
|
||||
{
|
||||
AUD_seek(scene->sound_scene_handle, CFRA / FPS);
|
||||
@@ -437,12 +433,16 @@ void sound_seek_scene(struct bContext *C)
|
||||
|
||||
if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer)
|
||||
{
|
||||
AUD_setLoop(scene->sound_scene_handle, -1, 1 / FPS);
|
||||
// AUD_XXX TODO: fix scrubbing, it currently doesn't stop playing
|
||||
if(scene->audio.flag & AUDIO_SYNC)
|
||||
AUD_seekSequencer(scene->sound_scene_handle, CFRA / FPS);
|
||||
else
|
||||
AUD_seek(scene->sound_scene_handle, CFRA / FPS);
|
||||
AUD_resume(scene->sound_scene_handle);
|
||||
if(AUD_getStatus(scene->sound_scrub_handle) != AUD_STATUS_INVALID)
|
||||
AUD_seek(scene->sound_scrub_handle, 0);
|
||||
else
|
||||
scene->sound_scrub_handle = AUD_pauseAfter(scene->sound_scene_handle, 1 / FPS);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -795,6 +795,7 @@ typedef struct Scene {
|
||||
|
||||
void *sound_scene;
|
||||
void *sound_scene_handle;
|
||||
void *sound_scrub_handle;
|
||||
|
||||
void *fps_info; /* (runtime) info/cache used for presenting playback framerate info to the user */
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ SET(INC
|
||||
../windowmanager
|
||||
../editors/include
|
||||
../../../intern/guardedalloc
|
||||
../../../intern/audaspace/intern
|
||||
${PYTHON_INC}
|
||||
)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ sources = env.Glob('intern/*.c')
|
||||
incs = '. ../editors/include ../makesdna ../makesrna ../blenlib ../blenkernel ../nodes'
|
||||
incs += ' ../imbuf ../blenloader ../render/extern/include ../windowmanager'
|
||||
incs += ' #intern/guardedalloc #intern/memutil #extern/glew/include'
|
||||
incs += ' ' + env['BF_PYTHON_INC']
|
||||
incs += ' #intern/audaspace/intern ' + env['BF_PYTHON_INC']
|
||||
|
||||
defs = []
|
||||
|
||||
|
||||
@@ -41,6 +41,11 @@
|
||||
#include "../generic/blf_api.h"
|
||||
#include "../generic/IDProp.h"
|
||||
|
||||
#ifndef DISABLE_PYTHON
|
||||
#define WITH_PYTHON
|
||||
#endif
|
||||
#include "AUD_C-API.h"
|
||||
|
||||
static char bpy_script_paths_doc[] =
|
||||
".. function:: script_paths()\n"
|
||||
"\n"
|
||||
@@ -153,7 +158,7 @@ void BPy_init_modules( void )
|
||||
BGL_Init();
|
||||
BLF_Init();
|
||||
IDProp_Init_Types();
|
||||
|
||||
AUD_initPython();
|
||||
|
||||
mod = PyModule_New("_bpy");
|
||||
|
||||
|
||||
@@ -388,9 +388,15 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
|
||||
ketsjiengine->InitDome(scene->gm.dome.res, scene->gm.dome.mode, scene->gm.dome.angle, scene->gm.dome.resbuf, scene->gm.dome.tilt, scene->gm.dome.warptext);
|
||||
|
||||
// initialize 3D Audio Settings
|
||||
AUD_set3DSetting(AUD_3DS_SPEED_OF_SOUND, scene->audio.speed_of_sound);
|
||||
AUD_set3DSetting(AUD_3DS_DOPPLER_FACTOR, scene->audio.doppler_factor);
|
||||
AUD_set3DSetting(AUD_3DS_DISTANCE_MODEL, scene->audio.distance_model);
|
||||
AUD_setSpeedOfSound(scene->audio.speed_of_sound);
|
||||
AUD_setDopplerFactor(scene->audio.doppler_factor);
|
||||
AUD_setDistanceModel(AUD_DistanceModel(scene->audio.distance_model));
|
||||
|
||||
// from see blender.c:
|
||||
// FIXME: this version patching should really be part of the file-reading code,
|
||||
// but we still get too many unrelated data-corruption crashes otherwise...
|
||||
if (blenderdata->versionfile < 250)
|
||||
do_versions_ipos_to_animato(blenderdata);
|
||||
|
||||
if (sceneconverter)
|
||||
{
|
||||
|
||||
@@ -235,7 +235,7 @@ void KX_KetsjiEngine::SetRasterizer(RAS_IRasterizer* rasterizer)
|
||||
|
||||
#ifndef DISABLE_PYTHON
|
||||
/*
|
||||
* At the moment the GameLogic module is imported into 'pythondictionary' after this function is called.
|
||||
* At the moment the bge.logic module is imported into 'pythondictionary' after this function is called.
|
||||
* if this function ever changes to assign a copy, make sure the game logic module is imported into this dictionary before hand.
|
||||
*/
|
||||
void KX_KetsjiEngine::SetPyNamespace(PyObject* pythondictionary)
|
||||
@@ -966,44 +966,17 @@ void KX_KetsjiEngine::DoSound(KX_Scene* scene)
|
||||
KX_Camera* cam = scene->GetActiveCamera();
|
||||
if (!cam)
|
||||
return;
|
||||
MT_Point3 listenerposition = cam->NodeGetWorldPosition();
|
||||
MT_Vector3 listenervelocity = cam->GetLinearVelocity();
|
||||
MT_Matrix3x3 listenerorientation = cam->NodeGetWorldOrientation();
|
||||
|
||||
{
|
||||
AUD_3DData data;
|
||||
float f;
|
||||
float f[4];
|
||||
|
||||
listenerorientation.getValue3x3(data.orientation);
|
||||
listenerposition.getValue(data.position);
|
||||
listenervelocity.getValue(data.velocity);
|
||||
cam->NodeGetWorldPosition().getValue(f);
|
||||
AUD_setListenerLocation(f);
|
||||
|
||||
f = data.position[1];
|
||||
data.position[1] = data.position[2];
|
||||
data.position[2] = -f;
|
||||
cam->GetLinearVelocity().getValue(f);
|
||||
AUD_setListenerVelocity(f);
|
||||
|
||||
f = data.velocity[1];
|
||||
data.velocity[1] = data.velocity[2];
|
||||
data.velocity[2] = -f;
|
||||
|
||||
f = data.orientation[1];
|
||||
data.orientation[1] = data.orientation[2];
|
||||
data.orientation[2] = -f;
|
||||
|
||||
f = data.orientation[3];
|
||||
data.orientation[3] = -data.orientation[6];
|
||||
data.orientation[6] = f;
|
||||
|
||||
f = data.orientation[4];
|
||||
data.orientation[4] = -data.orientation[8];
|
||||
data.orientation[8] = -f;
|
||||
|
||||
f = data.orientation[5];
|
||||
data.orientation[5] = data.orientation[7];
|
||||
data.orientation[7] = f;
|
||||
|
||||
AUD_updateListener(&data);
|
||||
}
|
||||
cam->NodeGetWorldOrientation().getRotation().getValue(f);
|
||||
AUD_setListenerOrientation(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -45,6 +45,10 @@ extern "C" {
|
||||
|
||||
#include "marshal.h" /* python header for loading/saving dicts */
|
||||
}
|
||||
|
||||
#define WITH_PYTHON
|
||||
#include "AUD_C-API.h"
|
||||
|
||||
#endif
|
||||
|
||||
#include "KX_PythonInit.h"
|
||||
@@ -262,8 +266,8 @@ static PyObject* gPyRestartGame(PyObject*)
|
||||
}
|
||||
|
||||
static char gPySaveGlobalDict_doc[] =
|
||||
"saveGlobalDict()\n\
|
||||
Saves GameLogic.globalDict to a file";
|
||||
"saveGlobalDict()\n"
|
||||
"Saves bge.logic.globalDict to a file";
|
||||
|
||||
static PyObject* gPySaveGlobalDict(PyObject*)
|
||||
{
|
||||
@@ -299,8 +303,8 @@ static PyObject* gPySaveGlobalDict(PyObject*)
|
||||
}
|
||||
|
||||
static char gPyLoadGlobalDict_doc[] =
|
||||
"LoadGlobalDict()\n\
|
||||
Loads GameLogic.globalDict from a file";
|
||||
"LoadGlobalDict()\n"
|
||||
"Loads bge.logic.globalDict from a file";
|
||||
|
||||
static PyObject* gPyLoadGlobalDict(PyObject*)
|
||||
{
|
||||
@@ -375,15 +379,6 @@ static PyObject* gPyGetSpectrum(PyObject*)
|
||||
return resultlist;
|
||||
}
|
||||
|
||||
|
||||
static PyObject* gPyStopDSP(PyObject*, PyObject* args)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError, "no audio device available");
|
||||
return NULL;
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject* gPySetLogicTicRate(PyObject*, PyObject* args)
|
||||
{
|
||||
float ticrate;
|
||||
@@ -752,7 +747,6 @@ static struct PyMethodDef game_methods[] = {
|
||||
{"getRandomFloat",(PyCFunction) gPyGetRandomFloat, METH_NOARGS, (const char *)gPyGetRandomFloat_doc},
|
||||
{"setGravity",(PyCFunction) gPySetGravity, METH_O, (const char *)"set Gravitation"},
|
||||
{"getSpectrum",(PyCFunction) gPyGetSpectrum, METH_NOARGS, (const char *)"get audio spectrum"},
|
||||
{"stopDSP",(PyCFunction) gPyStopDSP, METH_VARARGS, (const char *)"stop using the audio dsp (for performance reasons)"},
|
||||
{"getMaxLogicFrame", (PyCFunction) gPyGetMaxLogicFrame, METH_NOARGS, (const char *)"Gets the max number of logic frame per render frame"},
|
||||
{"setMaxLogicFrame", (PyCFunction) gPySetMaxLogicFrame, METH_VARARGS, (const char *)"Sets the max number of logic frame per render frame"},
|
||||
{"getMaxPhysicsFrame", (PyCFunction) gPyGetMaxPhysicsFrame, METH_NOARGS, (const char *)"Gets the max number of physics frame per render frame"},
|
||||
@@ -935,7 +929,6 @@ static PyObject* gPyDisableMist(PyObject*)
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
static PyObject* gPySetMistStart(PyObject*, PyObject* args)
|
||||
{
|
||||
|
||||
@@ -1232,7 +1225,7 @@ static struct PyMethodDef rasterizer_methods[] = {
|
||||
// Initialization function for the module (*must* be called initGameLogic)
|
||||
|
||||
static char GameLogic_module_documentation[] =
|
||||
"This is the Python API for the game engine of GameLogic"
|
||||
"This is the Python API for the game engine of bge.logic"
|
||||
;
|
||||
|
||||
static char Rasterizer_module_documentation[] =
|
||||
@@ -1313,7 +1306,6 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
|
||||
KX_MACRO_addTypesToDict(d, KX_PROPSENSOR_EXPRESSION, SCA_PropertySensor::KX_PROPSENSOR_EXPRESSION);
|
||||
|
||||
/* 3. Constraint actuator */
|
||||
/* XXX, TODO NXBGE, move constants names from KX_ACT_CONSTRAINT_foo to KX_CONSTRAINTACT_foo */
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_LOCX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCX);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_LOCY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCY);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_LOCZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCZ);
|
||||
@@ -1329,18 +1321,18 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIX);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIY);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIZ);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHPX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPX);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHPY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPY);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHPZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPZ);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHNX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNX);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHNY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNY);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_FHNZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNZ);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_NORMAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_NORMAL);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_MATERIAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_MATERIAL);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_PERMANENT, KX_ConstraintActuator::KX_ACT_CONSTRAINT_PERMANENT);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_DISTANCE, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DISTANCE);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_LOCAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCAL);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_DOROTFH, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DOROTFH);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_FHPX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPX);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_FHPY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPY);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_FHPZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHPZ);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_FHNX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNX);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_FHNY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNY);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_FHNZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_FHNZ);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_NORMAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_NORMAL);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_MATERIAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_MATERIAL);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_PERMANENT, KX_ConstraintActuator::KX_ACT_CONSTRAINT_PERMANENT);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DISTANCE, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DISTANCE);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_LOCAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCAL);
|
||||
KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DOROTFH, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DOROTFH);
|
||||
|
||||
/* 4. Ipo actuator, simple part */
|
||||
KX_MACRO_addTypesToDict(d, KX_IPOACT_PLAY, KX_IpoActuator::KX_ACT_IPO_PLAY);
|
||||
@@ -1582,7 +1574,7 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
|
||||
// Check for errors
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
Py_FatalError("can't initialize module GameLogic");
|
||||
Py_FatalError("can't initialize module bge.logic");
|
||||
}
|
||||
|
||||
return m;
|
||||
@@ -1979,7 +1971,6 @@ void setupGamePython(KX_KetsjiEngine* ketsjiengine, KX_Scene* startscene, Main *
|
||||
PyDict_SetItemString(PyModule_GetDict(*gameLogic), "globalDict", pyGlobalDict); // Same as importing the module.
|
||||
|
||||
*gameLogic_keys = PyDict_Keys(PyModule_GetDict(*gameLogic));
|
||||
PyDict_SetItemString(dictionaryobject, "GameLogic", *gameLogic); // Same as importing the module.
|
||||
|
||||
initGameKeys();
|
||||
initPythonConstraintBinding();
|
||||
@@ -1987,10 +1978,11 @@ void setupGamePython(KX_KetsjiEngine* ketsjiengine, KX_Scene* startscene, Main *
|
||||
initGeometry();
|
||||
initBGL();
|
||||
initBLF();
|
||||
AUD_initPython();
|
||||
initVideoTexture();
|
||||
|
||||
/* could be done a lot more nicely, but for now a quick way to get bge.* working */
|
||||
PyRun_SimpleString("sys = __import__('sys');mod = sys.modules['bge'] = type(sys)('bge');mod.__dict__.update({'logic':__import__('GameLogic'), 'render':__import__('Rasterizer'), 'events':__import__('GameKeys'), 'constraints':__import__('PhysicsConstraints'), 'types':__import__('GameTypes')})");
|
||||
PyRun_SimpleString("sys = __import__('sys');mod = sys.modules['bge'] = type(sys)('bge');mod.__dict__.update({'logic':__import__('GameLogic'), 'render':__import__('Rasterizer'), 'events':__import__('GameKeys'), 'constraints':__import__('PhysicsConstraints'), 'types':__import__('GameTypes')});import bge");
|
||||
}
|
||||
|
||||
static struct PyModuleDef Rasterizer_module_def = {
|
||||
@@ -2338,15 +2330,15 @@ int saveGamePythonConfig( char **marshal_buffer)
|
||||
memcpy(*marshal_buffer, marshal_cstring, marshal_length);
|
||||
Py_DECREF(pyGlobalDictMarshal);
|
||||
} else {
|
||||
printf("Error, GameLogic.globalDict could not be marshal'd\n");
|
||||
printf("Error, bge.logic.globalDict could not be marshal'd\n");
|
||||
}
|
||||
} else {
|
||||
printf("Error, GameLogic.globalDict was removed\n");
|
||||
printf("Error, bge.logic.globalDict was removed\n");
|
||||
}
|
||||
Py_DECREF(gameLogic);
|
||||
} else {
|
||||
PyErr_Clear();
|
||||
printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n");
|
||||
printf("Error, bge.logic failed to import bge.logic.globalDict will be lost\n");
|
||||
}
|
||||
return marshal_length;
|
||||
}
|
||||
@@ -2378,7 +2370,7 @@ int loadGamePythonConfig(char *marshal_buffer, int marshal_length)
|
||||
}
|
||||
} else {
|
||||
PyErr_Clear();
|
||||
printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n");
|
||||
printf("Error, bge.logic failed to import bge.logic.globalDict will be lost\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
#include "KX_SoundActuator.h"
|
||||
#include "AUD_C-API.h"
|
||||
#include "KX_GameObject.h"
|
||||
#include "KX_PyMath.h" // needed for PyObjectFrom()
|
||||
#include <iostream>
|
||||
@@ -75,23 +76,20 @@ void KX_SoundActuator::play()
|
||||
|
||||
// this is the sound that will be played and not deleted afterwards
|
||||
AUD_Sound* sound = m_sound;
|
||||
// this sounds are for temporary stacked sounds, will be deleted if not NULL
|
||||
// this sound is for temporary stacked sounds, will be deleted if not NULL
|
||||
AUD_Sound* sound2 = NULL;
|
||||
AUD_Sound* sound3 = NULL;
|
||||
|
||||
bool loop = false;
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
case KX_SOUNDACT_LOOPBIDIRECTIONAL:
|
||||
case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
|
||||
// create a ping pong sound on sound2 stacked on the orignal sound
|
||||
sound2 = AUD_pingpongSound(sound);
|
||||
// create a loop sound on sound3 stacked on the pingpong sound and let that one play (save it to sound)
|
||||
sound = sound3 = AUD_loopSound(sound2);
|
||||
break;
|
||||
sound = sound2 = AUD_pingpongSound(sound);
|
||||
// fall through
|
||||
case KX_SOUNDACT_LOOPEND:
|
||||
case KX_SOUNDACT_LOOPSTOP:
|
||||
// create a loop sound on sound2 stacked on the pingpong sound and let that one play (save it to sound)
|
||||
sound = sound2 = AUD_loopSound(sound);
|
||||
loop = true;
|
||||
break;
|
||||
case KX_SOUNDACT_PLAYSTOP:
|
||||
case KX_SOUNDACT_PLAYEND:
|
||||
@@ -102,28 +100,27 @@ void KX_SoundActuator::play()
|
||||
if(m_is3d)
|
||||
{
|
||||
// sound shall be played 3D
|
||||
m_handle = AUD_play3D(sound, 0);
|
||||
m_handle = AUD_play(sound, 0);
|
||||
|
||||
AUD_set3DSourceSetting(m_handle, AUD_3DSS_MAX_GAIN, m_3d.max_gain);
|
||||
AUD_set3DSourceSetting(m_handle, AUD_3DSS_MIN_GAIN, m_3d.min_gain);
|
||||
AUD_set3DSourceSetting(m_handle, AUD_3DSS_REFERENCE_DISTANCE, m_3d.reference_distance);
|
||||
AUD_set3DSourceSetting(m_handle, AUD_3DSS_MAX_DISTANCE, m_3d.max_distance);
|
||||
AUD_set3DSourceSetting(m_handle, AUD_3DSS_ROLLOFF_FACTOR, m_3d.rolloff_factor);
|
||||
AUD_set3DSourceSetting(m_handle, AUD_3DSS_CONE_INNER_ANGLE, m_3d.cone_inner_angle);
|
||||
AUD_set3DSourceSetting(m_handle, AUD_3DSS_CONE_OUTER_ANGLE, m_3d.cone_outer_angle);
|
||||
AUD_set3DSourceSetting(m_handle, AUD_3DSS_CONE_OUTER_GAIN, m_3d.cone_outer_gain);
|
||||
AUD_setRelative(m_handle, true);
|
||||
AUD_setVolumeMaximum(m_handle, m_3d.max_gain);
|
||||
AUD_setVolumeMinimum(m_handle, m_3d.min_gain);
|
||||
AUD_setDistanceReference(m_handle, m_3d.reference_distance);
|
||||
AUD_setDistanceMaximum(m_handle, m_3d.max_distance);
|
||||
AUD_setAttenuation(m_handle, m_3d.rolloff_factor);
|
||||
AUD_setConeAngleInner(m_handle, m_3d.cone_inner_angle);
|
||||
AUD_setConeAngleOuter(m_handle, m_3d.cone_outer_angle);
|
||||
AUD_setConeVolumeOuter(m_handle, m_3d.cone_outer_gain);
|
||||
}
|
||||
else
|
||||
m_handle = AUD_play(sound, 0);
|
||||
|
||||
if(loop)
|
||||
AUD_setLoop(m_handle, -1);
|
||||
AUD_setSoundPitch(m_handle, m_pitch);
|
||||
AUD_setSoundVolume(m_handle, m_volume);
|
||||
m_isplaying = true;
|
||||
|
||||
// now we unload the pingpong and loop sounds, as we don't need them anymore
|
||||
// the started sound will continue playing like it was created, don't worry!
|
||||
if(sound3)
|
||||
AUD_unload(sound3);
|
||||
if(sound2)
|
||||
AUD_unload(sound2);
|
||||
}
|
||||
@@ -183,7 +180,7 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
|
||||
case KX_SOUNDACT_LOOPBIDIRECTIONAL:
|
||||
{
|
||||
// stop the looping so that the sound stops when it finished
|
||||
AUD_setLoop(m_handle, 0, -1);
|
||||
AUD_setLoop(m_handle, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -215,39 +212,15 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
|
||||
{
|
||||
if(m_is3d)
|
||||
{
|
||||
AUD_3DData data;
|
||||
float f;
|
||||
((KX_GameObject*)this->GetParent())->NodeGetWorldPosition().getValue(data.position);
|
||||
((KX_GameObject*)this->GetParent())->GetLinearVelocity().getValue(data.velocity);
|
||||
((KX_GameObject*)this->GetParent())->NodeGetWorldOrientation().getValue3x3(data.orientation);
|
||||
KX_GameObject* obj = (KX_GameObject*)this->GetParent();
|
||||
float f[4];
|
||||
|
||||
/*
|
||||
* The 3D data from blender has to be transformed for OpenAL:
|
||||
* - In blender z is up and y is forwards
|
||||
* - In OpenAL y is up and z is backwards
|
||||
* We have to do that for all 5 vectors.
|
||||
*/
|
||||
f = data.position[1];
|
||||
data.position[1] = data.position[2];
|
||||
data.position[2] = -f;
|
||||
|
||||
f = data.velocity[1];
|
||||
data.velocity[1] = data.velocity[2];
|
||||
data.velocity[2] = -f;
|
||||
|
||||
f = data.orientation[1];
|
||||
data.orientation[1] = data.orientation[2];
|
||||
data.orientation[2] = -f;
|
||||
|
||||
f = data.orientation[4];
|
||||
data.orientation[4] = data.orientation[5];
|
||||
data.orientation[5] = -f;
|
||||
|
||||
f = data.orientation[7];
|
||||
data.orientation[7] = data.orientation[8];
|
||||
data.orientation[8] = -f;
|
||||
|
||||
AUD_update3DSource(m_handle, &data);
|
||||
obj->NodeGetWorldPosition().getValue(f);
|
||||
AUD_setSourceLocation(m_handle, f);
|
||||
obj->GetLinearVelocity().getValue(f);
|
||||
AUD_setSourceVelocity(m_handle, f);
|
||||
obj->NodeGetWorldOrientation().getRotation().getValue(f);
|
||||
AUD_setSourceOrientation(m_handle, f);
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
@@ -300,19 +273,18 @@ PyMethodDef KX_SoundActuator::Methods[] = {
|
||||
|
||||
PyAttributeDef KX_SoundActuator::Attributes[] = {
|
||||
KX_PYATTRIBUTE_BOOL_RO("is3D", KX_SoundActuator, m_is3d),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("maxGain3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("minGain3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("referenceDistance3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("maxDistance3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("rolloffFactor3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("coneInnerAngle3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("coneOuterAngle3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("coneOuterGain3D", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("volume_maximum", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("volume_minimum", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("distance_reference", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("distance_maximum", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("attenuation", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("cone_angle_inner", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("cone_angle_outer", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("cone_volume_outer", KX_SoundActuator, pyattr_get_3d_property, pyattr_set_3d_property),
|
||||
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("time", KX_SoundActuator, pyattr_get_audposition, pyattr_set_audposition),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("volume", KX_SoundActuator, pyattr_get_gain, pyattr_set_gain),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("pitch", KX_SoundActuator, pyattr_get_pitch, pyattr_set_pitch),
|
||||
KX_PYATTRIBUTE_RW_FUNCTION("rollOffFactor", KX_SoundActuator, pyattr_get_rollOffFactor, pyattr_set_rollOffFactor),
|
||||
KX_PYATTRIBUTE_ENUM_RW("mode",KX_SoundActuator::KX_SOUNDACT_NODEF+1,KX_SoundActuator::KX_SOUNDACT_MAX-1,false,KX_SoundActuator,m_type),
|
||||
{ NULL } //Sentinel
|
||||
};
|
||||
@@ -358,28 +330,28 @@ PyObject* KX_SoundActuator::pyattr_get_3d_property(void *self, const struct KX_P
|
||||
const char* prop = attrdef->m_name;
|
||||
float result_value = 0.0;
|
||||
|
||||
if(!strcmp(prop, "maxGain3D")) {
|
||||
if(!strcmp(prop, "volume_maximum")) {
|
||||
result_value = actuator->m_3d.max_gain;
|
||||
|
||||
} else if (!strcmp(prop, "minGain3D")) {
|
||||
} else if (!strcmp(prop, "volume_minimum")) {
|
||||
result_value = actuator->m_3d.min_gain;
|
||||
|
||||
} else if (!strcmp(prop, "referenceDistance3D")) {
|
||||
} else if (!strcmp(prop, "distance_reference")) {
|
||||
result_value = actuator->m_3d.reference_distance;
|
||||
|
||||
} else if (!strcmp(prop, "maxDistance3D")) {
|
||||
} else if (!strcmp(prop, "distance_maximum")) {
|
||||
result_value = actuator->m_3d.max_distance;
|
||||
|
||||
} else if (!strcmp(prop, "rolloffFactor3D")) {
|
||||
} else if (!strcmp(prop, "attenuation")) {
|
||||
result_value = actuator->m_3d.rolloff_factor;
|
||||
|
||||
} else if (!strcmp(prop, "coneInnerAngle3D")) {
|
||||
} else if (!strcmp(prop, "cone_angle_inner")) {
|
||||
result_value = actuator->m_3d.cone_inner_angle;
|
||||
|
||||
} else if (!strcmp(prop, "coneOuterAngle3D")) {
|
||||
} else if (!strcmp(prop, "cone_angle_outer")) {
|
||||
result_value = actuator->m_3d.cone_outer_angle;
|
||||
|
||||
} else if (!strcmp(prop, "coneOuterGain3D")) {
|
||||
} else if (!strcmp(prop, "cone_volume_outer")) {
|
||||
result_value = actuator->m_3d.cone_outer_gain;
|
||||
|
||||
} else {
|
||||
@@ -423,66 +395,63 @@ PyObject* KX_SoundActuator::pyattr_get_pitch(void *self, const struct KX_PYATTRI
|
||||
return result;
|
||||
}
|
||||
|
||||
PyObject* KX_SoundActuator::pyattr_get_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
|
||||
{
|
||||
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
|
||||
float rollofffactor = actuator->m_3d.rolloff_factor;
|
||||
PyObject* result = PyFloat_FromDouble(rollofffactor);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int KX_SoundActuator::pyattr_set_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
|
||||
{
|
||||
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
|
||||
const char* prop = attrdef->m_name;
|
||||
float prop_value = 0.0;
|
||||
AUD_3DSourceSetting setting = AUD_3DSS_NONE;
|
||||
|
||||
if (!PyArg_Parse(value, "f", &prop_value))
|
||||
return PY_SET_ATTR_FAIL;
|
||||
|
||||
// update the internal value
|
||||
if(!strcmp(prop, "maxGain3D")) {
|
||||
// if sound is working and 3D, set the new setting
|
||||
if(!actuator->m_is3d)
|
||||
return PY_SET_ATTR_FAIL;
|
||||
|
||||
if(!strcmp(prop, "volume_maximum")) {
|
||||
actuator->m_3d.max_gain = prop_value;
|
||||
setting = AUD_3DSS_MAX_GAIN;
|
||||
if(actuator->m_handle)
|
||||
AUD_setVolumeMaximum(actuator->m_handle, prop_value);
|
||||
|
||||
} else if (!strcmp(prop, "minGain3D")) {
|
||||
} else if (!strcmp(prop, "volume_minimum")) {
|
||||
actuator->m_3d.min_gain = prop_value;
|
||||
setting = AUD_3DSS_MIN_GAIN;
|
||||
if(actuator->m_handle)
|
||||
AUD_setVolumeMinimum(actuator->m_handle, prop_value);
|
||||
|
||||
} else if (!strcmp(prop, "referenceDistance3D")) {
|
||||
} else if (!strcmp(prop, "distance_reference")) {
|
||||
actuator->m_3d.reference_distance = prop_value;
|
||||
setting = AUD_3DSS_REFERENCE_DISTANCE;
|
||||
if(actuator->m_handle)
|
||||
AUD_setDistanceReference(actuator->m_handle, prop_value);
|
||||
|
||||
} else if (!strcmp(prop, "maxDistance3D")) {
|
||||
} else if (!strcmp(prop, "distance_maximum")) {
|
||||
actuator->m_3d.max_distance = prop_value;
|
||||
setting = AUD_3DSS_MAX_DISTANCE;
|
||||
if(actuator->m_handle)
|
||||
AUD_setDistanceMaximum(actuator->m_handle, prop_value);
|
||||
|
||||
} else if (!strcmp(prop, "rolloffFactor3D")) {
|
||||
} else if (!strcmp(prop, "attenuation")) {
|
||||
actuator->m_3d.rolloff_factor = prop_value;
|
||||
setting = AUD_3DSS_ROLLOFF_FACTOR;
|
||||
if(actuator->m_handle)
|
||||
AUD_setAttenuation(actuator->m_handle, prop_value);
|
||||
|
||||
} else if (!!strcmp(prop, "coneInnerAngle3D")) {
|
||||
} else if (!!strcmp(prop, "cone_angle_inner")) {
|
||||
actuator->m_3d.cone_inner_angle = prop_value;
|
||||
setting = AUD_3DSS_CONE_INNER_ANGLE;
|
||||
if(actuator->m_handle)
|
||||
AUD_setConeAngleInner(actuator->m_handle, prop_value);
|
||||
|
||||
} else if (!strcmp(prop, "coneOuterAngle3D")) {
|
||||
} else if (!strcmp(prop, "cone_angle_outer")) {
|
||||
actuator->m_3d.cone_outer_angle = prop_value;
|
||||
setting = AUD_3DSS_CONE_OUTER_ANGLE;
|
||||
if(actuator->m_handle)
|
||||
AUD_setConeAngleOuter(actuator->m_handle, prop_value);
|
||||
|
||||
} else if (!strcmp(prop, "coneOuterGain3D")) {
|
||||
} else if (!strcmp(prop, "cone_volume_outer")) {
|
||||
actuator->m_3d.cone_outer_gain = prop_value;
|
||||
setting = AUD_3DSS_CONE_OUTER_GAIN;
|
||||
if(actuator->m_handle)
|
||||
AUD_setConeVolumeOuter(actuator->m_handle, prop_value);
|
||||
|
||||
} else {
|
||||
return PY_SET_ATTR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// if sound is working and 3D, set the new setting
|
||||
if(actuator->m_handle && actuator->m_is3d && setting != AUD_3DSS_NONE)
|
||||
AUD_set3DSourceSetting(actuator->m_handle, setting, prop_value);
|
||||
|
||||
return PY_SET_ATTR_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -527,18 +496,4 @@ int KX_SoundActuator::pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_D
|
||||
return PY_SET_ATTR_SUCCESS;
|
||||
}
|
||||
|
||||
int KX_SoundActuator::pyattr_set_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
|
||||
{
|
||||
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
|
||||
float rollofffactor = 1.0;
|
||||
if (!PyArg_Parse(value, "f", &rollofffactor))
|
||||
return PY_SET_ATTR_FAIL;
|
||||
|
||||
actuator->m_3d.rolloff_factor = rollofffactor;
|
||||
if(actuator->m_handle)
|
||||
AUD_set3DSourceSetting(actuator->m_handle, AUD_3DSS_ROLLOFF_FACTOR, rollofffactor);
|
||||
|
||||
return PY_SET_ATTR_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // DISABLE_PYTHON
|
||||
|
||||
@@ -58,7 +58,7 @@ class KX_SoundActuator : public SCA_IActuator
|
||||
float m_pitch;
|
||||
bool m_is3d;
|
||||
KX_3DSoundSettings m_3d;
|
||||
AUD_Handle* m_handle;
|
||||
AUD_Channel* m_handle;
|
||||
|
||||
void play();
|
||||
|
||||
@@ -107,14 +107,12 @@ public:
|
||||
static int pyattr_set_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
|
||||
static int pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
|
||||
static int pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
|
||||
static int pyattr_set_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
|
||||
static int pyattr_set_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
|
||||
|
||||
static PyObject* pyattr_get_3d_property(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
|
||||
static PyObject* pyattr_get_audposition(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
|
||||
static PyObject* pyattr_get_gain(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
|
||||
static PyObject* pyattr_get_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
|
||||
static PyObject* pyattr_get_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
|
||||
static PyObject* pyattr_get_type(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
|
||||
|
||||
#endif // DISABLE_PYTHON
|
||||
|
||||
Reference in New Issue
Block a user