forked from bartvdbraak/blender
Merging pepper to trunk at revision 39791.
Important note: I used rsync to do the local merge, as "svn merge --reintegrate ^/branches/soc-2011-pepper" doesn't work with our svn server right now!
This commit is contained in:
commit
9424b1ceff
@ -1539,6 +1539,63 @@ Game Types (bge.types)
|
||||
Return the value matching key, or the default value if its not found.
|
||||
:return: The key value or a default.
|
||||
|
||||
.. method:: playAction(name, start_frame, end_frame, layer=0, priority=0 blendin=0, play_mode=ACT_MODE_PLAY, layer_weight=0.0, ipo_flags=0, speed=1.0)
|
||||
|
||||
Plays an action.
|
||||
|
||||
:arg name: the name of the action
|
||||
:type name: string
|
||||
:arg start: the start frame of the action
|
||||
:type start: float
|
||||
:arg end: the end frame of the action
|
||||
:type end: float
|
||||
:arg layer: the layer the action will play in (actions in different layers are added/blended together)
|
||||
:type layer: integer
|
||||
:arg priority: only play this action if there isn't an action currently playing in this layer with a higher (lower number) priority
|
||||
:type priority: integer
|
||||
:arg blendin: the amount of blending between this animation and the previous one on this layer
|
||||
:type blendin: float
|
||||
:arg play_mode: the play mode
|
||||
:type play_mode: KX_ACTION_PLAY, KX_ACTION_LOOP, or KX_ACTION_PING_PONG
|
||||
:arg layer_weight: how much of the previous layer to use for blending (0 = add)
|
||||
:type layer_weight: float
|
||||
:arg ipo_flags: flags for the old IPO behaviors (force, etc)
|
||||
:type ipo_flags: int bitfield
|
||||
:arg speed: the playback speed of the action as a factor (1.0 = normal speed, 2.0 = 2x speed, etc)
|
||||
:type speed: float
|
||||
|
||||
.. method:: stopAction(layer=0)
|
||||
|
||||
Stop playing the action on the given layer.
|
||||
|
||||
:arg layer: The layer to stop playing.
|
||||
:type layer: integer
|
||||
|
||||
.. method:: getActionFrame(layer=0)
|
||||
|
||||
Gets the current frame of the action playing in the supplied layer.
|
||||
|
||||
:arg layer: The layer that you want to get the frame from.
|
||||
:type layer: integer
|
||||
|
||||
:return: The current frame of the action
|
||||
|
||||
.. method:: setActionFrame(frame, layer=0)
|
||||
|
||||
Set the current frame of the action playing in the supplied layer.
|
||||
|
||||
:arg layer: The layer where you want to set the frame
|
||||
:type layer: integer
|
||||
:arg frame: The frame to set the action to
|
||||
:type frame: float
|
||||
|
||||
.. method:: isPlayingAction(layer=0)
|
||||
|
||||
Checks to see if there is an action playing in the given layer.
|
||||
|
||||
:arg layer: The layer to check for a playing action.
|
||||
:type layer: integer
|
||||
|
||||
.. class:: KX_IpoActuator(SCA_IActuator)
|
||||
|
||||
IPO actuator activates an animation.
|
||||
|
@ -41,6 +41,8 @@ set(SRC
|
||||
FX/AUD_DelayReader.cpp
|
||||
FX/AUD_DoubleFactory.cpp
|
||||
FX/AUD_DoubleReader.cpp
|
||||
FX/AUD_DynamicIIRFilterFactory.cpp
|
||||
FX/AUD_DynamicIIRFilterReader.cpp
|
||||
FX/AUD_EffectFactory.cpp
|
||||
FX/AUD_EffectReader.cpp
|
||||
FX/AUD_EnvelopeFactory.cpp
|
||||
@ -66,6 +68,8 @@ set(SRC
|
||||
FX/AUD_SuperposeReader.cpp
|
||||
FX/AUD_VolumeFactory.cpp
|
||||
intern/AUD_3DMath.h
|
||||
intern/AUD_AnimateableProperty.cpp
|
||||
intern/AUD_AnimateableProperty.h
|
||||
intern/AUD_Buffer.cpp
|
||||
intern/AUD_Buffer.h
|
||||
intern/AUD_BufferReader.cpp
|
||||
@ -82,14 +86,21 @@ set(SRC
|
||||
intern/AUD_ConverterFunctions.h
|
||||
intern/AUD_ConverterReader.cpp
|
||||
intern/AUD_ConverterReader.h
|
||||
intern/AUD_DefaultMixer.cpp
|
||||
intern/AUD_DefaultMixer.h
|
||||
intern/AUD_FileFactory.cpp
|
||||
intern/AUD_FileFactory.h
|
||||
intern/AUD_FileWriter.cpp
|
||||
intern/AUD_FileWriter.h
|
||||
intern/AUD_I3DDevice.h
|
||||
intern/AUD_I3DHandle.h
|
||||
intern/AUD_IDevice.h
|
||||
intern/AUD_IFactory.h
|
||||
intern/AUD_IHandle.h
|
||||
intern/AUD_IReader.h
|
||||
intern/AUD_IWriter.h
|
||||
intern/AUD_JOSResampleFactory.cpp
|
||||
intern/AUD_JOSResampleFactory.h
|
||||
intern/AUD_JOSResampleReader.cpp
|
||||
intern/AUD_JOSResampleReader.h
|
||||
intern/AUD_LinearResampleFactory.cpp
|
||||
intern/AUD_LinearResampleFactory.h
|
||||
intern/AUD_LinearResampleReader.cpp
|
||||
@ -104,9 +115,15 @@ set(SRC
|
||||
intern/AUD_ReadDevice.cpp
|
||||
intern/AUD_ReadDevice.h
|
||||
intern/AUD_Reference.h
|
||||
intern/AUD_ResampleFactory.h
|
||||
intern/AUD_ReferenceHandler.cpp
|
||||
intern/AUD_ResampleReader.cpp
|
||||
intern/AUD_ResampleReader.h
|
||||
intern/AUD_SequencerEntry.cpp
|
||||
intern/AUD_SequencerEntry.h
|
||||
intern/AUD_SequencerFactory.cpp
|
||||
intern/AUD_SequencerFactory.h
|
||||
intern/AUD_SequencerHandle.cpp
|
||||
intern/AUD_SequencerHandle.h
|
||||
intern/AUD_SequencerReader.cpp
|
||||
intern/AUD_SequencerReader.h
|
||||
intern/AUD_SilenceFactory.cpp
|
||||
@ -131,6 +148,8 @@ set(SRC
|
||||
FX/AUD_DelayReader.h
|
||||
FX/AUD_DoubleFactory.h
|
||||
FX/AUD_DoubleReader.h
|
||||
FX/AUD_DynamicIIRFilterFactory.h
|
||||
FX/AUD_DynamicIIRFilterReader.h
|
||||
FX/AUD_EffectFactory.h
|
||||
FX/AUD_EffectReader.h
|
||||
FX/AUD_EnvelopeFactory.h
|
||||
@ -168,9 +187,11 @@ if(WITH_CODEC_FFMPEG)
|
||||
list(APPEND SRC
|
||||
ffmpeg/AUD_FFMPEGFactory.cpp
|
||||
ffmpeg/AUD_FFMPEGReader.cpp
|
||||
ffmpeg/AUD_FFMPEGWriter.cpp
|
||||
|
||||
ffmpeg/AUD_FFMPEGFactory.h
|
||||
ffmpeg/AUD_FFMPEGReader.h
|
||||
ffmpeg/AUD_FFMPEGWriter.h
|
||||
)
|
||||
endif()
|
||||
|
||||
@ -230,9 +251,11 @@ if(WITH_CODEC_SNDFILE)
|
||||
list(APPEND SRC
|
||||
sndfile/AUD_SndFileFactory.cpp
|
||||
sndfile/AUD_SndFileReader.cpp
|
||||
sndfile/AUD_SndFileWriter.cpp
|
||||
|
||||
sndfile/AUD_SndFileFactory.h
|
||||
sndfile/AUD_SndFileReader.h
|
||||
sndfile/AUD_SndFileWriter.h
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "AUD_AccumulatorFactory.h"
|
||||
#include "AUD_CallbackIIRFilterReader.h"
|
||||
|
||||
sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless)
|
||||
sample_t AUD_AccumulatorFactory::accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless)
|
||||
{
|
||||
float in = reader->x(0);
|
||||
float lastin = reader->x(-1);
|
||||
@ -42,7 +42,7 @@ sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* us
|
||||
return out;
|
||||
}
|
||||
|
||||
sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
|
||||
sample_t AUD_AccumulatorFactory::accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
|
||||
{
|
||||
float in = reader->x(0);
|
||||
float lastin = reader->x(-1);
|
||||
@ -52,14 +52,14 @@ sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
|
||||
return out;
|
||||
}
|
||||
|
||||
AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_IFactory* factory,
|
||||
AUD_AccumulatorFactory::AUD_AccumulatorFactory(AUD_Reference<AUD_IFactory> factory,
|
||||
bool additive) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_additive(additive)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_AccumulatorFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_AccumulatorFactory::createReader()
|
||||
{
|
||||
return new AUD_CallbackIIRFilterReader(getReader(), 2, 2,
|
||||
m_additive ? accumulatorFilterAdditive : accumulatorFilter);
|
||||
|
@ -33,9 +33,14 @@
|
||||
#define AUD_ACCUMULATORFACTORY
|
||||
|
||||
#include "AUD_EffectFactory.h"
|
||||
class AUD_CallbackIIRFilterReader;
|
||||
|
||||
/**
|
||||
* This factory creates an accumulator reader.
|
||||
*
|
||||
* The accumulator adds the difference at the input to the last output in case
|
||||
* it's positive. In additive mode it additionaly adds the difference always.
|
||||
* So in case the difference is positive, it's added twice.
|
||||
*/
|
||||
class AUD_AccumulatorFactory : public AUD_EffectFactory
|
||||
{
|
||||
@ -55,9 +60,12 @@ public:
|
||||
* \param factory The input factory.
|
||||
* \param additive Whether the accumulator is additive.
|
||||
*/
|
||||
AUD_AccumulatorFactory(AUD_IFactory* factory, bool additive = false);
|
||||
AUD_AccumulatorFactory(AUD_Reference<AUD_IFactory> factory, bool additive = false);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
|
||||
static sample_t accumulatorFilterAdditive(AUD_CallbackIIRFilterReader* reader, void* useless);
|
||||
static sample_t accumulatorFilter(AUD_CallbackIIRFilterReader* reader, void* useless);
|
||||
};
|
||||
|
||||
#endif //AUD_ACCUMULATORFACTORY
|
||||
|
@ -33,20 +33,20 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#define CC m_channels + m_channel
|
||||
#define CC m_specs.channels + m_channel
|
||||
|
||||
AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_IReader* reader, int in,
|
||||
AUD_BaseIIRFilterReader::AUD_BaseIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in,
|
||||
int out) :
|
||||
AUD_EffectReader(reader),
|
||||
m_channels(reader->getSpecs().channels),
|
||||
m_specs(reader->getSpecs()),
|
||||
m_xlen(in), m_ylen(out),
|
||||
m_xpos(0), m_ypos(0), m_channel(0)
|
||||
{
|
||||
m_x = new sample_t[in * m_channels];
|
||||
m_y = new sample_t[out * m_channels];
|
||||
m_x = new sample_t[m_xlen * m_specs.channels];
|
||||
m_y = new sample_t[m_ylen * m_specs.channels];
|
||||
|
||||
memset(m_x, 0, sizeof(sample_t) * in * m_channels);
|
||||
memset(m_y, 0, sizeof(sample_t) * out * m_channels);
|
||||
memset(m_x, 0, sizeof(sample_t) * m_xlen * m_specs.channels);
|
||||
memset(m_y, 0, sizeof(sample_t) * m_ylen * m_specs.channels);
|
||||
}
|
||||
|
||||
AUD_BaseIIRFilterReader::~AUD_BaseIIRFilterReader()
|
||||
@ -55,24 +55,77 @@ AUD_BaseIIRFilterReader::~AUD_BaseIIRFilterReader()
|
||||
delete[] m_y;
|
||||
}
|
||||
|
||||
void AUD_BaseIIRFilterReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_BaseIIRFilterReader::setLengths(int in, int out)
|
||||
{
|
||||
sample_t* buf;
|
||||
if(in != m_xlen)
|
||||
{
|
||||
sample_t* xn = new sample_t[in * m_specs.channels];
|
||||
memset(xn, 0, sizeof(sample_t) * in * m_specs.channels);
|
||||
|
||||
int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs());
|
||||
for(m_channel = 0; m_channel < m_specs.channels; m_channel++)
|
||||
{
|
||||
for(int i = 1; i <= in && i <= m_xlen; i++)
|
||||
{
|
||||
xn[(in - i) * CC] = x(-i);
|
||||
}
|
||||
}
|
||||
|
||||
m_reader->read(length, buf);
|
||||
delete[] m_x;
|
||||
m_x = xn;
|
||||
m_xpos = 0;
|
||||
m_xlen = in;
|
||||
}
|
||||
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
m_buffer.resize(length * samplesize);
|
||||
if(out != m_ylen)
|
||||
{
|
||||
sample_t* yn = new sample_t[out * m_specs.channels];
|
||||
memset(yn, 0, sizeof(sample_t) * out * m_specs.channels);
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
for(m_channel = 0; m_channel < m_specs.channels; m_channel++)
|
||||
{
|
||||
for(int i = 1; i <= out && i <= m_ylen; i++)
|
||||
{
|
||||
yn[(out - i) * CC] = y(-i);
|
||||
}
|
||||
}
|
||||
|
||||
for(m_channel = 0; m_channel < m_channels; m_channel++)
|
||||
delete[] m_y;
|
||||
m_y = yn;
|
||||
m_ypos = 0;
|
||||
m_ylen = out;
|
||||
}
|
||||
}
|
||||
|
||||
void AUD_BaseIIRFilterReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
if(specs.channels != m_specs.channels)
|
||||
{
|
||||
m_specs.channels = specs.channels;
|
||||
|
||||
delete[] m_x;
|
||||
delete[] m_y;
|
||||
|
||||
m_x = new sample_t[m_xlen * m_specs.channels];
|
||||
m_y = new sample_t[m_ylen * m_specs.channels];
|
||||
|
||||
memset(m_x, 0, sizeof(sample_t) * m_xlen * m_specs.channels);
|
||||
memset(m_y, 0, sizeof(sample_t) * m_ylen * m_specs.channels);
|
||||
}
|
||||
|
||||
if(specs.rate != m_specs.rate)
|
||||
{
|
||||
m_specs = specs;
|
||||
sampleRateChanged(m_specs.rate);
|
||||
}
|
||||
|
||||
m_reader->read(length, eos, buffer);
|
||||
|
||||
for(m_channel = 0; m_channel < m_specs.channels; m_channel++)
|
||||
{
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
m_x[m_xpos * CC] = buf[i * CC];
|
||||
m_x[m_xpos * CC] = buffer[i * CC];
|
||||
m_y[m_ypos * CC] = buffer[i * CC] = filter();
|
||||
|
||||
m_xpos = (m_xpos + 1) % m_xlen;
|
||||
@ -80,3 +133,7 @@ void AUD_BaseIIRFilterReader::read(int & length, sample_t* & buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AUD_BaseIIRFilterReader::sampleRateChanged(AUD_SampleRate rate)
|
||||
{
|
||||
}
|
||||
|
@ -42,24 +42,19 @@ class AUD_BaseIIRFilterReader : public AUD_EffectReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Channel count.
|
||||
* Specs.
|
||||
*/
|
||||
const int m_channels;
|
||||
AUD_Specs m_specs;
|
||||
|
||||
/**
|
||||
* Length of input samples needed.
|
||||
*/
|
||||
const int m_xlen;
|
||||
int m_xlen;
|
||||
|
||||
/**
|
||||
* Length of output samples needed.
|
||||
*/
|
||||
const int m_ylen;
|
||||
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer m_buffer;
|
||||
int m_ylen;
|
||||
|
||||
/**
|
||||
* The last in samples array.
|
||||
@ -97,24 +92,46 @@ protected:
|
||||
* \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);
|
||||
AUD_BaseIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, int out);
|
||||
|
||||
void setLengths(int in, int out);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Retrieves the last input samples.
|
||||
* \param pos The position, valid are 0 (current) or negative values.
|
||||
* \return The sample value.
|
||||
*/
|
||||
inline sample_t x(int pos)
|
||||
{
|
||||
return m_x[(m_xpos + pos + m_xlen) % m_xlen * m_channels + m_channel];
|
||||
return m_x[(m_xpos + pos + m_xlen) % m_xlen * m_specs.channels + m_channel];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the last output samples.
|
||||
* \param pos The position, valid are negative values.
|
||||
* \return The sample value.
|
||||
*/
|
||||
inline sample_t y(int pos)
|
||||
{
|
||||
return m_y[(m_ypos + pos + m_ylen) % m_ylen * m_channels + m_channel];
|
||||
return m_y[(m_ypos + pos + m_ylen) % m_ylen * m_specs.channels + m_channel];
|
||||
}
|
||||
|
||||
virtual ~AUD_BaseIIRFilterReader();
|
||||
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||
|
||||
/**
|
||||
* Runs the filtering function.
|
||||
* \return The current output sample value.
|
||||
*/
|
||||
virtual sample_t filter()=0;
|
||||
|
||||
/**
|
||||
* Notifies the filter about a sample rate change.
|
||||
* \param rate The new sample rate.
|
||||
*/
|
||||
virtual void sampleRateChanged(AUD_SampleRate rate);
|
||||
};
|
||||
|
||||
#endif //AUD_BASEIIRFILTERREADER
|
||||
|
@ -41,19 +41,18 @@
|
||||
#define BWPB41 0.76536686473
|
||||
#define BWPB42 1.84775906502
|
||||
|
||||
AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_IFactory* factory,
|
||||
AUD_ButterworthFactory::AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory,
|
||||
float frequency) :
|
||||
AUD_EffectFactory(factory),
|
||||
AUD_DynamicIIRFilterFactory(factory),
|
||||
m_frequency(frequency)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_ButterworthFactory::createReader() const
|
||||
void AUD_ButterworthFactory::recalculateCoefficients(AUD_SampleRate rate,
|
||||
std::vector<float> &b,
|
||||
std::vector<float> &a)
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
// calculate coefficients
|
||||
float omega = 2 * tan(m_frequency * M_PI / reader->getSpecs().rate);
|
||||
float omega = 2 * tan(m_frequency * M_PI / rate);
|
||||
float o2 = omega * omega;
|
||||
float o4 = o2 * o2;
|
||||
float x1 = o2 + 2 * BWPB41 * omega + 4;
|
||||
@ -62,7 +61,6 @@ AUD_IReader* AUD_ButterworthFactory::createReader() const
|
||||
float y2 = o2 - 2 * BWPB42 * omega + 4;
|
||||
float o228 = 2 * o2 - 8;
|
||||
float norm = x1 * x2;
|
||||
std::vector<float> a, b;
|
||||
a.push_back(1);
|
||||
a.push_back((x1 + x2) * o228 / norm);
|
||||
a.push_back((x1 * y2 + x2 * y1 + o228 * o228) / norm);
|
||||
@ -73,6 +71,4 @@ AUD_IReader* AUD_ButterworthFactory::createReader() const
|
||||
b.push_back(6 * o4 / norm);
|
||||
b.push_back(b[1]);
|
||||
b.push_back(b[0]);
|
||||
|
||||
return new AUD_IIRFilterReader(reader, b, a);
|
||||
}
|
||||
|
@ -32,12 +32,12 @@
|
||||
#ifndef AUD_BUTTERWORTHFACTORY
|
||||
#define AUD_BUTTERWORTHFACTORY
|
||||
|
||||
#include "AUD_EffectFactory.h"
|
||||
#include "AUD_DynamicIIRFilterFactory.h"
|
||||
|
||||
/**
|
||||
* This factory creates a butterworth filter reader.
|
||||
* This factory creates a butterworth lowpass filter reader.
|
||||
*/
|
||||
class AUD_ButterworthFactory : public AUD_EffectFactory
|
||||
class AUD_ButterworthFactory : public AUD_DynamicIIRFilterFactory
|
||||
{
|
||||
private:
|
||||
/**
|
||||
@ -55,9 +55,11 @@ public:
|
||||
* \param factory The input factory.
|
||||
* \param frequency The cutoff frequency.
|
||||
*/
|
||||
AUD_ButterworthFactory(AUD_IFactory* factory, float frequency);
|
||||
AUD_ButterworthFactory(AUD_Reference<AUD_IFactory> factory, float frequency);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual void recalculateCoefficients(AUD_SampleRate rate,
|
||||
std::vector<float>& b,
|
||||
std::vector<float>& a);
|
||||
};
|
||||
|
||||
#endif //AUD_BUTTERWORTHFACTORY
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
#include "AUD_CallbackIIRFilterReader.h"
|
||||
|
||||
AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(AUD_IReader* reader,
|
||||
AUD_CallbackIIRFilterReader::AUD_CallbackIIRFilterReader(AUD_Reference<AUD_IReader> reader,
|
||||
int in, int out,
|
||||
doFilterIIR doFilter,
|
||||
endFilterIIR endFilter,
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
* \param endFilter The finishing callback.
|
||||
* \param data Data pointer for the callbacks.
|
||||
*/
|
||||
AUD_CallbackIIRFilterReader(AUD_IReader* reader, int in, int out,
|
||||
AUD_CallbackIIRFilterReader(AUD_Reference<AUD_IReader> reader, int in, int out,
|
||||
doFilterIIR doFilter,
|
||||
endFilterIIR endFilter = 0,
|
||||
void* data = 0);
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "AUD_DelayReader.h"
|
||||
#include "AUD_Space.h"
|
||||
|
||||
AUD_DelayFactory::AUD_DelayFactory(AUD_IFactory* factory, float delay) :
|
||||
AUD_DelayFactory::AUD_DelayFactory(AUD_Reference<AUD_IFactory> factory, float delay) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_delay(delay)
|
||||
{
|
||||
@ -44,7 +44,7 @@ float AUD_DelayFactory::getDelay() const
|
||||
return m_delay;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_DelayFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_DelayFactory::createReader()
|
||||
{
|
||||
return new AUD_DelayReader(getReader(), m_delay);
|
||||
}
|
||||
|
@ -55,14 +55,14 @@ public:
|
||||
* \param factory The input factory.
|
||||
* \param delay The desired delay in seconds.
|
||||
*/
|
||||
AUD_DelayFactory(AUD_IFactory* factory, float delay = 0);
|
||||
AUD_DelayFactory(AUD_Reference<AUD_IFactory> factory, float delay = 0);
|
||||
|
||||
/**
|
||||
* Returns the delay in seconds.
|
||||
*/
|
||||
float getDelay() const;
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_DELAYFACTORY
|
||||
|
@ -33,11 +33,10 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_DelayReader::AUD_DelayReader(AUD_IReader* reader, float delay) :
|
||||
AUD_DelayReader::AUD_DelayReader(AUD_Reference<AUD_IReader> reader, float delay) :
|
||||
AUD_EffectReader(reader),
|
||||
m_delay(int(delay * reader->getSpecs().rate)),
|
||||
m_remdelay(int(delay * reader->getSpecs().rate)),
|
||||
m_empty(true)
|
||||
m_remdelay(int(delay * reader->getSpecs().rate))
|
||||
{
|
||||
}
|
||||
|
||||
@ -70,49 +69,30 @@ int AUD_DelayReader::getPosition() const
|
||||
return m_reader->getPosition() + m_delay;
|
||||
}
|
||||
|
||||
void AUD_DelayReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_DelayReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
if(m_remdelay > 0)
|
||||
{
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
{
|
||||
m_buffer.resize(length * samplesize);
|
||||
m_empty = false;
|
||||
}
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
if(length > m_remdelay)
|
||||
{
|
||||
if(!m_empty)
|
||||
memset(buffer, 0, m_remdelay * samplesize);
|
||||
|
||||
int len = length - m_remdelay;
|
||||
sample_t* buf;
|
||||
m_reader->read(len, buf);
|
||||
m_reader->read(len, eos, buffer + m_remdelay * specs.channels);
|
||||
|
||||
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
|
||||
{
|
||||
if(!m_empty)
|
||||
{
|
||||
memset(buffer, 0, length * samplesize);
|
||||
m_empty = true;
|
||||
}
|
||||
m_remdelay -= length;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_reader->read(length, buffer);
|
||||
m_reader->read(length, eos, buffer);
|
||||
}
|
||||
|
@ -36,16 +36,11 @@
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
/**
|
||||
* This class reads another reader and changes it's delay.
|
||||
* This class reads another reader and delays it.
|
||||
*/
|
||||
class AUD_DelayReader : public AUD_EffectReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The delay level.
|
||||
*/
|
||||
@ -56,11 +51,6 @@ private:
|
||||
*/
|
||||
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&);
|
||||
@ -71,12 +61,12 @@ public:
|
||||
* \param reader The reader to read from.
|
||||
* \param delay The delay in seconds.
|
||||
*/
|
||||
AUD_DelayReader(AUD_IReader* reader, float delay);
|
||||
AUD_DelayReader(AUD_Reference<AUD_IReader> reader, float delay);
|
||||
|
||||
virtual void seek(int position);
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_DELAYREADER
|
||||
|
@ -32,25 +32,15 @@
|
||||
#include "AUD_DoubleFactory.h"
|
||||
#include "AUD_DoubleReader.h"
|
||||
|
||||
AUD_DoubleFactory::AUD_DoubleFactory(AUD_IFactory* factory1, AUD_IFactory* factory2) :
|
||||
AUD_DoubleFactory::AUD_DoubleFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2) :
|
||||
m_factory1(factory1), m_factory2(factory2)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_DoubleFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_DoubleFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader1 = m_factory1->createReader();
|
||||
AUD_IReader* reader2;
|
||||
|
||||
try
|
||||
{
|
||||
reader2 = m_factory2->createReader();
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
delete reader1;
|
||||
throw;
|
||||
}
|
||||
AUD_Reference<AUD_IReader> reader1 = m_factory1->createReader();
|
||||
AUD_Reference<AUD_IReader> reader2 = m_factory2->createReader();
|
||||
|
||||
return new AUD_DoubleReader(reader1, reader2);
|
||||
}
|
||||
|
@ -36,7 +36,6 @@
|
||||
|
||||
/**
|
||||
* 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_DoubleFactory : public AUD_IFactory
|
||||
{
|
||||
@ -44,12 +43,12 @@ private:
|
||||
/**
|
||||
* First played factory.
|
||||
*/
|
||||
AUD_IFactory* m_factory1;
|
||||
AUD_Reference<AUD_IFactory> m_factory1;
|
||||
|
||||
/**
|
||||
* Second played factory.
|
||||
*/
|
||||
AUD_IFactory* m_factory2;
|
||||
AUD_Reference<AUD_IFactory> m_factory2;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_DoubleFactory(const AUD_DoubleFactory&);
|
||||
@ -61,9 +60,9 @@ public:
|
||||
* \param factory1 The first input factory.
|
||||
* \param factory2 The second input factory.
|
||||
*/
|
||||
AUD_DoubleFactory(AUD_IFactory* factory1, AUD_IFactory* factory2);
|
||||
AUD_DoubleFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_DOUBLEFACTORY
|
||||
|
@ -33,28 +33,17 @@
|
||||
|
||||
#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) :
|
||||
AUD_DoubleReader::AUD_DoubleReader(AUD_Reference<AUD_IReader> reader1,
|
||||
AUD_Reference<AUD_IReader> reader2) :
|
||||
m_reader1(reader1), m_reader2(reader2), m_finished1(false)
|
||||
{
|
||||
AUD_Specs s1, s2;
|
||||
s1 = reader1->getSpecs();
|
||||
s2 = reader2->getSpecs();
|
||||
if(memcmp(&s1, &s2, sizeof(AUD_Specs)) != 0)
|
||||
{
|
||||
delete reader1;
|
||||
delete reader2;
|
||||
AUD_THROW(AUD_ERROR_SPECS, specs_error);
|
||||
}
|
||||
}
|
||||
|
||||
AUD_DoubleReader::~AUD_DoubleReader()
|
||||
{
|
||||
delete m_reader1;
|
||||
delete m_reader2;
|
||||
}
|
||||
|
||||
bool AUD_DoubleReader::isSeekable() const
|
||||
@ -90,43 +79,36 @@ int AUD_DoubleReader::getPosition() const
|
||||
|
||||
AUD_Specs AUD_DoubleReader::getSpecs() const
|
||||
{
|
||||
return m_reader1->getSpecs();
|
||||
return m_finished1 ? m_reader1->getSpecs() : m_reader2->getSpecs();
|
||||
}
|
||||
|
||||
void AUD_DoubleReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_DoubleReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
eos = false;
|
||||
|
||||
if(!m_finished1)
|
||||
{
|
||||
int len = length;
|
||||
m_reader1->read(len, buffer);
|
||||
|
||||
m_reader1->read(len, m_finished1, 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);
|
||||
|
||||
sample_t* buf = buffer;
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
memcpy(buffer, buf, len * samplesize);
|
||||
|
||||
len = length - len;
|
||||
length -= len;
|
||||
m_reader2->read(len, buf);
|
||||
|
||||
memcpy(buffer + length * specs.channels, buf,
|
||||
len * samplesize);
|
||||
|
||||
length += len;
|
||||
|
||||
m_finished1 = true;
|
||||
AUD_Specs specs1, specs2;
|
||||
specs1 = m_reader1->getSpecs();
|
||||
specs2 = m_reader2->getSpecs();
|
||||
if(AUD_COMPARE_SPECS(specs1, specs2))
|
||||
{
|
||||
int len2 = length - len;
|
||||
m_reader2->read(len2, eos, buffer + specs1.channels * len);
|
||||
length = len + len2;
|
||||
}
|
||||
else
|
||||
length = len;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_reader2->read(length, buffer);
|
||||
m_reader2->read(length, eos, buffer);
|
||||
}
|
||||
}
|
||||
|
@ -34,9 +34,10 @@
|
||||
|
||||
#include "AUD_IReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
#include "AUD_Reference.h"
|
||||
|
||||
/**
|
||||
* This reader plays two readers with the same specs sequently.
|
||||
* This reader plays two readers sequently.
|
||||
*/
|
||||
class AUD_DoubleReader : public AUD_IReader
|
||||
{
|
||||
@ -44,35 +45,29 @@ private:
|
||||
/**
|
||||
* The first reader.
|
||||
*/
|
||||
AUD_IReader* m_reader1;
|
||||
AUD_Reference<AUD_IReader> m_reader1;
|
||||
|
||||
/**
|
||||
* The second reader.
|
||||
*/
|
||||
AUD_IReader* m_reader2;
|
||||
AUD_Reference<AUD_IReader> m_reader2;
|
||||
|
||||
/**
|
||||
* Whether we've reached the end of the first reader.
|
||||
*/
|
||||
bool m_finished1;
|
||||
|
||||
/**
|
||||
* The playback buffer for the intersecting part.
|
||||
*/
|
||||
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.
|
||||
* Creates a new double 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_DoubleReader(AUD_IReader* reader1, AUD_IReader* reader2);
|
||||
AUD_DoubleReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
@ -84,7 +79,7 @@ public:
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_DOUBLEREADER
|
||||
|
42
intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp
Normal file
42
intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009-2011 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* Audaspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Audaspace; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file audaspace/FX/AUD_DynamicIIRFilterFactory.cpp
|
||||
* \ingroup audfx
|
||||
*/
|
||||
|
||||
#include "AUD_DynamicIIRFilterFactory.h"
|
||||
#include "AUD_DynamicIIRFilterReader.h"
|
||||
|
||||
AUD_DynamicIIRFilterFactory::AUD_DynamicIIRFilterFactory(AUD_Reference<AUD_IFactory> factory) :
|
||||
AUD_EffectFactory(factory)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_Reference<AUD_IReader> AUD_DynamicIIRFilterFactory::createReader()
|
||||
{
|
||||
return new AUD_DynamicIIRFilterReader(getReader(), this);
|
||||
}
|
65
intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h
Normal file
65
intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009-2011 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* Audaspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Audaspace; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file audaspace/FX/AUD_DynamicIIRFilterFactory.h
|
||||
* \ingroup audfx
|
||||
*/
|
||||
|
||||
#ifndef AUD_DYNAMICIIRFILTERFACTORY
|
||||
#define AUD_DYNAMICIIRFILTERFACTORY
|
||||
|
||||
#include "AUD_EffectFactory.h"
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* This factory creates a IIR filter reader.
|
||||
*
|
||||
* This means that on sample rate change the filter recalculates its
|
||||
* coefficients.
|
||||
*/
|
||||
class AUD_DynamicIIRFilterFactory : public AUD_EffectFactory
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates a new Dynmic IIR filter factory.
|
||||
* \param factory The input factory.
|
||||
*/
|
||||
AUD_DynamicIIRFilterFactory(AUD_Reference<AUD_IFactory> factory);
|
||||
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
|
||||
/**
|
||||
* Recalculates the filter coefficients.
|
||||
* \param rate The sample rate of the audio data.
|
||||
* \param[out] b The input filter coefficients.
|
||||
* \param[out] a The output filter coefficients.
|
||||
*/
|
||||
virtual void recalculateCoefficients(AUD_SampleRate rate,
|
||||
std::vector<float>& b,
|
||||
std::vector<float>& a)=0;
|
||||
};
|
||||
|
||||
#endif // AUD_DYNAMICIIRFILTERFACTORY
|
45
intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp
Normal file
45
intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009-2011 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* Audaspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Audaspace; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file audaspace/FX/AUD_DynamicIIRFilterReader.cpp
|
||||
* \ingroup audfx
|
||||
*/
|
||||
|
||||
#include "AUD_DynamicIIRFilterReader.h"
|
||||
|
||||
AUD_DynamicIIRFilterReader::AUD_DynamicIIRFilterReader(AUD_Reference<AUD_IReader> reader,
|
||||
AUD_Reference<AUD_DynamicIIRFilterFactory> factory) :
|
||||
AUD_IIRFilterReader(reader, std::vector<float>(), std::vector<float>())
|
||||
{
|
||||
sampleRateChanged(reader->getSpecs().rate);
|
||||
}
|
||||
|
||||
void AUD_DynamicIIRFilterReader::sampleRateChanged(AUD_SampleRate rate)
|
||||
{
|
||||
std::vector<float> a, b;
|
||||
m_factory->recalculateCoefficients(rate, b, a);
|
||||
setCoefficients(b, a);
|
||||
}
|
56
intern/audaspace/FX/AUD_DynamicIIRFilterReader.h
Normal file
56
intern/audaspace/FX/AUD_DynamicIIRFilterReader.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009-2011 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* Audaspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Audaspace; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file audaspace/FX/AUD_DynamicIIRFilterReader.h
|
||||
* \ingroup audfx
|
||||
*/
|
||||
|
||||
#ifndef AUD_DYNAMICIIRFILTERREADER
|
||||
#define AUD_DYNAMICIIRFILTERREADER
|
||||
|
||||
#include "AUD_IIRFilterReader.h"
|
||||
#include "AUD_DynamicIIRFilterFactory.h"
|
||||
|
||||
/**
|
||||
* This class is for dynamic infinite impulse response filters with simple
|
||||
* coefficients that change depending on the sample rate.
|
||||
*/
|
||||
class AUD_DynamicIIRFilterReader : public AUD_IIRFilterReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The factory for dynamically recalculating filter coefficients.
|
||||
*/
|
||||
AUD_Reference<AUD_DynamicIIRFilterFactory> m_factory;
|
||||
|
||||
public:
|
||||
AUD_DynamicIIRFilterReader(AUD_Reference<AUD_IReader> reader,
|
||||
AUD_Reference<AUD_DynamicIIRFilterFactory> factory);
|
||||
|
||||
virtual void sampleRateChanged(AUD_SampleRate rate);
|
||||
};
|
||||
|
||||
#endif // AUD_DYNAMICIIRFILTERREADER
|
@ -32,7 +32,7 @@
|
||||
#include "AUD_EffectFactory.h"
|
||||
#include "AUD_IReader.h"
|
||||
|
||||
AUD_EffectFactory::AUD_EffectFactory(AUD_IFactory* factory)
|
||||
AUD_EffectFactory::AUD_EffectFactory(AUD_Reference<AUD_IFactory> factory)
|
||||
{
|
||||
m_factory = factory;
|
||||
}
|
||||
@ -41,7 +41,7 @@ AUD_EffectFactory::~AUD_EffectFactory()
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IFactory* AUD_EffectFactory::getFactory() const
|
||||
AUD_Reference<AUD_IFactory> AUD_EffectFactory::getFactory() const
|
||||
{
|
||||
return m_factory;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ protected:
|
||||
/**
|
||||
* If there is no reader it is created out of this factory.
|
||||
*/
|
||||
AUD_IFactory* m_factory;
|
||||
AUD_Reference<AUD_IFactory> m_factory;
|
||||
|
||||
/**
|
||||
* Returns the reader created out of the factory.
|
||||
@ -57,7 +57,7 @@ protected:
|
||||
* classes.
|
||||
* \return The reader created out of the factory.
|
||||
*/
|
||||
inline AUD_IReader* getReader() const
|
||||
inline AUD_Reference<AUD_IReader> getReader() const
|
||||
{
|
||||
return m_factory->createReader();
|
||||
}
|
||||
@ -67,7 +67,7 @@ public:
|
||||
* Creates a new factory.
|
||||
* \param factory The input factory.
|
||||
*/
|
||||
AUD_EffectFactory(AUD_IFactory* factory);
|
||||
AUD_EffectFactory(AUD_Reference<AUD_IFactory> factory);
|
||||
|
||||
/**
|
||||
* Destroys the factory.
|
||||
@ -78,7 +78,7 @@ public:
|
||||
* Returns the saved factory.
|
||||
* \return The factory or NULL if there has no factory been saved.
|
||||
*/
|
||||
AUD_IFactory* getFactory() const;
|
||||
AUD_Reference<AUD_IFactory> getFactory() const;
|
||||
};
|
||||
|
||||
#endif //AUD_EFFECTFACTORY
|
||||
|
@ -31,14 +31,13 @@
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
|
||||
AUD_EffectReader::AUD_EffectReader(AUD_IReader* reader)
|
||||
AUD_EffectReader::AUD_EffectReader(AUD_Reference<AUD_IReader> reader)
|
||||
{
|
||||
m_reader = reader;
|
||||
}
|
||||
|
||||
AUD_EffectReader::~AUD_EffectReader()
|
||||
{
|
||||
delete m_reader;
|
||||
}
|
||||
|
||||
bool AUD_EffectReader::isSeekable() const
|
||||
@ -66,7 +65,7 @@ AUD_Specs AUD_EffectReader::getSpecs() const
|
||||
return m_reader->getSpecs();
|
||||
}
|
||||
|
||||
void AUD_EffectReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_EffectReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
m_reader->read(length, buffer);
|
||||
m_reader->read(length, eos, buffer);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define AUD_EFFECTREADER
|
||||
|
||||
#include "AUD_IReader.h"
|
||||
#include "AUD_Reference.h"
|
||||
|
||||
/**
|
||||
* This reader is a base class for all effect readers that take one other reader
|
||||
@ -49,14 +50,14 @@ protected:
|
||||
/**
|
||||
* The reader to read from.
|
||||
*/
|
||||
AUD_IReader* m_reader;
|
||||
AUD_Reference<AUD_IReader> m_reader;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new effect reader.
|
||||
* \param reader The reader to read from.
|
||||
*/
|
||||
AUD_EffectReader(AUD_IReader* reader);
|
||||
AUD_EffectReader(AUD_Reference<AUD_IReader> reader);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
@ -68,7 +69,7 @@ public:
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_EFFECTREADER
|
||||
|
@ -42,7 +42,7 @@ struct EnvelopeParameters
|
||||
float arthreshold;
|
||||
};
|
||||
|
||||
sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param)
|
||||
sample_t AUD_EnvelopeFactory::envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param)
|
||||
{
|
||||
float in = fabs(reader->x(0));
|
||||
float out = reader->y(-1);
|
||||
@ -51,12 +51,12 @@ sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters*
|
||||
return (in > out ? param->attack : param->release) * (out - in) + in;
|
||||
}
|
||||
|
||||
void endEnvelopeFilter(EnvelopeParameters* param)
|
||||
void AUD_EnvelopeFactory::endEnvelopeFilter(EnvelopeParameters* param)
|
||||
{
|
||||
delete param;
|
||||
}
|
||||
|
||||
AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack,
|
||||
AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_Reference<AUD_IFactory> factory, float attack,
|
||||
float release, float threshold,
|
||||
float arthreshold) :
|
||||
AUD_EffectFactory(factory),
|
||||
@ -67,14 +67,14 @@ AUD_EnvelopeFactory::AUD_EnvelopeFactory(AUD_IFactory* factory, float attack,
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_EnvelopeFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_EnvelopeFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
AUD_Reference<AUD_IReader> reader = getReader();
|
||||
|
||||
EnvelopeParameters* param = new EnvelopeParameters();
|
||||
param->arthreshold = m_arthreshold;
|
||||
param->attack = pow(m_arthreshold, 1.0f/(reader->getSpecs().rate * m_attack));
|
||||
param->release = pow(m_arthreshold, 1.0f/(reader->getSpecs().rate * m_release));
|
||||
param->attack = pow(m_arthreshold, 1.0f/(static_cast<float>(reader->getSpecs().rate) * m_attack));
|
||||
param->release = pow(m_arthreshold, 1.0f/(static_cast<float>(reader->getSpecs().rate) * m_release));
|
||||
param->threshold = m_threshold;
|
||||
|
||||
return new AUD_CallbackIIRFilterReader(reader, 1, 2,
|
||||
|
@ -33,6 +33,8 @@
|
||||
#define AUD_ENVELOPEFACTORY
|
||||
|
||||
#include "AUD_EffectFactory.h"
|
||||
class AUD_CallbackIIRFilterReader;
|
||||
struct EnvelopeParameters;
|
||||
|
||||
/**
|
||||
* This factory creates an envelope follower reader.
|
||||
@ -73,10 +75,13 @@ public:
|
||||
* \param threshold The threshold value.
|
||||
* \param arthreshold The attack/release threshold value.
|
||||
*/
|
||||
AUD_EnvelopeFactory(AUD_IFactory* factory, float attack, float release,
|
||||
AUD_EnvelopeFactory(AUD_Reference<AUD_IFactory> factory, float attack, float release,
|
||||
float threshold, float arthreshold);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
|
||||
static sample_t envelopeFilter(AUD_CallbackIIRFilterReader* reader, EnvelopeParameters* param);
|
||||
static void endEnvelopeFilter(EnvelopeParameters* param);
|
||||
};
|
||||
|
||||
#endif //AUD_ENVELOPEFACTORY
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "AUD_FaderFactory.h"
|
||||
#include "AUD_FaderReader.h"
|
||||
|
||||
AUD_FaderFactory::AUD_FaderFactory(AUD_IFactory* factory, AUD_FadeType type,
|
||||
AUD_FaderFactory::AUD_FaderFactory(AUD_Reference<AUD_IFactory> factory, AUD_FadeType type,
|
||||
float start, float length) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_type(type),
|
||||
@ -56,7 +56,7 @@ float AUD_FaderFactory::getLength() const
|
||||
return m_length;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_FaderFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_FaderFactory::createReader()
|
||||
{
|
||||
return new AUD_FaderReader(getReader(), m_type, m_start, m_length);
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ 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,
|
||||
AUD_FaderFactory(AUD_Reference<AUD_IFactory> factory,
|
||||
AUD_FadeType type = AUD_FADE_IN,
|
||||
float start = 0.0f, float length = 1.0f);
|
||||
|
||||
@ -88,7 +88,7 @@ public:
|
||||
*/
|
||||
float getLength() const;
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_FADERFACTORY
|
||||
|
@ -33,68 +33,39 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_FaderReader::AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type,
|
||||
AUD_FaderReader::AUD_FaderReader(AUD_Reference<AUD_IReader> reader, AUD_FadeType type,
|
||||
float start,float length) :
|
||||
AUD_EffectReader(reader),
|
||||
m_type(type),
|
||||
m_start(start),
|
||||
m_length(length),
|
||||
m_empty(true)
|
||||
m_length(length)
|
||||
{
|
||||
}
|
||||
|
||||
void AUD_FaderReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_FaderReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
int position = m_reader->getPosition();
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
|
||||
m_reader->read(length, buffer);
|
||||
m_reader->read(length, eos, buffer);
|
||||
|
||||
if((position + length) / (float)specs.rate <= m_start)
|
||||
{
|
||||
if(m_type != AUD_FADE_OUT)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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(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++)
|
||||
@ -111,10 +82,7 @@ void AUD_FaderReader::read(int & length, sample_t* & buffer)
|
||||
volume = 1.0f - volume;
|
||||
}
|
||||
|
||||
buf[i] = buffer[i] * volume;
|
||||
buffer[i] = buffer[i] * volume;
|
||||
}
|
||||
|
||||
buffer = buf;
|
||||
m_empty = false;
|
||||
}
|
||||
}
|
||||
|
@ -58,16 +58,6 @@ private:
|
||||
*/
|
||||
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&);
|
||||
@ -79,10 +69,10 @@ public:
|
||||
* \param start The time where fading should start in seconds.
|
||||
* \param length How long fading should last in seconds.
|
||||
*/
|
||||
AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type,
|
||||
AUD_FaderReader(AUD_Reference<AUD_IReader> reader, AUD_FadeType type,
|
||||
float start,float length);
|
||||
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_FADERREADER
|
||||
|
@ -38,30 +38,26 @@
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
AUD_HighpassFactory::AUD_HighpassFactory(AUD_IFactory* factory, float frequency,
|
||||
AUD_HighpassFactory::AUD_HighpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency,
|
||||
float Q) :
|
||||
AUD_EffectFactory(factory),
|
||||
AUD_DynamicIIRFilterFactory(factory),
|
||||
m_frequency(frequency),
|
||||
m_Q(Q)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_HighpassFactory::createReader() const
|
||||
void AUD_HighpassFactory::recalculateCoefficients(AUD_SampleRate rate,
|
||||
std::vector<float> &b,
|
||||
std::vector<float> &a)
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
// calculate coefficients
|
||||
float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate;
|
||||
float w0 = 2 * M_PI * m_frequency / rate;
|
||||
float alpha = sin(w0) / (2 * m_Q);
|
||||
float norm = 1 + alpha;
|
||||
float c = cos(w0);
|
||||
std::vector<float> a, b;
|
||||
a.push_back(1);
|
||||
a.push_back(-2 * c / norm);
|
||||
a.push_back((1 - alpha) / norm);
|
||||
b.push_back((1 + c) / (2 * norm));
|
||||
b.push_back((-1 - c) / norm);
|
||||
b.push_back(b[0]);
|
||||
|
||||
return new AUD_IIRFilterReader(reader, b, a);
|
||||
}
|
||||
|
@ -32,16 +32,16 @@
|
||||
#ifndef AUD_HIGHPASSFACTORY
|
||||
#define AUD_HIGHPASSFACTORY
|
||||
|
||||
#include "AUD_EffectFactory.h"
|
||||
#include "AUD_DynamicIIRFilterFactory.h"
|
||||
|
||||
/**
|
||||
* This factory creates a highpass filter reader.
|
||||
*/
|
||||
class AUD_HighpassFactory : public AUD_EffectFactory
|
||||
class AUD_HighpassFactory : public AUD_DynamicIIRFilterFactory
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The attack value in seconds.
|
||||
* The cutoff frequency.
|
||||
*/
|
||||
const float m_frequency;
|
||||
|
||||
@ -61,9 +61,9 @@ public:
|
||||
* \param frequency The cutoff frequency.
|
||||
* \param Q The Q factor.
|
||||
*/
|
||||
AUD_HighpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0f);
|
||||
AUD_HighpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector<float> &b, std::vector<float> &a);
|
||||
};
|
||||
|
||||
#endif //AUD_HIGHPASSFACTORY
|
||||
|
@ -32,14 +32,14 @@
|
||||
#include "AUD_IIRFilterFactory.h"
|
||||
#include "AUD_IIRFilterReader.h"
|
||||
|
||||
AUD_IIRFilterFactory::AUD_IIRFilterFactory(AUD_IFactory* factory,
|
||||
AUD_IIRFilterFactory::AUD_IIRFilterFactory(AUD_Reference<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
|
||||
AUD_Reference<AUD_IReader> AUD_IIRFilterFactory::createReader()
|
||||
{
|
||||
return new AUD_IIRFilterReader(getReader(), m_b, m_a);
|
||||
}
|
||||
|
@ -63,10 +63,10 @@ public:
|
||||
* \param b The input filter coefficients.
|
||||
* \param a The output filter coefficients.
|
||||
*/
|
||||
AUD_IIRFilterFactory(AUD_IFactory* factory, std::vector<float> b,
|
||||
AUD_IIRFilterFactory(AUD_Reference<AUD_IFactory> factory, std::vector<float> b,
|
||||
std::vector<float> a);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_IIRFILTERFACTORY
|
||||
|
@ -31,9 +31,9 @@
|
||||
|
||||
#include "AUD_IIRFilterReader.h"
|
||||
|
||||
AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_IReader* reader,
|
||||
std::vector<float> b,
|
||||
std::vector<float> a) :
|
||||
AUD_IIRFilterReader::AUD_IIRFilterReader(AUD_Reference<AUD_IReader> reader,
|
||||
const std::vector<float>& b,
|
||||
const std::vector<float>& a) :
|
||||
AUD_BaseIIRFilterReader(reader, b.size(), a.size()), m_a(a), m_b(b)
|
||||
{
|
||||
for(int i = 1; i < m_a.size(); i++)
|
||||
@ -54,3 +54,11 @@ sample_t AUD_IIRFilterReader::filter()
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void AUD_IIRFilterReader::setCoefficients(const std::vector<float>& b,
|
||||
const std::vector<float>& a)
|
||||
{
|
||||
setLengths(m_b.size(), m_a.size());
|
||||
m_a = a;
|
||||
m_b = b;
|
||||
}
|
||||
|
@ -63,10 +63,13 @@ public:
|
||||
* \param b The input filter coefficients.
|
||||
* \param a The output filter coefficients.
|
||||
*/
|
||||
AUD_IIRFilterReader(AUD_IReader* reader, std::vector<float> b,
|
||||
std::vector<float> a);
|
||||
AUD_IIRFilterReader(AUD_Reference<AUD_IReader> reader, const std::vector<float>& b,
|
||||
const std::vector<float>& a);
|
||||
|
||||
virtual sample_t filter();
|
||||
|
||||
void setCoefficients(const std::vector<float>& b,
|
||||
const std::vector<float>& a);
|
||||
};
|
||||
|
||||
#endif //AUD_IIRFILTERREADER
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "AUD_LimiterReader.h"
|
||||
#include "AUD_Space.h"
|
||||
|
||||
AUD_LimiterFactory::AUD_LimiterFactory(AUD_IFactory* factory,
|
||||
AUD_LimiterFactory::AUD_LimiterFactory(AUD_Reference<AUD_IFactory> factory,
|
||||
float start, float end) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_start(start),
|
||||
@ -51,7 +51,7 @@ float AUD_LimiterFactory::getEnd() const
|
||||
return m_end;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_LimiterFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_LimiterFactory::createReader()
|
||||
{
|
||||
return new AUD_LimiterReader(getReader(), m_start, m_end);
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ public:
|
||||
* \param end The desired end time, a negative value signals that it should
|
||||
* play to the end.
|
||||
*/
|
||||
AUD_LimiterFactory(AUD_IFactory* factory,
|
||||
AUD_LimiterFactory(AUD_Reference<AUD_IFactory> factory,
|
||||
float start = 0, float end = -1);
|
||||
|
||||
/**
|
||||
@ -75,7 +75,7 @@ public:
|
||||
*/
|
||||
float getEnd() const;
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_LIMITERFACTORY
|
||||
|
@ -32,30 +32,46 @@
|
||||
#include "AUD_LimiterReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
AUD_LimiterReader::AUD_LimiterReader(AUD_IReader* reader,
|
||||
AUD_LimiterReader::AUD_LimiterReader(AUD_Reference<AUD_IReader> reader,
|
||||
float start, float end) :
|
||||
AUD_EffectReader(reader),
|
||||
m_start(int(start * reader->getSpecs().rate)),
|
||||
m_end(int(end * reader->getSpecs().rate))
|
||||
m_start(start),
|
||||
m_end(end)
|
||||
{
|
||||
if(m_start > 0)
|
||||
{
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
AUD_Specs specs2;
|
||||
|
||||
if(m_reader->isSeekable())
|
||||
m_reader->seek(m_start);
|
||||
m_reader->seek(m_start * specs.rate);
|
||||
else
|
||||
{
|
||||
// skip first m_start samples by reading them
|
||||
int length = AUD_DEFAULT_BUFFER_SIZE;
|
||||
sample_t* buffer;
|
||||
for(int len = m_start;
|
||||
length == AUD_DEFAULT_BUFFER_SIZE;
|
||||
len -= AUD_DEFAULT_BUFFER_SIZE)
|
||||
AUD_Buffer buffer(AUD_DEFAULT_BUFFER_SIZE * AUD_SAMPLE_SIZE(specs));
|
||||
bool eos = false;
|
||||
for(int len = m_start * specs.rate;
|
||||
length > 0 && !eos;
|
||||
len -= length)
|
||||
{
|
||||
if(len < AUD_DEFAULT_BUFFER_SIZE)
|
||||
length = len;
|
||||
m_reader->read(length, buffer);
|
||||
|
||||
m_reader->read(length, eos, buffer.getBuffer());
|
||||
|
||||
specs2 = m_reader->getSpecs();
|
||||
if(specs2.rate != specs.rate)
|
||||
{
|
||||
len = len * specs2.rate / specs.rate;
|
||||
specs.rate = specs2.rate;
|
||||
}
|
||||
|
||||
if(specs2.channels != specs.channels)
|
||||
{
|
||||
specs = specs2;
|
||||
buffer.assureSize(AUD_DEFAULT_BUFFER_SIZE * AUD_SAMPLE_SIZE(specs));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -63,35 +79,71 @@ AUD_LimiterReader::AUD_LimiterReader(AUD_IReader* reader,
|
||||
|
||||
void AUD_LimiterReader::seek(int position)
|
||||
{
|
||||
m_reader->seek(position + m_start);
|
||||
m_reader->seek(position + m_start * m_reader->getSpecs().rate);
|
||||
}
|
||||
|
||||
int AUD_LimiterReader::getLength() const
|
||||
{
|
||||
int len = m_reader->getLength();
|
||||
if(len < 0 || (len > m_end && m_end >= 0))
|
||||
len = m_end;
|
||||
return len - m_start;
|
||||
AUD_SampleRate rate = m_reader->getSpecs().rate;
|
||||
if(len < 0 || (len > m_end * rate && m_end >= 0))
|
||||
len = m_end * rate;
|
||||
return len - m_start * rate;
|
||||
}
|
||||
|
||||
int AUD_LimiterReader::getPosition() const
|
||||
{
|
||||
int pos = m_reader->getPosition();
|
||||
return AUD_MIN(pos, m_end) - m_start;
|
||||
AUD_SampleRate rate = m_reader->getSpecs().rate;
|
||||
return AUD_MIN(pos, m_end * rate) - m_start * rate;
|
||||
}
|
||||
|
||||
void AUD_LimiterReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_LimiterReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
eos = false;
|
||||
if(m_end >= 0)
|
||||
{
|
||||
int position = m_reader->getPosition();
|
||||
if(position + length > m_end)
|
||||
length = m_end - position;
|
||||
AUD_SampleRate rate = m_reader->getSpecs().rate;
|
||||
|
||||
if(position + length > m_end * rate)
|
||||
{
|
||||
length = m_end * rate - position;
|
||||
eos = true;
|
||||
}
|
||||
|
||||
if(position < m_start * rate)
|
||||
{
|
||||
int len2 = length;
|
||||
for(int len = m_start * rate - position;
|
||||
len2 == length && !eos;
|
||||
len -= length)
|
||||
{
|
||||
if(len < length)
|
||||
len2 = len;
|
||||
|
||||
m_reader->read(len2, eos, buffer);
|
||||
position += len2;
|
||||
}
|
||||
|
||||
if(position < m_start * rate)
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(length < 0)
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_reader->read(length, buffer);
|
||||
if(eos)
|
||||
{
|
||||
m_reader->read(length, eos, buffer);
|
||||
eos = true;
|
||||
}
|
||||
else
|
||||
m_reader->read(length, eos, buffer);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include "AUD_EffectReader.h"
|
||||
|
||||
/**
|
||||
* This reader limits another reader in start and end sample.
|
||||
* This reader limits another reader in start and end times.
|
||||
*/
|
||||
class AUD_LimiterReader : public AUD_EffectReader
|
||||
{
|
||||
@ -43,12 +43,12 @@ private:
|
||||
/**
|
||||
* The start sample: inclusive.
|
||||
*/
|
||||
const int m_start;
|
||||
const float m_start;
|
||||
|
||||
/**
|
||||
* The end sample: exlusive.
|
||||
*/
|
||||
const int m_end;
|
||||
const float m_end;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_LimiterReader(const AUD_LimiterReader&);
|
||||
@ -58,16 +58,16 @@ public:
|
||||
/**
|
||||
* Creates a new limiter reader.
|
||||
* \param reader The reader to read from.
|
||||
* \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.
|
||||
* \param start The desired start time (inclusive).
|
||||
* \param end The desired end time (sample exklusive), a negative value
|
||||
* signals that it should play to the end.
|
||||
*/
|
||||
AUD_LimiterReader(AUD_IReader* reader, float start = 0, float end = -1);
|
||||
AUD_LimiterReader(AUD_Reference<AUD_IReader> reader, float start = 0, float end = -1);
|
||||
|
||||
virtual void seek(int position);
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_LIMITERREADER
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "AUD_LoopFactory.h"
|
||||
#include "AUD_LoopReader.h"
|
||||
|
||||
AUD_LoopFactory::AUD_LoopFactory(AUD_IFactory* factory, int loop) :
|
||||
AUD_LoopFactory::AUD_LoopFactory(AUD_Reference<AUD_IFactory> factory, int loop) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_loop(loop)
|
||||
{
|
||||
@ -43,7 +43,7 @@ int AUD_LoopFactory::getLoop() const
|
||||
return m_loop;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_LoopFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_LoopFactory::createReader()
|
||||
{
|
||||
return new AUD_LoopReader(getReader(), m_loop);
|
||||
}
|
||||
|
@ -57,14 +57,14 @@ public:
|
||||
* \param loop The desired loop count, negative values result in endless
|
||||
* looping.
|
||||
*/
|
||||
AUD_LoopFactory(AUD_IFactory* factory, int loop = -1);
|
||||
AUD_LoopFactory(AUD_Reference<AUD_IFactory> factory, int loop = -1);
|
||||
|
||||
/**
|
||||
* Returns the loop count.
|
||||
*/
|
||||
int getLoop() const;
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_LOOPFACTORY
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) :
|
||||
AUD_LoopReader::AUD_LoopReader(AUD_Reference<AUD_IReader> reader, int loop) :
|
||||
AUD_EffectReader(reader), m_count(loop), m_left(loop)
|
||||
{
|
||||
}
|
||||
@ -68,29 +68,20 @@ int AUD_LoopReader::getPosition() const
|
||||
return m_reader->getPosition() * (m_count < 0 ? 1 : m_count);
|
||||
}
|
||||
|
||||
void AUD_LoopReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_LoopReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
const AUD_Specs specs = m_reader->getSpecs();
|
||||
|
||||
int len = length;
|
||||
|
||||
m_reader->read(len, buffer);
|
||||
m_reader->read(length, eos, buffer);
|
||||
|
||||
if(len < length && m_left)
|
||||
if(length < len && eos && m_left)
|
||||
{
|
||||
int pos = 0;
|
||||
int pos = length;
|
||||
length = len;
|
||||
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
m_buffer.resize(length * samplesize);
|
||||
|
||||
sample_t* buf = m_buffer.getBuffer();
|
||||
|
||||
memcpy(buf + pos * specs.channels, buffer, len * samplesize);
|
||||
|
||||
pos += len;
|
||||
|
||||
while(pos < length && m_left)
|
||||
while(pos < length && eos && m_left)
|
||||
{
|
||||
if(m_left > 0)
|
||||
m_left--;
|
||||
@ -98,20 +89,15 @@ void AUD_LoopReader::read(int & length, sample_t* & buffer)
|
||||
m_reader->seek(0);
|
||||
|
||||
len = length - pos;
|
||||
m_reader->read(len, buffer);
|
||||
m_reader->read(len, eos, buffer + pos * specs.channels);
|
||||
|
||||
// prevent endless loop
|
||||
if(!len)
|
||||
break;
|
||||
|
||||
memcpy(buf + pos * specs.channels, buffer, len * samplesize);
|
||||
|
||||
pos += len;
|
||||
}
|
||||
|
||||
length = pos;
|
||||
buffer = buf;
|
||||
}
|
||||
else
|
||||
length = len;
|
||||
}
|
||||
|
@ -42,11 +42,6 @@
|
||||
class AUD_LoopReader : public AUD_EffectReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The loop count.
|
||||
*/
|
||||
@ -68,12 +63,12 @@ public:
|
||||
* \param loop The desired loop count, negative values result in endless
|
||||
* looping.
|
||||
*/
|
||||
AUD_LoopReader(AUD_IReader* reader, int loop);
|
||||
AUD_LoopReader(AUD_Reference<AUD_IReader> reader, int loop);
|
||||
|
||||
virtual void seek(int position);
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_LOOPREADER
|
||||
|
@ -38,30 +38,26 @@
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
AUD_LowpassFactory::AUD_LowpassFactory(AUD_IFactory* factory, float frequency,
|
||||
AUD_LowpassFactory::AUD_LowpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency,
|
||||
float Q) :
|
||||
AUD_EffectFactory(factory),
|
||||
AUD_DynamicIIRFilterFactory(factory),
|
||||
m_frequency(frequency),
|
||||
m_Q(Q)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_LowpassFactory::createReader() const
|
||||
void AUD_LowpassFactory::recalculateCoefficients(AUD_SampleRate rate,
|
||||
std::vector<float> &b,
|
||||
std::vector<float> &a)
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
// calculate coefficients
|
||||
float w0 = 2 * M_PI * m_frequency / reader->getSpecs().rate;
|
||||
float w0 = 2 * M_PI * m_frequency / rate;
|
||||
float alpha = sin(w0) / (2 * m_Q);
|
||||
float norm = 1 + alpha;
|
||||
float c = cos(w0);
|
||||
std::vector<float> a, b;
|
||||
a.push_back(1);
|
||||
a.push_back(-2 * c / norm);
|
||||
a.push_back((1 - alpha) / norm);
|
||||
b.push_back((1 - c) / (2 * norm));
|
||||
b.push_back((1 - c) / norm);
|
||||
b.push_back(b[0]);
|
||||
|
||||
return new AUD_IIRFilterReader(reader, b, a);
|
||||
}
|
||||
|
@ -32,16 +32,16 @@
|
||||
#ifndef AUD_LOWPASSFACTORY
|
||||
#define AUD_LOWPASSFACTORY
|
||||
|
||||
#include "AUD_EffectFactory.h"
|
||||
#include "AUD_DynamicIIRFilterFactory.h"
|
||||
|
||||
/**
|
||||
* This factory creates a lowpass filter reader.
|
||||
*/
|
||||
class AUD_LowpassFactory : public AUD_EffectFactory
|
||||
class AUD_LowpassFactory : public AUD_DynamicIIRFilterFactory
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The attack value in seconds.
|
||||
* The cutoff frequency.
|
||||
*/
|
||||
const float m_frequency;
|
||||
|
||||
@ -61,9 +61,9 @@ public:
|
||||
* \param frequency The cutoff frequency.
|
||||
* \param Q The Q factor.
|
||||
*/
|
||||
AUD_LowpassFactory(AUD_IFactory* factory, float frequency, float Q = 1.0f);
|
||||
AUD_LowpassFactory(AUD_Reference<AUD_IFactory> factory, float frequency, float Q = 1.0f);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual void recalculateCoefficients(AUD_SampleRate rate, std::vector<float> &b, std::vector<float> &a);
|
||||
};
|
||||
|
||||
#endif //AUD_LOWPASSFACTORY
|
||||
|
@ -33,26 +33,16 @@
|
||||
#include "AUD_DoubleReader.h"
|
||||
#include "AUD_ReverseFactory.h"
|
||||
|
||||
AUD_PingPongFactory::AUD_PingPongFactory(AUD_IFactory* factory) :
|
||||
AUD_PingPongFactory::AUD_PingPongFactory(AUD_Reference<AUD_IFactory> factory) :
|
||||
AUD_EffectFactory(factory)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_PingPongFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_PingPongFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
AUD_IReader* reader2;
|
||||
AUD_Reference<AUD_IReader> reader = getReader();
|
||||
AUD_ReverseFactory factory(m_factory);
|
||||
|
||||
try
|
||||
{
|
||||
reader2 = factory.createReader();
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
delete reader;
|
||||
throw;
|
||||
}
|
||||
AUD_Reference<AUD_IReader> reader2 = factory.createReader();
|
||||
|
||||
return new AUD_DoubleReader(reader, reader2);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
/**
|
||||
* This factory plays another factory first normal, then reversed.
|
||||
* \note Readers from the underlying factory must be from the buffer type.
|
||||
* \note Readers from the underlying factory must be reversable with seeking.
|
||||
*/
|
||||
class AUD_PingPongFactory : public AUD_EffectFactory
|
||||
{
|
||||
@ -50,9 +50,9 @@ public:
|
||||
* Creates a new ping pong factory.
|
||||
* \param factory The input factory.
|
||||
*/
|
||||
AUD_PingPongFactory(AUD_IFactory* factory);
|
||||
AUD_PingPongFactory(AUD_Reference<AUD_IFactory> factory);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_PINGPONGFACTORY
|
||||
|
@ -33,13 +33,13 @@
|
||||
#include "AUD_PitchReader.h"
|
||||
#include "AUD_Space.h"
|
||||
|
||||
AUD_PitchFactory::AUD_PitchFactory(AUD_IFactory* factory, float pitch) :
|
||||
AUD_PitchFactory::AUD_PitchFactory(AUD_Reference<AUD_IFactory> factory, float pitch) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_pitch(pitch)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_PitchFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_PitchFactory::createReader()
|
||||
{
|
||||
return new AUD_PitchReader(getReader(), m_pitch);
|
||||
}
|
||||
|
@ -55,9 +55,9 @@ public:
|
||||
* \param factory The input factory.
|
||||
* \param pitch The desired pitch.
|
||||
*/
|
||||
AUD_PitchFactory(AUD_IFactory* factory, float pitch);
|
||||
AUD_PitchFactory(AUD_Reference<AUD_IFactory> factory, float pitch);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_PITCHFACTORY
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
#include "AUD_PitchReader.h"
|
||||
|
||||
AUD_PitchReader::AUD_PitchReader(AUD_IReader* reader, float pitch) :
|
||||
AUD_PitchReader::AUD_PitchReader(AUD_Reference<AUD_IReader> reader, float pitch) :
|
||||
AUD_EffectReader(reader), m_pitch(pitch)
|
||||
{
|
||||
}
|
||||
@ -39,6 +39,16 @@ AUD_PitchReader::AUD_PitchReader(AUD_IReader* reader, float pitch) :
|
||||
AUD_Specs AUD_PitchReader::getSpecs() const
|
||||
{
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
specs.rate = (AUD_SampleRate)((int)(specs.rate * m_pitch));
|
||||
specs.rate *= m_pitch;
|
||||
return specs;
|
||||
}
|
||||
|
||||
float AUD_PitchReader::getPitch() const
|
||||
{
|
||||
return m_pitch;
|
||||
}
|
||||
|
||||
void AUD_PitchReader::setPitch(float pitch)
|
||||
{
|
||||
m_pitch = pitch;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ private:
|
||||
/**
|
||||
* The pitch level.
|
||||
*/
|
||||
const float m_pitch;
|
||||
float m_pitch;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_PitchReader(const AUD_PitchReader&);
|
||||
@ -53,11 +53,23 @@ public:
|
||||
/**
|
||||
* Creates a new pitch reader.
|
||||
* \param reader The reader to read from.
|
||||
* \param pitch The size of the buffer.
|
||||
* \param pitch The pitch value.
|
||||
*/
|
||||
AUD_PitchReader(AUD_IReader* reader, float pitch);
|
||||
AUD_PitchReader(AUD_Reference<AUD_IReader> reader, float pitch);
|
||||
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
|
||||
/**
|
||||
* Retrieves the pitch.
|
||||
* \return The current pitch value.
|
||||
*/
|
||||
float getPitch() const;
|
||||
|
||||
/**
|
||||
* Sets the pitch.
|
||||
* \param pitch The new pitch value.
|
||||
*/
|
||||
void setPitch(float pitch);
|
||||
};
|
||||
|
||||
#endif //AUD_PITCHREADER
|
||||
|
@ -34,17 +34,17 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
sample_t rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
|
||||
sample_t AUD_RectifyFactory::rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless)
|
||||
{
|
||||
return fabs(reader->x(0));
|
||||
}
|
||||
|
||||
AUD_RectifyFactory::AUD_RectifyFactory(AUD_IFactory* factory) :
|
||||
AUD_RectifyFactory::AUD_RectifyFactory(AUD_Reference<AUD_IFactory> factory) :
|
||||
AUD_EffectFactory(factory)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_RectifyFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_RectifyFactory::createReader()
|
||||
{
|
||||
return new AUD_CallbackIIRFilterReader(getReader(), 1, 1, rectifyFilter);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define AUD_RECTIFYFACTORY
|
||||
|
||||
#include "AUD_EffectFactory.h"
|
||||
class AUD_CallbackIIRFilterReader;
|
||||
|
||||
/**
|
||||
* This factory rectifies another factory.
|
||||
@ -49,9 +50,11 @@ public:
|
||||
* Creates a new rectify factory.
|
||||
* \param factory The input factory.
|
||||
*/
|
||||
AUD_RectifyFactory(AUD_IFactory* factory);
|
||||
AUD_RectifyFactory(AUD_Reference<AUD_IFactory> factory);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
|
||||
static sample_t rectifyFilter(AUD_CallbackIIRFilterReader* reader, void* useless);
|
||||
};
|
||||
|
||||
#endif //AUD_RECTIFYFACTORY
|
||||
|
@ -33,12 +33,12 @@
|
||||
#include "AUD_ReverseReader.h"
|
||||
#include "AUD_Space.h"
|
||||
|
||||
AUD_ReverseFactory::AUD_ReverseFactory(AUD_IFactory* factory) :
|
||||
AUD_ReverseFactory::AUD_ReverseFactory(AUD_Reference<AUD_IFactory> factory) :
|
||||
AUD_EffectFactory(factory)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_ReverseFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_ReverseFactory::createReader()
|
||||
{
|
||||
return new AUD_ReverseReader(getReader());
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
/**
|
||||
* This factory reads another factory reverted.
|
||||
* \note Readers from the underlying factory must be from the buffer type.
|
||||
* \note Readers from the underlying factory must be seekable.
|
||||
*/
|
||||
class AUD_ReverseFactory : public AUD_EffectFactory
|
||||
{
|
||||
@ -50,9 +50,9 @@ public:
|
||||
* Creates a new reverse factory.
|
||||
* \param factory The input factory.
|
||||
*/
|
||||
AUD_ReverseFactory(AUD_IFactory* factory);
|
||||
AUD_ReverseFactory(AUD_Reference<AUD_IFactory> factory);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_REVERSEFACTORY
|
||||
|
@ -36,7 +36,7 @@
|
||||
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_ReverseReader::AUD_ReverseReader(AUD_Reference<AUD_IReader> reader) :
|
||||
AUD_EffectReader(reader),
|
||||
m_length(reader->getLength()),
|
||||
m_position(0)
|
||||
@ -60,7 +60,7 @@ int AUD_ReverseReader::getPosition() const
|
||||
return m_position;
|
||||
}
|
||||
|
||||
void AUD_ReverseReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_ReverseReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
// first correct the length
|
||||
if(m_position + length > m_length)
|
||||
@ -69,39 +69,39 @@ void AUD_ReverseReader::read(int & length, sample_t* & buffer)
|
||||
if(length <= 0)
|
||||
{
|
||||
length = 0;
|
||||
eos = true;
|
||||
return;
|
||||
}
|
||||
|
||||
AUD_Specs specs = getSpecs();
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
const AUD_Specs specs = getSpecs();
|
||||
const int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
|
||||
// resize buffer if needed
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
m_buffer.resize(length * samplesize);
|
||||
sample_t temp[AUD_CHANNEL_MAX];
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
sample_t* buf;
|
||||
int len = length;
|
||||
|
||||
// read from reader
|
||||
m_reader->seek(m_length - m_position - len);
|
||||
m_reader->read(len, buf);
|
||||
m_reader->read(len, eos, buffer);
|
||||
|
||||
// set null if reader didn't give enough data
|
||||
if(len < length)
|
||||
{
|
||||
memset(buffer, 0, (length - len) * samplesize);
|
||||
buffer += (length - len) * specs.channels;
|
||||
}
|
||||
|
||||
// copy the samples reverted
|
||||
for(int i = 0; i < len; i++)
|
||||
memcpy(buffer + i * specs.channels,
|
||||
buf + (len - 1 - i) * specs.channels,
|
||||
for(int i = 0; i < length / 2; i++)
|
||||
{
|
||||
memcpy(temp,
|
||||
buffer + (len - 1 - i) * specs.channels,
|
||||
samplesize);
|
||||
memcpy(buffer + (len - 1 - i) * specs.channels,
|
||||
buffer + i * specs.channels,
|
||||
samplesize);
|
||||
memcpy(buffer + i * specs.channels,
|
||||
temp,
|
||||
samplesize);
|
||||
}
|
||||
|
||||
m_position += length;
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
eos = false;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
/**
|
||||
* This class reads another reader from back to front.
|
||||
* \note The underlying reader must be a buffer.
|
||||
* \note The underlying reader must be seekable.
|
||||
*/
|
||||
class AUD_ReverseReader : public AUD_EffectReader
|
||||
{
|
||||
@ -52,11 +52,6 @@ private:
|
||||
*/
|
||||
int m_position;
|
||||
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_ReverseReader(const AUD_ReverseReader&);
|
||||
AUD_ReverseReader& operator=(const AUD_ReverseReader&);
|
||||
@ -68,12 +63,12 @@ public:
|
||||
* \exception AUD_Exception Thrown if the reader specified has an
|
||||
* undeterminable/infinite length or is not seekable.
|
||||
*/
|
||||
AUD_ReverseReader(AUD_IReader* reader);
|
||||
AUD_ReverseReader(AUD_Reference<AUD_IReader> reader);
|
||||
|
||||
virtual void seek(int position);
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_REVERSEREADER
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "AUD_SquareFactory.h"
|
||||
#include "AUD_CallbackIIRFilterReader.h"
|
||||
|
||||
sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold)
|
||||
sample_t AUD_SquareFactory::squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold)
|
||||
{
|
||||
float in = reader->x(0);
|
||||
if(in >= *threshold)
|
||||
@ -43,12 +43,12 @@ sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void endSquareFilter(float* threshold)
|
||||
void AUD_SquareFactory::endSquareFilter(float* threshold)
|
||||
{
|
||||
delete threshold;
|
||||
}
|
||||
|
||||
AUD_SquareFactory::AUD_SquareFactory(AUD_IFactory* factory, float threshold) :
|
||||
AUD_SquareFactory::AUD_SquareFactory(AUD_Reference<AUD_IFactory> factory, float threshold) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_threshold(threshold)
|
||||
{
|
||||
@ -59,7 +59,7 @@ float AUD_SquareFactory::getThreshold() const
|
||||
return m_threshold;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_SquareFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_SquareFactory::createReader()
|
||||
{
|
||||
return new AUD_CallbackIIRFilterReader(getReader(), 1, 1,
|
||||
(doFilterIIR) squareFilter,
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define AUD_SQUAREFACTORY
|
||||
|
||||
#include "AUD_EffectFactory.h"
|
||||
class AUD_CallbackIIRFilterReader;
|
||||
|
||||
/**
|
||||
* This factory Transforms any signal to a square signal.
|
||||
@ -55,14 +56,17 @@ public:
|
||||
* \param factory The input factory.
|
||||
* \param threshold The threshold.
|
||||
*/
|
||||
AUD_SquareFactory(AUD_IFactory* factory, float threshold = 0.0f);
|
||||
AUD_SquareFactory(AUD_Reference<AUD_IFactory> factory, float threshold = 0.0f);
|
||||
|
||||
/**
|
||||
* Returns the threshold.
|
||||
*/
|
||||
float getThreshold() const;
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
|
||||
static sample_t squareFilter(AUD_CallbackIIRFilterReader* reader, float* threshold);
|
||||
static void endSquareFilter(float* threshold);
|
||||
};
|
||||
|
||||
#endif //AUD_SQUAREFACTORY
|
||||
|
@ -32,12 +32,12 @@
|
||||
#include "AUD_SumFactory.h"
|
||||
#include "AUD_IIRFilterReader.h"
|
||||
|
||||
AUD_SumFactory::AUD_SumFactory(AUD_IFactory* factory) :
|
||||
AUD_SumFactory::AUD_SumFactory(AUD_Reference<AUD_IFactory> factory) :
|
||||
AUD_EffectFactory(factory)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_SumFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_SumFactory::createReader()
|
||||
{
|
||||
std::vector<float> a, b;
|
||||
a.push_back(1);
|
||||
|
@ -49,9 +49,9 @@ public:
|
||||
* Creates a new sum factory.
|
||||
* \param factory The input factory.
|
||||
*/
|
||||
AUD_SumFactory(AUD_IFactory* factory);
|
||||
AUD_SumFactory(AUD_Reference<AUD_IFactory> factory);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_SUMFACTORY
|
||||
|
@ -32,24 +32,15 @@
|
||||
#include "AUD_SuperposeFactory.h"
|
||||
#include "AUD_SuperposeReader.h"
|
||||
|
||||
AUD_SuperposeFactory::AUD_SuperposeFactory(AUD_IFactory* factory1, AUD_IFactory* factory2) :
|
||||
AUD_SuperposeFactory::AUD_SuperposeFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2) :
|
||||
m_factory1(factory1), m_factory2(factory2)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_SuperposeFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_SuperposeFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader1 = m_factory1->createReader();
|
||||
AUD_IReader* reader2;
|
||||
try
|
||||
{
|
||||
reader2 = m_factory2->createReader();
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
delete reader1;
|
||||
throw;
|
||||
}
|
||||
AUD_Reference<AUD_IReader> reader1 = m_factory1->createReader();
|
||||
AUD_Reference<AUD_IReader> reader2 = m_factory2->createReader();
|
||||
|
||||
return new AUD_SuperposeReader(reader1, reader2);
|
||||
}
|
||||
|
@ -35,8 +35,9 @@
|
||||
#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.
|
||||
* This factory mixes two other factories, playing them the same time.
|
||||
* \note Readers from the underlying factories must have the same sample rate
|
||||
* and channel count.
|
||||
*/
|
||||
class AUD_SuperposeFactory : public AUD_IFactory
|
||||
{
|
||||
@ -44,12 +45,12 @@ private:
|
||||
/**
|
||||
* First played factory.
|
||||
*/
|
||||
AUD_IFactory* m_factory1;
|
||||
AUD_Reference<AUD_IFactory> m_factory1;
|
||||
|
||||
/**
|
||||
* Second played factory.
|
||||
*/
|
||||
AUD_IFactory* m_factory2;
|
||||
AUD_Reference<AUD_IFactory> m_factory2;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SuperposeFactory(const AUD_SuperposeFactory&);
|
||||
@ -61,9 +62,9 @@ public:
|
||||
* \param factory1 The first input factory.
|
||||
* \param factory2 The second input factory.
|
||||
*/
|
||||
AUD_SuperposeFactory(AUD_IFactory* factory1, AUD_IFactory* factory2);
|
||||
AUD_SuperposeFactory(AUD_Reference<AUD_IFactory> factory1, AUD_Reference<AUD_IFactory> factory2);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_SUPERPOSEFACTORY
|
||||
|
@ -36,30 +36,13 @@
|
||||
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) :
|
||||
AUD_SuperposeReader::AUD_SuperposeReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<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
|
||||
@ -94,28 +77,31 @@ AUD_Specs AUD_SuperposeReader::getSpecs() const
|
||||
return m_reader1->getSpecs();
|
||||
}
|
||||
|
||||
void AUD_SuperposeReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_SuperposeReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
AUD_Specs specs = m_reader1->getSpecs();
|
||||
AUD_Specs s2 = m_reader2->getSpecs();
|
||||
if(!AUD_COMPARE_SPECS(specs, s2))
|
||||
AUD_THROW(AUD_ERROR_SPECS, specs_error);
|
||||
|
||||
int samplesize = AUD_SAMPLE_SIZE(specs);
|
||||
|
||||
if(m_buffer.getSize() < length * samplesize)
|
||||
m_buffer.resize(length * samplesize);
|
||||
buffer = m_buffer.getBuffer();
|
||||
m_buffer.assureSize(length * samplesize);
|
||||
|
||||
int len1 = length;
|
||||
sample_t* buf;
|
||||
m_reader1->read(len1, buf);
|
||||
memcpy(buffer, buf, len1 * samplesize);
|
||||
m_reader1->read(len1, eos, buffer);
|
||||
|
||||
if(len1 < length)
|
||||
memset(buffer + len1 * specs.channels, 0, (length - len1) * samplesize);
|
||||
|
||||
int len2 = length;
|
||||
m_reader2->read(len2, buf);
|
||||
bool eos2;
|
||||
sample_t* buf = m_buffer.getBuffer();
|
||||
m_reader2->read(len2, eos2, buf);
|
||||
|
||||
for(int i = 0; i < len2 * specs.channels; i++)
|
||||
buffer[i] += buf[i];
|
||||
|
||||
length = AUD_MAX(len1, len2);
|
||||
eos &= eos2;
|
||||
}
|
||||
|
@ -34,9 +34,10 @@
|
||||
|
||||
#include "AUD_IReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
#include "AUD_Reference.h"
|
||||
|
||||
/**
|
||||
* This reader plays two readers with the same specs sequently.
|
||||
* This reader plays two readers with the same specs in parallel.
|
||||
*/
|
||||
class AUD_SuperposeReader : public AUD_IReader
|
||||
{
|
||||
@ -44,15 +45,15 @@ private:
|
||||
/**
|
||||
* The first reader.
|
||||
*/
|
||||
AUD_IReader* m_reader1;
|
||||
AUD_Reference<AUD_IReader> m_reader1;
|
||||
|
||||
/**
|
||||
* The second reader.
|
||||
*/
|
||||
AUD_IReader* m_reader2;
|
||||
AUD_Reference<AUD_IReader> m_reader2;
|
||||
|
||||
/**
|
||||
* The playback buffer for the intersecting part.
|
||||
* Buffer used for mixing.
|
||||
*/
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
@ -67,7 +68,7 @@ public:
|
||||
* \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);
|
||||
AUD_SuperposeReader(AUD_Reference<AUD_IReader> reader1, AUD_Reference<AUD_IReader> reader2);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
@ -79,7 +80,7 @@ public:
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_SUPERPOSEREADER
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "AUD_VolumeFactory.h"
|
||||
#include "AUD_IIRFilterReader.h"
|
||||
|
||||
AUD_VolumeFactory::AUD_VolumeFactory(AUD_IFactory* factory, float volume) :
|
||||
AUD_VolumeFactory::AUD_VolumeFactory(AUD_Reference<AUD_IFactory> factory, float volume) :
|
||||
AUD_EffectFactory(factory),
|
||||
m_volume(volume)
|
||||
{
|
||||
@ -43,7 +43,7 @@ float AUD_VolumeFactory::getVolume() const
|
||||
return m_volume;
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_VolumeFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_VolumeFactory::createReader()
|
||||
{
|
||||
std::vector<float> a, b;
|
||||
a.push_back(1);
|
||||
|
@ -57,14 +57,15 @@ public:
|
||||
* \param factory The input factory.
|
||||
* \param volume The desired volume.
|
||||
*/
|
||||
AUD_VolumeFactory(AUD_IFactory* factory, float volume);
|
||||
AUD_VolumeFactory(AUD_Reference<AUD_IFactory> factory, float volume);
|
||||
|
||||
/**
|
||||
* Returns the volume.
|
||||
* \return The current volume.
|
||||
*/
|
||||
float getVolume() const;
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_VOLUMEFACTORY
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -33,9 +33,11 @@
|
||||
#define AUD_OPENALDEVICE
|
||||
|
||||
#include "AUD_IDevice.h"
|
||||
#include "AUD_IHandle.h"
|
||||
#include "AUD_I3DDevice.h"
|
||||
struct AUD_OpenALHandle;
|
||||
struct AUD_OpenALBufferedFactory;
|
||||
#include "AUD_I3DHandle.h"
|
||||
#include "AUD_Buffer.h"
|
||||
//struct AUD_OpenALBufferedFactory;
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
@ -48,6 +50,110 @@ struct AUD_OpenALBufferedFactory;
|
||||
class AUD_OpenALDevice : public AUD_IDevice, public AUD_I3DDevice
|
||||
{
|
||||
private:
|
||||
/// Saves the data for playback.
|
||||
class AUD_OpenALHandle : public AUD_IHandle, public AUD_I3DHandle
|
||||
{
|
||||
public:
|
||||
static const int CYCLE_BUFFERS = 3;
|
||||
|
||||
/// Whether it's a buffered or a streamed source.
|
||||
bool m_isBuffered;
|
||||
|
||||
/// The reader source.
|
||||
AUD_Reference<AUD_IReader> m_reader;
|
||||
|
||||
/// Whether to keep the source if end of it is reached.
|
||||
bool m_keep;
|
||||
|
||||
/// OpenAL sample format.
|
||||
ALenum m_format;
|
||||
|
||||
/// OpenAL source.
|
||||
ALuint m_source;
|
||||
|
||||
/// OpenAL buffers.
|
||||
ALuint m_buffers[CYCLE_BUFFERS];
|
||||
|
||||
/// The first buffer to be read next.
|
||||
int m_current;
|
||||
|
||||
/// Whether the stream doesn't return any more data.
|
||||
bool m_eos;
|
||||
|
||||
/// The loop count of the source.
|
||||
int m_loopcount;
|
||||
|
||||
/// The stop callback.
|
||||
stopCallback m_stop;
|
||||
|
||||
/// Stop callback data.
|
||||
void* m_stop_data;
|
||||
|
||||
/// Orientation.
|
||||
AUD_Quaternion m_orientation;
|
||||
|
||||
/// Current status of the handle
|
||||
AUD_Status m_status;
|
||||
|
||||
/// Own device.
|
||||
AUD_OpenALDevice* m_device;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Creates a new OpenAL handle.
|
||||
* \param device The OpenAL device the handle belongs to.
|
||||
* \param format The AL format.
|
||||
* \param reader The reader this handle plays.
|
||||
* \param keep Whether to keep the handle alive when the reader ends.
|
||||
*/
|
||||
AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference<AUD_IReader> reader, bool keep);
|
||||
|
||||
virtual ~AUD_OpenALHandle() {}
|
||||
virtual bool pause();
|
||||
virtual bool resume();
|
||||
virtual bool stop();
|
||||
virtual bool getKeep();
|
||||
virtual bool setKeep(bool keep);
|
||||
virtual bool seek(float position);
|
||||
virtual float getPosition();
|
||||
virtual AUD_Status getStatus();
|
||||
virtual float getVolume();
|
||||
virtual bool setVolume(float volume);
|
||||
virtual float getPitch();
|
||||
virtual bool setPitch(float pitch);
|
||||
virtual int getLoopCount();
|
||||
virtual bool setLoopCount(int count);
|
||||
virtual bool setStopCallback(stopCallback callback = 0, void* data = 0);
|
||||
|
||||
virtual AUD_Vector3 getSourceLocation();
|
||||
virtual bool setSourceLocation(const AUD_Vector3& location);
|
||||
virtual AUD_Vector3 getSourceVelocity();
|
||||
virtual bool setSourceVelocity(const AUD_Vector3& velocity);
|
||||
virtual AUD_Quaternion getSourceOrientation();
|
||||
virtual bool setSourceOrientation(const AUD_Quaternion& orientation);
|
||||
virtual bool isRelative();
|
||||
virtual bool setRelative(bool relative);
|
||||
virtual float getVolumeMaximum();
|
||||
virtual bool setVolumeMaximum(float volume);
|
||||
virtual float getVolumeMinimum();
|
||||
virtual bool setVolumeMinimum(float volume);
|
||||
virtual float getDistanceMaximum();
|
||||
virtual bool setDistanceMaximum(float distance);
|
||||
virtual float getDistanceReference();
|
||||
virtual bool setDistanceReference(float distance);
|
||||
virtual float getAttenuation();
|
||||
virtual bool setAttenuation(float factor);
|
||||
virtual float getConeAngleOuter();
|
||||
virtual bool setConeAngleOuter(float angle);
|
||||
virtual float getConeAngleInner();
|
||||
virtual bool setConeAngleInner(float angle);
|
||||
virtual float getConeVolumeOuter();
|
||||
virtual bool setConeVolumeOuter(float volume);
|
||||
};
|
||||
|
||||
typedef std::list<AUD_Reference<AUD_OpenALHandle> >::iterator AUD_HandleIterator;
|
||||
|
||||
/**
|
||||
* The OpenAL device handle.
|
||||
*/
|
||||
@ -71,17 +177,17 @@ private:
|
||||
/**
|
||||
* The list of sounds that are currently playing.
|
||||
*/
|
||||
std::list<AUD_OpenALHandle*>* m_playingSounds;
|
||||
std::list<AUD_Reference<AUD_OpenALHandle> > m_playingSounds;
|
||||
|
||||
/**
|
||||
* The list of sounds that are currently paused.
|
||||
*/
|
||||
std::list<AUD_OpenALHandle*>* m_pausedSounds;
|
||||
std::list<AUD_Reference<AUD_OpenALHandle> > m_pausedSounds;
|
||||
|
||||
/**
|
||||
* The list of buffered factories.
|
||||
*/
|
||||
std::list<AUD_OpenALBufferedFactory*>* m_bufferedFactories;
|
||||
//std::list<AUD_OpenALBufferedFactory*>* m_bufferedFactories;
|
||||
|
||||
/**
|
||||
* The mutex for locking.
|
||||
@ -104,16 +210,20 @@ private:
|
||||
int m_buffersize;
|
||||
|
||||
/**
|
||||
* Starts the streaming thread.
|
||||
* Device buffer.
|
||||
*/
|
||||
void start(bool join = true);
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* Checks if a handle is valid.
|
||||
* \param handle The handle to check.
|
||||
* \return Whether the handle is valid.
|
||||
* Orientation.
|
||||
*/
|
||||
bool isValid(AUD_Handle* handle);
|
||||
AUD_Quaternion m_orientation;
|
||||
|
||||
/**
|
||||
* Starts the streaming thread.
|
||||
* \param Whether the previous thread should be joined.
|
||||
*/
|
||||
void start(bool join = true);
|
||||
|
||||
/**
|
||||
* Gets the format according to the specs.
|
||||
@ -147,27 +257,13 @@ public:
|
||||
virtual ~AUD_OpenALDevice();
|
||||
|
||||
virtual AUD_DeviceSpecs getSpecs() const;
|
||||
virtual AUD_Handle* play(AUD_IReader* reader, bool keep = false);
|
||||
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 seek(AUD_Handle* handle, float position);
|
||||
virtual float getPosition(AUD_Handle* handle);
|
||||
virtual AUD_Status getStatus(AUD_Handle* handle);
|
||||
virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false);
|
||||
virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false);
|
||||
virtual void stopAll();
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
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_Vector3 getListenerLocation() const;
|
||||
virtual void setListenerLocation(const AUD_Vector3& location);
|
||||
@ -181,30 +277,6 @@ public:
|
||||
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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -36,35 +36,38 @@
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#include "AUD_IDevice.h"
|
||||
#else
|
||||
typedef void AUD_IFactory;
|
||||
typedef void AUD_IDevice;
|
||||
typedef void AUD_Handle;
|
||||
typedef void AUD_IHandle;
|
||||
#endif
|
||||
|
||||
typedef void AUD_Reference_AUD_IFactory;
|
||||
typedef void AUD_Reference_AUD_IDevice;
|
||||
typedef void AUD_Reference_AUD_IHandle;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject* child_list;
|
||||
AUD_IFactory* factory;
|
||||
AUD_Reference_AUD_IFactory* factory;
|
||||
} Factory;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
AUD_Handle* handle;
|
||||
PyObject* device;
|
||||
AUD_Reference_AUD_IHandle* handle;
|
||||
} Handle;
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
AUD_IDevice* device;
|
||||
AUD_Reference_AUD_IDevice* device;
|
||||
} Device;
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit_aud(void);
|
||||
|
||||
extern PyObject *
|
||||
Device_empty();
|
||||
extern PyObject* Device_empty();
|
||||
extern PyObject* Factory_empty();
|
||||
extern Factory* checkFactory(PyObject* factory);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -32,18 +32,13 @@
|
||||
#include "AUD_SRCResampleFactory.h"
|
||||
#include "AUD_SRCResampleReader.h"
|
||||
|
||||
AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IFactory* factory,
|
||||
AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_Reference<AUD_IFactory> factory,
|
||||
AUD_DeviceSpecs specs) :
|
||||
AUD_ResampleFactory(factory, specs)
|
||||
AUD_MixerFactory(factory, specs)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_SRCResampleFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_SRCResampleFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
|
||||
if(reader->getSpecs().rate != m_specs.rate)
|
||||
reader = new AUD_SRCResampleReader(reader, m_specs.specs);
|
||||
|
||||
return reader;
|
||||
return new AUD_SRCResampleReader(getReader(), m_specs.specs);
|
||||
}
|
||||
|
@ -32,13 +32,13 @@
|
||||
#ifndef AUD_SRCRESAMPLEFACTORY
|
||||
#define AUD_SRCRESAMPLEFACTORY
|
||||
|
||||
#include "AUD_ResampleFactory.h"
|
||||
#include "AUD_MixerFactory.h"
|
||||
|
||||
/**
|
||||
* This factory creates a resampling reader that uses libsamplerate for
|
||||
* resampling.
|
||||
*/
|
||||
class AUD_SRCResampleFactory : public AUD_ResampleFactory
|
||||
class AUD_SRCResampleFactory : public AUD_MixerFactory
|
||||
{
|
||||
private:
|
||||
// hide copy constructor and operator=
|
||||
@ -46,9 +46,14 @@ private:
|
||||
AUD_SRCResampleFactory& operator=(const AUD_SRCResampleFactory&);
|
||||
|
||||
public:
|
||||
AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
|
||||
/**
|
||||
* Creates a new factory.
|
||||
* \param factory The input factory.
|
||||
* \param specs The target specifications.
|
||||
*/
|
||||
AUD_SRCResampleFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_SRCRESAMPLEFACTORY
|
||||
|
@ -43,20 +43,16 @@ static long src_callback(void *cb_data, float **data)
|
||||
static const char* state_error = "AUD_SRCResampleReader: SRC State couldn't be "
|
||||
"created.";
|
||||
|
||||
AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader,
|
||||
AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_Reference<AUD_IReader> reader,
|
||||
AUD_Specs specs) :
|
||||
AUD_EffectReader(reader),
|
||||
m_sspecs(reader->getSpecs()),
|
||||
m_factor(double(specs.rate) / double(m_sspecs.rate)),
|
||||
m_tspecs(specs),
|
||||
AUD_ResampleReader(reader, specs.rate),
|
||||
m_channels(reader->getSpecs().channels),
|
||||
m_position(0)
|
||||
{
|
||||
m_tspecs.channels = m_sspecs.channels;
|
||||
|
||||
int error;
|
||||
m_src = src_callback_new(src_callback,
|
||||
SRC_SINC_MEDIUM_QUALITY,
|
||||
m_sspecs.channels,
|
||||
m_channels,
|
||||
&error,
|
||||
this);
|
||||
|
||||
@ -74,25 +70,32 @@ AUD_SRCResampleReader::~AUD_SRCResampleReader()
|
||||
|
||||
long AUD_SRCResampleReader::doCallback(float** data)
|
||||
{
|
||||
int length = m_buffer.getSize() / AUD_SAMPLE_SIZE(m_tspecs);
|
||||
sample_t* buffer;
|
||||
AUD_Specs specs;
|
||||
specs.channels = m_channels;
|
||||
specs.rate = m_rate;
|
||||
|
||||
m_reader->read(length, buffer);
|
||||
int length = m_buffer.getSize() / AUD_SAMPLE_SIZE(specs);
|
||||
|
||||
*data = m_buffer.getBuffer();
|
||||
m_reader->read(length, m_eos, *data);
|
||||
|
||||
*data = buffer;
|
||||
return length;
|
||||
}
|
||||
|
||||
void AUD_SRCResampleReader::seek(int position)
|
||||
{
|
||||
m_reader->seek(position / m_factor);
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
double factor = double(m_rate) / double(specs.rate);
|
||||
m_reader->seek(position / factor);
|
||||
src_reset(m_src);
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
int AUD_SRCResampleReader::getLength() const
|
||||
{
|
||||
return m_reader->getLength() * m_factor;
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
double factor = double(m_rate) / double(specs.rate);
|
||||
return m_reader->getLength() * factor;
|
||||
}
|
||||
|
||||
int AUD_SRCResampleReader::getPosition() const
|
||||
@ -102,19 +105,48 @@ int AUD_SRCResampleReader::getPosition() const
|
||||
|
||||
AUD_Specs AUD_SRCResampleReader::getSpecs() const
|
||||
{
|
||||
return m_tspecs;
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
specs.rate = m_rate;
|
||||
return specs;
|
||||
}
|
||||
|
||||
void AUD_SRCResampleReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_SRCResampleReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
int size = length * AUD_SAMPLE_SIZE(m_tspecs);
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
|
||||
if(m_buffer.getSize() < size)
|
||||
m_buffer.resize(size);
|
||||
double factor = double(m_rate) / double(specs.rate);
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
specs.rate = m_rate;
|
||||
|
||||
length = src_callback_read(m_src, m_factor, length, buffer);
|
||||
int size = length;
|
||||
|
||||
m_buffer.assureSize(length * AUD_SAMPLE_SIZE(specs));
|
||||
|
||||
if(specs.channels != m_channels)
|
||||
{
|
||||
src_delete(m_src);
|
||||
|
||||
m_channels = specs.channels;
|
||||
|
||||
int error;
|
||||
m_src = src_callback_new(src_callback,
|
||||
SRC_SINC_MEDIUM_QUALITY,
|
||||
m_channels,
|
||||
&error,
|
||||
this);
|
||||
|
||||
if(!m_src)
|
||||
{
|
||||
// XXX printf("%s\n", src_strerror(error));
|
||||
AUD_THROW(AUD_ERROR_SRC, state_error);
|
||||
}
|
||||
}
|
||||
|
||||
m_eos = false;
|
||||
|
||||
length = src_callback_read(m_src, factor, length, buffer);
|
||||
|
||||
m_position += length;
|
||||
|
||||
eos = m_eos && (length < size);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
#ifndef AUD_SRCRESAMPLEREADER
|
||||
#define AUD_SRCRESAMPLEREADER
|
||||
|
||||
#include "AUD_EffectReader.h"
|
||||
#include "AUD_ResampleReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <samplerate.h>
|
||||
@ -40,28 +40,18 @@
|
||||
/**
|
||||
* This resampling reader uses libsamplerate for resampling.
|
||||
*/
|
||||
class AUD_SRCResampleReader : public AUD_EffectReader
|
||||
class AUD_SRCResampleReader : public AUD_ResampleReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The sample specification of the source.
|
||||
*/
|
||||
const AUD_Specs m_sspecs;
|
||||
|
||||
/**
|
||||
* The resampling factor.
|
||||
*/
|
||||
const double m_factor;
|
||||
|
||||
/**
|
||||
* The sound output buffer.
|
||||
*/
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The target specification.
|
||||
* The reader channels.
|
||||
*/
|
||||
AUD_Specs m_tspecs;
|
||||
AUD_Channels m_channels;
|
||||
|
||||
/**
|
||||
* The src state structure.
|
||||
@ -73,6 +63,11 @@ private:
|
||||
*/
|
||||
int m_position;
|
||||
|
||||
/**
|
||||
* Whether reader reached end of stream.
|
||||
*/
|
||||
bool m_eos;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_SRCResampleReader(const AUD_SRCResampleReader&);
|
||||
AUD_SRCResampleReader& operator=(const AUD_SRCResampleReader&);
|
||||
@ -85,7 +80,7 @@ public:
|
||||
* \exception AUD_Exception Thrown if the source specification cannot be
|
||||
* resampled to the target specification.
|
||||
*/
|
||||
AUD_SRCResampleReader(AUD_IReader* reader, AUD_Specs specs);
|
||||
AUD_SRCResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
@ -104,7 +99,7 @@ public:
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_SRCRESAMPLEREADER
|
||||
|
@ -36,7 +36,6 @@
|
||||
|
||||
#include "AUD_FFMPEGFactory.h"
|
||||
#include "AUD_FFMPEGReader.h"
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
AUD_FFMPEGFactory::AUD_FFMPEGFactory(std::string filename) :
|
||||
m_filename(filename)
|
||||
@ -46,13 +45,13 @@ AUD_FFMPEGFactory::AUD_FFMPEGFactory(std::string filename) :
|
||||
AUD_FFMPEGFactory::AUD_FFMPEGFactory(const data_t* buffer, int size) :
|
||||
m_buffer(new AUD_Buffer(size))
|
||||
{
|
||||
memcpy(m_buffer.get()->getBuffer(), buffer, size);
|
||||
memcpy(m_buffer->getBuffer(), buffer, size);
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_FFMPEGFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_FFMPEGFactory::createReader()
|
||||
{
|
||||
if(m_buffer.get())
|
||||
return new AUD_FFMPEGReader(m_buffer);
|
||||
else
|
||||
if(m_buffer.isNull())
|
||||
return new AUD_FFMPEGReader(m_filename);
|
||||
else
|
||||
return new AUD_FFMPEGReader(m_buffer);
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#include "AUD_IFactory.h"
|
||||
#include "AUD_Reference.h"
|
||||
class AUD_Buffer;
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -74,7 +74,7 @@ public:
|
||||
*/
|
||||
AUD_FFMPEGFactory(const data_t* buffer, int size);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_FFMPEGFACTORY
|
||||
|
@ -39,6 +39,7 @@
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavformat/avio.h>
|
||||
#include "ffmpeg_compat.h"
|
||||
}
|
||||
|
||||
@ -176,11 +177,12 @@ static const char* fileopen_error = "AUD_FFMPEGReader: File couldn't be "
|
||||
|
||||
AUD_FFMPEGReader::AUD_FFMPEGReader(std::string filename) :
|
||||
m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1),
|
||||
m_byteiocontext(NULL),
|
||||
m_formatCtx(NULL),
|
||||
m_aviocontext(NULL),
|
||||
m_membuf(NULL)
|
||||
{
|
||||
// open file
|
||||
if(av_open_input_file(&m_formatCtx, filename.c_str(), NULL, 0, NULL)!=0)
|
||||
if(avformat_open_input(&m_formatCtx, filename.c_str(), NULL, NULL)!=0)
|
||||
AUD_THROW(AUD_ERROR_FILE, fileopen_error);
|
||||
|
||||
try
|
||||
@ -204,25 +206,20 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) :
|
||||
{
|
||||
m_membuf = reinterpret_cast<data_t*>(av_malloc(FF_MIN_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE));
|
||||
|
||||
m_byteiocontext = av_alloc_put_byte(m_membuf, FF_MIN_BUFFER_SIZE, 0, this,
|
||||
m_aviocontext = avio_alloc_context(m_membuf, FF_MIN_BUFFER_SIZE, 0, this,
|
||||
read_packet, NULL, seek_packet);
|
||||
|
||||
if(!m_byteiocontext)
|
||||
if(!m_aviocontext)
|
||||
{
|
||||
av_free(m_byteiocontext);
|
||||
av_free(m_aviocontext);
|
||||
AUD_THROW(AUD_ERROR_FILE, fileopen_error);
|
||||
}
|
||||
|
||||
AVProbeData probe_data;
|
||||
probe_data.filename = "";
|
||||
probe_data.buf = reinterpret_cast<data_t*>(buffer.get()->getBuffer());
|
||||
probe_data.buf_size = buffer.get()->getSize();
|
||||
AVInputFormat* fmt = av_probe_input_format(&probe_data, 1);
|
||||
|
||||
// open stream
|
||||
if(av_open_input_stream(&m_formatCtx, m_byteiocontext, "", fmt, NULL)!=0)
|
||||
m_formatCtx = avformat_alloc_context();
|
||||
m_formatCtx->pb = m_aviocontext;
|
||||
if(avformat_open_input(&m_formatCtx, "", NULL, NULL)!=0)
|
||||
{
|
||||
av_free(m_byteiocontext);
|
||||
av_free(m_aviocontext);
|
||||
AUD_THROW(AUD_ERROR_FILE, streamopen_error);
|
||||
}
|
||||
|
||||
@ -233,7 +230,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) :
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
av_close_input_stream(m_formatCtx);
|
||||
av_free(m_byteiocontext);
|
||||
av_free(m_aviocontext);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@ -242,10 +239,10 @@ AUD_FFMPEGReader::~AUD_FFMPEGReader()
|
||||
{
|
||||
avcodec_close(m_codecCtx);
|
||||
|
||||
if(m_byteiocontext)
|
||||
if(m_aviocontext)
|
||||
{
|
||||
av_close_input_stream(m_formatCtx);
|
||||
av_free(m_byteiocontext);
|
||||
av_free(m_aviocontext);
|
||||
}
|
||||
else
|
||||
av_close_input_file(m_formatCtx);
|
||||
@ -255,12 +252,12 @@ int AUD_FFMPEGReader::read_packet(void* opaque, uint8_t* buf, int buf_size)
|
||||
{
|
||||
AUD_FFMPEGReader* reader = reinterpret_cast<AUD_FFMPEGReader*>(opaque);
|
||||
|
||||
int size = AUD_MIN(buf_size, reader->m_membuffer.get()->getSize() - reader->m_membufferpos);
|
||||
int size = AUD_MIN(buf_size, reader->m_membuffer->getSize() - reader->m_membufferpos);
|
||||
|
||||
if(size < 0)
|
||||
return -1;
|
||||
|
||||
memcpy(buf, ((data_t*)reader->m_membuffer.get()->getBuffer()) + reader->m_membufferpos, size);
|
||||
memcpy(buf, ((data_t*)reader->m_membuffer->getBuffer()) + reader->m_membufferpos, size);
|
||||
reader->m_membufferpos += size;
|
||||
|
||||
return size;
|
||||
@ -276,10 +273,10 @@ int64_t AUD_FFMPEGReader::seek_packet(void* opaque, int64_t offset, int whence)
|
||||
reader->m_membufferpos = 0;
|
||||
break;
|
||||
case SEEK_END:
|
||||
reader->m_membufferpos = reader->m_membuffer.get()->getSize();
|
||||
reader->m_membufferpos = reader->m_membuffer->getSize();
|
||||
break;
|
||||
case AVSEEK_SIZE:
|
||||
return reader->m_membuffer.get()->getSize();
|
||||
return reader->m_membuffer->getSize();
|
||||
}
|
||||
|
||||
return (reader->m_membufferpos += offset);
|
||||
@ -341,14 +338,15 @@ void AUD_FFMPEGReader::seek(int position)
|
||||
{
|
||||
// read until we're at the right position
|
||||
int length = AUD_DEFAULT_BUFFER_SIZE;
|
||||
sample_t* buffer;
|
||||
AUD_Buffer buffer(length * AUD_SAMPLE_SIZE(m_specs));
|
||||
bool eos;
|
||||
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);
|
||||
read(length, eos, buffer.getBuffer());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -381,7 +379,7 @@ AUD_Specs AUD_FFMPEGReader::getSpecs() const
|
||||
return m_specs.specs;
|
||||
}
|
||||
|
||||
void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_FFMPEGReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
// read packages and decode them
|
||||
AVPacket packet;
|
||||
@ -390,11 +388,7 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
|
||||
int left = length;
|
||||
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));
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
sample_t* buf = buffer;
|
||||
pkgbuf_pos = m_pkgbuf_left;
|
||||
m_pkgbuf_left = 0;
|
||||
|
||||
@ -402,9 +396,9 @@ 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*) buf, (data_t*) m_pkgbuf.getBuffer(),
|
||||
data_size / AUD_FORMAT_SIZE(m_specs.format));
|
||||
buffer += data_size / AUD_FORMAT_SIZE(m_specs.format);
|
||||
buf += data_size / AUD_FORMAT_SIZE(m_specs.format);
|
||||
left -= data_size/sample_size;
|
||||
}
|
||||
|
||||
@ -419,9 +413,9 @@ 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*) buf, (data_t*) m_pkgbuf.getBuffer(),
|
||||
data_size / AUD_FORMAT_SIZE(m_specs.format));
|
||||
buffer += data_size / AUD_FORMAT_SIZE(m_specs.format);
|
||||
buf += data_size / AUD_FORMAT_SIZE(m_specs.format);
|
||||
left -= data_size/sample_size;
|
||||
}
|
||||
av_free_packet(&packet);
|
||||
@ -435,9 +429,8 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
|
||||
pkgbuf_pos-data_size);
|
||||
}
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
|
||||
if(left > 0)
|
||||
if((eos = (left > 0)))
|
||||
length -= left;
|
||||
|
||||
m_position += length;
|
||||
}
|
||||
|
@ -49,8 +49,6 @@ extern "C" {
|
||||
* \warning Seeking may not be accurate! Moreover the position is updated after
|
||||
* a buffer reading call. So calling getPosition right after seek
|
||||
* normally results in a wrong value.
|
||||
* \warning Playback of an ogg with some outdated ffmpeg versions results in a
|
||||
* segfault on windows.
|
||||
*/
|
||||
class AUD_FFMPEGReader : public AUD_IReader
|
||||
{
|
||||
@ -60,11 +58,6 @@ private:
|
||||
*/
|
||||
int m_position;
|
||||
|
||||
/**
|
||||
* The playback buffer.
|
||||
*/
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The specification of the audio data.
|
||||
*/
|
||||
@ -91,9 +84,9 @@ private:
|
||||
AVCodecContext* m_codecCtx;
|
||||
|
||||
/**
|
||||
* The ByteIOContext to read the data from.
|
||||
* The AVIOContext to read the data from.
|
||||
*/
|
||||
ByteIOContext* m_byteiocontext;
|
||||
AVIOContext* m_aviocontext;
|
||||
|
||||
/**
|
||||
* The stream ID in the file.
|
||||
@ -167,7 +160,7 @@ public:
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_FFMPEGREADER
|
||||
|
305
intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
Normal file
305
intern/audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
Normal file
@ -0,0 +1,305 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009-2011 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* Audaspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Audaspace; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file audaspace/ffmpeg/AUD_FFMPEGWriter.cpp
|
||||
* \ingroup audffmpeg
|
||||
*/
|
||||
|
||||
|
||||
// needed for INT64_C
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#include "AUD_FFMPEGWriter.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavformat/avio.h>
|
||||
#include "ffmpeg_compat.h"
|
||||
}
|
||||
|
||||
static const char* context_error = "AUD_FFMPEGWriter: Couldn't allocate context.";
|
||||
static const char* codec_error = "AUD_FFMPEGWriter: Invalid codec or codec not found.";
|
||||
static const char* stream_error = "AUD_FFMPEGWriter: Couldn't allocate stream.";
|
||||
static const char* format_error = "AUD_FFMPEGWriter: Unsupported sample format.";
|
||||
static const char* file_error = "AUD_FFMPEGWriter: File couldn't be written.";
|
||||
static const char* write_error = "AUD_FFMPEGWriter: Error writing packet.";
|
||||
|
||||
AUD_FFMPEGWriter::AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate) :
|
||||
m_position(0),
|
||||
m_specs(specs),
|
||||
m_input_samples(0)
|
||||
{
|
||||
static const char* formats[] = { NULL, "ac3", "flac", "matroska", "mp2", "mp3", "ogg", "wav" };
|
||||
|
||||
if(avformat_alloc_output_context2(&m_formatCtx, NULL, formats[format], filename.c_str()))
|
||||
AUD_THROW(AUD_ERROR_FFMPEG, context_error);
|
||||
|
||||
m_outputFmt = m_formatCtx->oformat;
|
||||
|
||||
switch(codec)
|
||||
{
|
||||
case AUD_CODEC_AAC:
|
||||
m_outputFmt->audio_codec = CODEC_ID_AAC;
|
||||
break;
|
||||
case AUD_CODEC_AC3:
|
||||
m_outputFmt->audio_codec = CODEC_ID_AC3;
|
||||
break;
|
||||
case AUD_CODEC_FLAC:
|
||||
m_outputFmt->audio_codec = CODEC_ID_FLAC;
|
||||
break;
|
||||
case AUD_CODEC_MP2:
|
||||
m_outputFmt->audio_codec = CODEC_ID_MP2;
|
||||
break;
|
||||
case AUD_CODEC_MP3:
|
||||
m_outputFmt->audio_codec = CODEC_ID_MP3;
|
||||
break;
|
||||
case AUD_CODEC_PCM:
|
||||
switch(specs.format)
|
||||
{
|
||||
case AUD_FORMAT_U8:
|
||||
m_outputFmt->audio_codec = CODEC_ID_PCM_U8;
|
||||
break;
|
||||
case AUD_FORMAT_S16:
|
||||
m_outputFmt->audio_codec = CODEC_ID_PCM_S16LE;
|
||||
break;
|
||||
case AUD_FORMAT_S24:
|
||||
m_outputFmt->audio_codec = CODEC_ID_PCM_S24LE;
|
||||
break;
|
||||
case AUD_FORMAT_S32:
|
||||
m_outputFmt->audio_codec = CODEC_ID_PCM_S32LE;
|
||||
break;
|
||||
case AUD_FORMAT_FLOAT32:
|
||||
m_outputFmt->audio_codec = CODEC_ID_PCM_F32LE;
|
||||
break;
|
||||
case AUD_FORMAT_FLOAT64:
|
||||
m_outputFmt->audio_codec = CODEC_ID_PCM_F64LE;
|
||||
break;
|
||||
default:
|
||||
m_outputFmt->audio_codec = CODEC_ID_NONE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AUD_CODEC_VORBIS:
|
||||
m_outputFmt->audio_codec = CODEC_ID_VORBIS;
|
||||
break;
|
||||
default:
|
||||
m_outputFmt->audio_codec = CODEC_ID_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(m_outputFmt->audio_codec == CODEC_ID_NONE)
|
||||
AUD_THROW(AUD_ERROR_SPECS, codec_error);
|
||||
|
||||
m_stream = av_new_stream(m_formatCtx, 0);
|
||||
if(!m_stream)
|
||||
AUD_THROW(AUD_ERROR_FFMPEG, stream_error);
|
||||
|
||||
m_codecCtx = m_stream->codec;
|
||||
m_codecCtx->codec_id = m_outputFmt->audio_codec;
|
||||
m_codecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
m_codecCtx->bit_rate = bitrate;
|
||||
m_codecCtx->sample_rate = int(m_specs.rate);
|
||||
m_codecCtx->channels = m_specs.channels;
|
||||
m_codecCtx->time_base.num = 1;
|
||||
m_codecCtx->time_base.den = m_codecCtx->sample_rate;
|
||||
|
||||
switch(m_specs.format)
|
||||
{
|
||||
case AUD_FORMAT_U8:
|
||||
m_convert = AUD_convert_float_u8;
|
||||
m_codecCtx->sample_fmt = SAMPLE_FMT_U8;
|
||||
break;
|
||||
case AUD_FORMAT_S16:
|
||||
m_convert = AUD_convert_float_s16;
|
||||
m_codecCtx->sample_fmt = SAMPLE_FMT_S16;
|
||||
break;
|
||||
case AUD_FORMAT_S32:
|
||||
m_convert = AUD_convert_float_s32;
|
||||
m_codecCtx->sample_fmt = SAMPLE_FMT_S32;
|
||||
break;
|
||||
case AUD_FORMAT_FLOAT32:
|
||||
m_convert = AUD_convert_copy<float>;
|
||||
m_codecCtx->sample_fmt = SAMPLE_FMT_FLT;
|
||||
break;
|
||||
case AUD_FORMAT_FLOAT64:
|
||||
m_convert = AUD_convert_float_double;
|
||||
m_codecCtx->sample_fmt = SAMPLE_FMT_DBL;
|
||||
break;
|
||||
default:
|
||||
AUD_THROW(AUD_ERROR_FFMPEG, format_error);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(m_formatCtx->oformat->flags & AVFMT_GLOBALHEADER)
|
||||
m_codecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
|
||||
AVCodec* codec = avcodec_find_encoder(m_codecCtx->codec_id);
|
||||
if(!codec)
|
||||
AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
|
||||
|
||||
if(avcodec_open(m_codecCtx, codec))
|
||||
AUD_THROW(AUD_ERROR_FFMPEG, codec_error);
|
||||
|
||||
m_output_buffer.resize(FF_MIN_BUFFER_SIZE);
|
||||
int samplesize = AUD_MAX(AUD_SAMPLE_SIZE(m_specs), AUD_DEVICE_SAMPLE_SIZE(m_specs));
|
||||
|
||||
if(m_codecCtx->frame_size <= 1)
|
||||
m_input_size = 0;
|
||||
else
|
||||
{
|
||||
m_input_buffer.resize(m_codecCtx->frame_size * samplesize);
|
||||
m_input_size = m_codecCtx->frame_size;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if(avio_open(&m_formatCtx->pb, filename.c_str(), AVIO_FLAG_WRITE))
|
||||
AUD_THROW(AUD_ERROR_FILE, file_error);
|
||||
|
||||
avformat_write_header(m_formatCtx, NULL);
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
avcodec_close(m_codecCtx);
|
||||
av_freep(&m_formatCtx->streams[0]->codec);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
av_freep(&m_formatCtx->streams[0]);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch(AUD_Exception&)
|
||||
{
|
||||
av_free(m_formatCtx);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
AUD_FFMPEGWriter::~AUD_FFMPEGWriter()
|
||||
{
|
||||
// writte missing data
|
||||
if(m_input_samples)
|
||||
{
|
||||
sample_t* buf = m_input_buffer.getBuffer();
|
||||
memset(buf + m_specs.channels * m_input_samples, 0,
|
||||
(m_input_size - m_input_samples) * AUD_DEVICE_SAMPLE_SIZE(m_specs));
|
||||
|
||||
encode(buf);
|
||||
}
|
||||
|
||||
av_write_trailer(m_formatCtx);
|
||||
|
||||
avcodec_close(m_codecCtx);
|
||||
|
||||
av_freep(&m_formatCtx->streams[0]->codec);
|
||||
av_freep(&m_formatCtx->streams[0]);
|
||||
|
||||
avio_close(m_formatCtx->pb);
|
||||
av_free(m_formatCtx);
|
||||
}
|
||||
|
||||
int AUD_FFMPEGWriter::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
AUD_DeviceSpecs AUD_FFMPEGWriter::getSpecs() const
|
||||
{
|
||||
return m_specs;
|
||||
}
|
||||
|
||||
void AUD_FFMPEGWriter::encode(sample_t* data)
|
||||
{
|
||||
sample_t* outbuf = m_output_buffer.getBuffer();
|
||||
|
||||
// convert first
|
||||
if(m_input_size)
|
||||
m_convert(reinterpret_cast<data_t*>(data), reinterpret_cast<data_t*>(data), m_input_size * m_specs.channels);
|
||||
|
||||
AVPacket packet;
|
||||
av_init_packet(&packet);
|
||||
packet.size = avcodec_encode_audio(m_codecCtx, reinterpret_cast<uint8_t*>(outbuf), m_output_buffer.getSize(), reinterpret_cast<short*>(data));
|
||||
if(m_codecCtx->coded_frame && m_codecCtx->coded_frame->pts != AV_NOPTS_VALUE)
|
||||
packet.pts = av_rescale_q(m_codecCtx->coded_frame->pts, m_codecCtx->time_base, m_stream->time_base);
|
||||
packet.flags |= AV_PKT_FLAG_KEY;
|
||||
packet.stream_index = m_stream->index;
|
||||
packet.data = reinterpret_cast<uint8_t*>(outbuf);
|
||||
|
||||
if(av_interleaved_write_frame(m_formatCtx, &packet))
|
||||
AUD_THROW(AUD_ERROR_FFMPEG, write_error);
|
||||
}
|
||||
|
||||
void AUD_FFMPEGWriter::write(unsigned int length, sample_t* buffer)
|
||||
{
|
||||
unsigned int samplesize = AUD_SAMPLE_SIZE(m_specs);
|
||||
|
||||
if(m_input_size)
|
||||
{
|
||||
sample_t* inbuf = m_input_buffer.getBuffer();
|
||||
|
||||
while(length)
|
||||
{
|
||||
unsigned int len = AUD_MIN(m_input_size - m_input_samples, length);
|
||||
|
||||
memcpy(inbuf + m_input_samples * m_specs.channels, buffer, len * samplesize);
|
||||
|
||||
buffer += len * m_specs.channels;
|
||||
m_input_samples += len;
|
||||
m_position += len;
|
||||
length -= len;
|
||||
|
||||
if(m_input_samples == m_input_size)
|
||||
{
|
||||
encode(inbuf);
|
||||
|
||||
m_input_samples = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // PCM data, can write directly!
|
||||
{
|
||||
int samplesize = AUD_SAMPLE_SIZE(m_specs);
|
||||
if(m_output_buffer.getSize() != length * m_specs.channels * m_codecCtx->bits_per_coded_sample / 8)
|
||||
m_output_buffer.resize(length * m_specs.channels * m_codecCtx->bits_per_coded_sample / 8);
|
||||
m_input_buffer.assureSize(length * AUD_MAX(AUD_DEVICE_SAMPLE_SIZE(m_specs), samplesize));
|
||||
|
||||
sample_t* buf = m_input_buffer.getBuffer();
|
||||
m_convert(reinterpret_cast<data_t*>(buf), reinterpret_cast<data_t*>(buffer), length * m_specs.channels);
|
||||
|
||||
encode(buf);
|
||||
|
||||
m_position += length;
|
||||
}
|
||||
}
|
140
intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h
Normal file
140
intern/audaspace/ffmpeg/AUD_FFMPEGWriter.h
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009-2011 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* Audaspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Audaspace; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file audaspace/ffmpeg/AUD_FFMPEGWriter.h
|
||||
* \ingroup audffmpeg
|
||||
*/
|
||||
|
||||
|
||||
#ifndef AUD_FFMPEGWRITER
|
||||
#define AUD_FFMPEGWRITER
|
||||
|
||||
#include "AUD_ConverterFunctions.h"
|
||||
#include "AUD_Buffer.h"
|
||||
#include "AUD_IWriter.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
struct AVCodecContext;
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
}
|
||||
|
||||
/**
|
||||
* This class writes a sound file via ffmpeg.
|
||||
*/
|
||||
class AUD_FFMPEGWriter : public AUD_IWriter
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The current position in samples.
|
||||
*/
|
||||
int m_position;
|
||||
|
||||
/**
|
||||
* The specification of the audio data.
|
||||
*/
|
||||
AUD_DeviceSpecs m_specs;
|
||||
|
||||
/**
|
||||
* The AVFormatContext structure for using ffmpeg.
|
||||
*/
|
||||
AVFormatContext* m_formatCtx;
|
||||
|
||||
/**
|
||||
* The AVCodecContext structure for using ffmpeg.
|
||||
*/
|
||||
AVCodecContext* m_codecCtx;
|
||||
|
||||
/**
|
||||
* The AVOutputFormat structure for using ffmpeg.
|
||||
*/
|
||||
AVOutputFormat* m_outputFmt;
|
||||
|
||||
/**
|
||||
* The AVStream structure for using ffmpeg.
|
||||
*/
|
||||
AVStream* m_stream;
|
||||
|
||||
/**
|
||||
* The input buffer for the format converted data before encoding.
|
||||
*/
|
||||
AUD_Buffer m_input_buffer;
|
||||
|
||||
/**
|
||||
* The output buffer for the encoded audio data.
|
||||
*/
|
||||
AUD_Buffer m_output_buffer;
|
||||
|
||||
/**
|
||||
* The count of input samples we have so far.
|
||||
*/
|
||||
unsigned int m_input_samples;
|
||||
|
||||
/**
|
||||
* The count of input samples necessary to encode a packet.
|
||||
*/
|
||||
unsigned int m_input_size;
|
||||
|
||||
/**
|
||||
* Converter function.
|
||||
*/
|
||||
AUD_convert_f m_convert;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_FFMPEGWriter(const AUD_FFMPEGWriter&);
|
||||
AUD_FFMPEGWriter& operator=(const AUD_FFMPEGWriter&);
|
||||
|
||||
/**
|
||||
* Encodes to the output buffer.
|
||||
* \param data Pointer to the data to encode.
|
||||
*/
|
||||
void encode(sample_t* data);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new writer.
|
||||
* \param filename The path to the file to be read.
|
||||
* \param specs The file's audio specification.
|
||||
* \param format The file's container format.
|
||||
* \param codec The codec used for encoding the audio data.
|
||||
* \param bitrate The bitrate for encoding.
|
||||
* \exception AUD_Exception Thrown if the file specified does not exist or
|
||||
* cannot be read with ffmpeg.
|
||||
*/
|
||||
AUD_FFMPEGWriter(std::string filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate);
|
||||
|
||||
/**
|
||||
* Destroys the writer and closes the file.
|
||||
*/
|
||||
virtual ~AUD_FFMPEGWriter();
|
||||
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_DeviceSpecs getSpecs() const;
|
||||
virtual void write(unsigned int length, sample_t* buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_FFMPEGWRITER
|
@ -71,8 +71,7 @@ void AUD_BandPassReader::read(int & length, sample_t* & buffer)
|
||||
|
||||
if(length > 0)
|
||||
{
|
||||
if(length * AUD_SAMPLE_SIZE(specs) > m_buffer->getSize())
|
||||
m_buffer->resize(length * AUD_SAMPLE_SIZE(specs));
|
||||
m_buffer->assureSize(length * AUD_SAMPLE_SIZE(specs));
|
||||
|
||||
if(length != m_length)
|
||||
{
|
||||
|
@ -32,9 +32,188 @@
|
||||
#ifndef AUD_3DMATH
|
||||
#define AUD_3DMATH
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
/**
|
||||
* This class represents a 3 dimensional vector.
|
||||
*/
|
||||
class AUD_Vector3
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The vector components.
|
||||
*/
|
||||
union
|
||||
{
|
||||
float m_v[3];
|
||||
struct
|
||||
{
|
||||
float m_x;
|
||||
float m_y;
|
||||
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 = 0, float y = 0, float z = 0) :
|
||||
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
|
||||
{
|
||||
memcpy(destination, m_v, sizeof(m_v));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the components of the vector.
|
||||
* \return The components as float[3].
|
||||
*/
|
||||
inline float* get()
|
||||
{
|
||||
return m_v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the components of the vector.
|
||||
* \return The components as float[3].
|
||||
*/
|
||||
inline const float* get() const
|
||||
{
|
||||
return m_v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the length of the vector.
|
||||
* \return The length of the vector.
|
||||
*/
|
||||
inline float length() const
|
||||
{
|
||||
return sqrt(m_x*m_x + m_y*m_y + m_z*m_z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the cross product.
|
||||
* \param op The second operand.
|
||||
* \return The cross product of the two vectors.
|
||||
*/
|
||||
inline AUD_Vector3 cross(const AUD_Vector3& op) const
|
||||
{
|
||||
return AUD_Vector3(m_y * op.m_z - m_z * op.m_y,
|
||||
m_z * op.m_x - m_x * op.m_z,
|
||||
m_x * op.m_y - m_y * op.m_x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the dot product.
|
||||
* \param op The second operand.
|
||||
* \return The dot product of the two vectors.
|
||||
*/
|
||||
inline float operator*(const AUD_Vector3& op) const
|
||||
{
|
||||
return m_x * op.m_x + m_y * op.m_y + m_z * op.m_z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the product with a scalar.
|
||||
* \param op The second operand.
|
||||
* \return The scaled vector.
|
||||
*/
|
||||
inline AUD_Vector3 operator*(const float& op) const
|
||||
{
|
||||
return AUD_Vector3(m_x * op, m_y * op, m_z * op);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two vectors.
|
||||
* \param op The second operand.
|
||||
* \return The sum vector.
|
||||
*/
|
||||
inline AUD_Vector3 operator+(const AUD_Vector3& op) const
|
||||
{
|
||||
return AUD_Vector3(m_x + op.m_x, m_y + op.m_y, m_z + op.m_z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts two vectors.
|
||||
* \param op The second operand.
|
||||
* \return The difference vector.
|
||||
*/
|
||||
inline AUD_Vector3 operator-(const AUD_Vector3& op) const
|
||||
{
|
||||
return AUD_Vector3(m_x - op.m_x, m_y - op.m_y, m_z - op.m_z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Negates the vector.
|
||||
* \return The vector facing in the opposite direction.
|
||||
*/
|
||||
inline AUD_Vector3 operator-() const
|
||||
{
|
||||
return AUD_Vector3(-m_x, -m_y, -m_z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts the second vector.
|
||||
* \param op The second operand.
|
||||
* \return The difference vector.
|
||||
*/
|
||||
inline AUD_Vector3& operator-=(const AUD_Vector3& op)
|
||||
{
|
||||
m_x -= op.m_x;
|
||||
m_y -= op.m_y;
|
||||
m_z -= op.m_z;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This class represents a quaternion used for 3D rotations.
|
||||
*/
|
||||
class AUD_Quaternion
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The quaternion components.
|
||||
*/
|
||||
union
|
||||
{
|
||||
float m_v[4];
|
||||
@ -55,7 +234,7 @@ public:
|
||||
* \param y The y component.
|
||||
* \param z The z component.
|
||||
*/
|
||||
inline AUD_Quaternion(float w, float x, float y, float z) :
|
||||
inline AUD_Quaternion(float w = 1, float x = 0, float y = 0, float z = 0) :
|
||||
m_w(w), m_x(x), m_y(y), m_z(z)
|
||||
{
|
||||
}
|
||||
@ -102,10 +281,16 @@ public:
|
||||
*/
|
||||
inline void get(float* destination) const
|
||||
{
|
||||
destination[0] = m_w;
|
||||
destination[1] = m_x;
|
||||
destination[2] = m_y;
|
||||
destination[3] = m_z;
|
||||
memcpy(destination, m_v, sizeof(m_v));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the components of the vector.
|
||||
* \return The components as float[4].
|
||||
*/
|
||||
inline float* get()
|
||||
{
|
||||
return m_v;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,79 +301,29 @@ public:
|
||||
{
|
||||
return m_v;
|
||||
}
|
||||
};
|
||||
|
||||
class AUD_Vector3
|
||||
{
|
||||
private:
|
||||
union
|
||||
{
|
||||
float m_v[3];
|
||||
struct
|
||||
{
|
||||
float m_x;
|
||||
float m_y;
|
||||
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.
|
||||
* When the quaternion represents an orientation, this returns the negative
|
||||
* z axis vector.
|
||||
* \return The negative z axis vector.
|
||||
*/
|
||||
inline AUD_Vector3(float x, float y, float z) :
|
||||
m_x(x), m_y(y), m_z(z)
|
||||
inline AUD_Vector3 getLookAt() const
|
||||
{
|
||||
return AUD_Vector3(-2 * (m_w * m_y + m_x * m_z),
|
||||
2 * (m_x * m_w - m_z * m_y),
|
||||
2 * (m_x * m_x + m_y * m_y) - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the x component of the vector.
|
||||
* \return The x component.
|
||||
* When the quaternion represents an orientation, this returns the y axis
|
||||
* vector.
|
||||
* \return The y axis vector.
|
||||
*/
|
||||
inline const float& x() const
|
||||
inline AUD_Vector3 getUp() 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;
|
||||
return AUD_Vector3(2 * (m_x * m_y - m_w * m_z),
|
||||
1 - 2 * (m_x * m_x + m_z * m_z),
|
||||
2 * (m_w * m_x + m_y * m_z));
|
||||
}
|
||||
};
|
||||
|
||||
|
159
intern/audaspace/intern/AUD_AnimateableProperty.cpp
Normal file
159
intern/audaspace/intern/AUD_AnimateableProperty.cpp
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009-2011 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* Audaspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Audaspace; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file audaspace/intern/AUD_AnimateableProperty.cpp
|
||||
* \ingroup audaspaceintern
|
||||
*/
|
||||
|
||||
|
||||
#include "AUD_AnimateableProperty.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
AUD_AnimateableProperty::AUD_AnimateableProperty(int count) :
|
||||
AUD_Buffer(count * sizeof(float)), m_count(count), m_isAnimated(false)
|
||||
{
|
||||
memset(getBuffer(), 0, count * sizeof(float));
|
||||
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
|
||||
pthread_mutex_init(&m_mutex, &attr);
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
}
|
||||
|
||||
AUD_AnimateableProperty::~AUD_AnimateableProperty()
|
||||
{
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
}
|
||||
|
||||
void AUD_AnimateableProperty::lock()
|
||||
{
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
}
|
||||
|
||||
void AUD_AnimateableProperty::unlock()
|
||||
{
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
}
|
||||
|
||||
void AUD_AnimateableProperty::write(const float* data)
|
||||
{
|
||||
lock();
|
||||
|
||||
m_isAnimated = false;
|
||||
memcpy(getBuffer(), data, m_count * sizeof(float));
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
void AUD_AnimateableProperty::write(const float* data, int position, int count)
|
||||
{
|
||||
lock();
|
||||
|
||||
m_isAnimated = true;
|
||||
|
||||
int pos = getSize() / (sizeof(float) * m_count);
|
||||
|
||||
assureSize((count + position) * m_count * sizeof(float), true);
|
||||
|
||||
float* buf = getBuffer();
|
||||
|
||||
memcpy(buf + position * m_count, data, count * m_count * sizeof(float));
|
||||
|
||||
for(int i = pos; i < position; i++)
|
||||
memcpy(buf + i * m_count, buf + (pos - 1) * m_count, m_count * sizeof(float));
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
void AUD_AnimateableProperty::read(float position, float* out)
|
||||
{
|
||||
lock();
|
||||
|
||||
if(!m_isAnimated)
|
||||
{
|
||||
memcpy(out, getBuffer(), m_count * sizeof(float));
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
int last = getSize() / (sizeof(float) * m_count) - 1;
|
||||
float t = position - floor(position);
|
||||
|
||||
if(position >= last)
|
||||
{
|
||||
position = last;
|
||||
t = 0;
|
||||
}
|
||||
|
||||
if(t == 0)
|
||||
{
|
||||
memcpy(out, getBuffer() + int(floor(position)) * m_count, m_count * sizeof(float));
|
||||
}
|
||||
else
|
||||
{
|
||||
int pos = int(floor(position)) * m_count;
|
||||
float t2 = t * t;
|
||||
float t3 = t2 * t;
|
||||
float m0, m1;
|
||||
float* p0;
|
||||
float* p1 = getBuffer() + pos;
|
||||
float* p2;
|
||||
float* p3;
|
||||
last *= m_count;
|
||||
|
||||
if(pos == 0)
|
||||
p0 = p1;
|
||||
else
|
||||
p0 = p1 - m_count;
|
||||
|
||||
p2 = p1 + m_count;
|
||||
if(pos + m_count == last)
|
||||
p3 = p2;
|
||||
else
|
||||
p3 = p2 + m_count;
|
||||
|
||||
for(int i = 0; i < m_count; i++)
|
||||
{
|
||||
m0 = (p2[i] - p0[i]) / 2.0f;
|
||||
m1 = (p3[i] - p1[i]) / 2.0f;
|
||||
|
||||
out[i] = (2 * t3 - 3 * t2 + 1) * p0[i] + (-2 * t3 + 3 * t2) * p1[i] +
|
||||
(t3 - 2 * t2 + t) * m0 + (t3 - t2) * m1;
|
||||
}
|
||||
}
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
bool AUD_AnimateableProperty::isAnimated() const
|
||||
{
|
||||
return m_isAnimated;
|
||||
}
|
108
intern/audaspace/intern/AUD_AnimateableProperty.h
Normal file
108
intern/audaspace/intern/AUD_AnimateableProperty.h
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||
*
|
||||
* Copyright 2009-2011 Jörg Hermann Müller
|
||||
*
|
||||
* This file is part of AudaSpace.
|
||||
*
|
||||
* Audaspace is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* AudaSpace is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Audaspace; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file audaspace/intern/AUD_AnimateableProperty.h
|
||||
* \ingroup audaspaceintern
|
||||
*/
|
||||
|
||||
|
||||
#ifndef AUD_ANIMATEABLEPROPERTY
|
||||
#define AUD_ANIMATEABLEPROPERTY
|
||||
|
||||
#include "AUD_Buffer.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/**
|
||||
* This class saves animation data for float properties.
|
||||
*/
|
||||
class AUD_AnimateableProperty : private AUD_Buffer
|
||||
{
|
||||
private:
|
||||
/// The count of floats for a single property.
|
||||
const int m_count;
|
||||
|
||||
/// Whether the property is animated or not.
|
||||
bool m_isAnimated;
|
||||
|
||||
/// The mutex for locking.
|
||||
pthread_mutex_t m_mutex;
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_AnimateableProperty(const AUD_AnimateableProperty&);
|
||||
AUD_AnimateableProperty& operator=(const AUD_AnimateableProperty&);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new animateable property.
|
||||
* \param count The count of floats for a single property.
|
||||
*/
|
||||
AUD_AnimateableProperty(int count = 1);
|
||||
|
||||
/**
|
||||
* Destroys the animateable property.
|
||||
*/
|
||||
~AUD_AnimateableProperty();
|
||||
|
||||
/**
|
||||
* Locks the property.
|
||||
*/
|
||||
void lock();
|
||||
|
||||
/**
|
||||
* Unlocks the previously locked property.
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
/**
|
||||
* Writes the properties value and marks it non-animated.
|
||||
* \param data The new value.
|
||||
*/
|
||||
void write(const float* data);
|
||||
|
||||
/**
|
||||
* Writes the properties value and marks it animated.
|
||||
* \param data The new value.
|
||||
* \param position The position in the animation in frames.
|
||||
* \param count The count of frames to write.
|
||||
*/
|
||||
void write(const float* data, int position, int count);
|
||||
|
||||
/**
|
||||
* Reads the properties value.
|
||||
* \param position The position in the animation in frames.
|
||||
* \param[out] out Where to write the value to.
|
||||
*/
|
||||
void read(float position, float* out);
|
||||
|
||||
/**
|
||||
* Returns whether the property is animated.
|
||||
* \return Whether the property is animated.
|
||||
*/
|
||||
bool isAnimated() const;
|
||||
};
|
||||
|
||||
#endif //AUD_ANIMATEABLEPROPERTY
|
@ -74,3 +74,9 @@ void AUD_Buffer::resize(int size, bool keep)
|
||||
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
void AUD_Buffer::assureSize(int size, bool keep)
|
||||
{
|
||||
if(m_size < size)
|
||||
resize(size, keep);
|
||||
}
|
||||
|
@ -80,6 +80,16 @@ public:
|
||||
* the data at the end will be lost.
|
||||
*/
|
||||
void resize(int size, bool keep = false);
|
||||
|
||||
/**
|
||||
* Makes sure the buffer has a minimum size.
|
||||
* If size is >= current size, nothing will happen.
|
||||
* Otherwise the buffer is resized with keep as parameter.
|
||||
* \param size The new minimum size of the buffer, measured in bytes.
|
||||
* \param keep Whether to keep the old data. If the new buffer is smaller,
|
||||
* the data at the end will be lost.
|
||||
*/
|
||||
void assureSize(int size, bool keep = false);
|
||||
};
|
||||
|
||||
#endif //AUD_BUFFER
|
||||
|
@ -33,6 +33,8 @@
|
||||
#include "AUD_Buffer.h"
|
||||
#include "AUD_Space.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_BufferReader::AUD_BufferReader(AUD_Reference<AUD_Buffer> buffer,
|
||||
AUD_Specs specs) :
|
||||
m_position(0), m_buffer(buffer), m_specs(specs)
|
||||
@ -51,7 +53,7 @@ void AUD_BufferReader::seek(int position)
|
||||
|
||||
int AUD_BufferReader::getLength() const
|
||||
{
|
||||
return m_buffer.get()->getSize() / AUD_SAMPLE_SIZE(m_specs);
|
||||
return m_buffer->getSize() / AUD_SAMPLE_SIZE(m_specs);
|
||||
}
|
||||
|
||||
int AUD_BufferReader::getPosition() const
|
||||
@ -64,17 +66,27 @@ AUD_Specs AUD_BufferReader::getSpecs() const
|
||||
return m_specs;
|
||||
}
|
||||
|
||||
void AUD_BufferReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_BufferReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
eos = false;
|
||||
|
||||
int sample_size = AUD_SAMPLE_SIZE(m_specs);
|
||||
|
||||
buffer = m_buffer.get()->getBuffer() + m_position * m_specs.channels;
|
||||
sample_t* buf = m_buffer->getBuffer() + m_position * m_specs.channels;
|
||||
|
||||
// in case the end of the buffer is reached
|
||||
if(m_buffer.get()->getSize() < (m_position + length) * sample_size)
|
||||
length = m_buffer.get()->getSize() / sample_size - m_position;
|
||||
if(m_buffer->getSize() < (m_position + length) * sample_size)
|
||||
{
|
||||
length = m_buffer->getSize() / sample_size - m_position;
|
||||
eos = true;
|
||||
}
|
||||
|
||||
if(length < 0)
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
m_position += length;
|
||||
memcpy(buffer, buf, length * sample_size);
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
virtual int getLength() const;
|
||||
virtual int getPosition() const;
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_BUFFERREADER
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,12 +31,17 @@
|
||||
#ifndef AUD_CAPI
|
||||
#define AUD_CAPI
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
#include "Python.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "AUD_Space.h"
|
||||
|
||||
/// Supported output devices.
|
||||
typedef enum
|
||||
{
|
||||
AUD_NULL_DEVICE = 0,
|
||||
@ -45,6 +50,7 @@ typedef enum
|
||||
AUD_JACK_DEVICE
|
||||
} AUD_DeviceType;
|
||||
|
||||
/// Sound information structure.
|
||||
typedef struct
|
||||
{
|
||||
AUD_Specs specs;
|
||||
@ -53,9 +59,9 @@ typedef struct
|
||||
|
||||
#ifndef AUD_CAPI_IMPLEMENTATION
|
||||
typedef void AUD_Sound;
|
||||
typedef void AUD_Channel;
|
||||
typedef void AUD_Handle;
|
||||
typedef void AUD_Device;
|
||||
typedef void AUD_SequencerEntry;
|
||||
typedef void AUD_SEntry;
|
||||
typedef float (*AUD_volumeFunction)(void*, void*, float);
|
||||
typedef void (*AUD_syncFunction)(void*, int, float);
|
||||
#endif
|
||||
@ -118,6 +124,13 @@ extern AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size);
|
||||
*/
|
||||
extern AUD_Sound* AUD_bufferSound(AUD_Sound* sound);
|
||||
|
||||
/**
|
||||
* Rechannels the sound to be mono.
|
||||
* \param sound The sound to rechannel.
|
||||
* \return The mono sound.
|
||||
*/
|
||||
extern AUD_Sound* AUD_monoSound(AUD_Sound* sound);
|
||||
|
||||
/**
|
||||
* Delays a sound.
|
||||
* \param sound The sound to dealy.
|
||||
@ -155,7 +168,7 @@ extern AUD_Sound* AUD_loopSound(AUD_Sound* sound);
|
||||
* \param loops The count of remaining loops, -1 for infinity.
|
||||
* \return Whether the handle is valid.
|
||||
*/
|
||||
extern int AUD_setLoop(AUD_Channel* handle, int loops);
|
||||
extern int AUD_setLoop(AUD_Handle* handle, int loops);
|
||||
|
||||
/**
|
||||
* Rectifies a sound.
|
||||
@ -177,28 +190,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_Channel* AUD_play(AUD_Sound* sound, int keep);
|
||||
extern AUD_Handle* 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_Channel* handle);
|
||||
extern int AUD_pause(AUD_Handle* 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_Channel* handle);
|
||||
extern int AUD_resume(AUD_Handle* 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_Channel* handle);
|
||||
extern int AUD_stop(AUD_Handle* handle);
|
||||
|
||||
/**
|
||||
* Sets the end behaviour of a playing or paused sound.
|
||||
@ -207,7 +220,7 @@ extern int AUD_stop(AUD_Channel* handle);
|
||||
* paused when its end has been reached.
|
||||
* \return Whether the handle has been valid or not.
|
||||
*/
|
||||
extern int AUD_setKeep(AUD_Channel* handle, int keep);
|
||||
extern int AUD_setKeep(AUD_Handle* handle, int keep);
|
||||
|
||||
/**
|
||||
* Seeks a playing or paused sound.
|
||||
@ -215,7 +228,7 @@ extern int AUD_setKeep(AUD_Channel* 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_Channel* handle, float seekTo);
|
||||
extern int AUD_seek(AUD_Handle* handle, float seekTo);
|
||||
|
||||
/**
|
||||
* Retrieves the playback position of a handle.
|
||||
@ -223,14 +236,14 @@ extern int AUD_seek(AUD_Channel* handle, float seekTo);
|
||||
* \return The current playback position in seconds or 0.0 if the handle is
|
||||
* invalid.
|
||||
*/
|
||||
extern float AUD_getPosition(AUD_Channel* handle);
|
||||
extern float AUD_getPosition(AUD_Handle* 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_Channel* handle);
|
||||
extern AUD_Status AUD_getStatus(AUD_Handle* handle);
|
||||
|
||||
/**
|
||||
* Sets the listener location.
|
||||
@ -277,7 +290,7 @@ extern int AUD_setDistanceModel(AUD_DistanceModel model);
|
||||
* \param location The new location.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setSourceLocation(AUD_Channel* handle, const float* location);
|
||||
extern int AUD_setSourceLocation(AUD_Handle* handle, const float* location);
|
||||
|
||||
/**
|
||||
* Sets the velocity of a source.
|
||||
@ -285,7 +298,7 @@ extern int AUD_setSourceLocation(AUD_Channel* handle, const float* location);
|
||||
* \param velocity The new velocity.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity);
|
||||
extern int AUD_setSourceVelocity(AUD_Handle* handle, const float* velocity);
|
||||
|
||||
/**
|
||||
* Sets the orientation of a source.
|
||||
@ -293,7 +306,7 @@ extern int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity);
|
||||
* \param orientation The new orientation as quaternion.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation);
|
||||
extern int AUD_setSourceOrientation(AUD_Handle* handle, const float* orientation);
|
||||
|
||||
/**
|
||||
* Sets whether the source location, velocity and orientation are relative
|
||||
@ -302,7 +315,7 @@ extern int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientatio
|
||||
* \param relative Whether the source is relative.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setRelative(AUD_Channel* handle, int relative);
|
||||
extern int AUD_setRelative(AUD_Handle* handle, int relative);
|
||||
|
||||
/**
|
||||
* Sets the maximum volume of a source.
|
||||
@ -310,7 +323,7 @@ extern int AUD_setRelative(AUD_Channel* handle, int relative);
|
||||
* \param volume The new maximum volume.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setVolumeMaximum(AUD_Channel* handle, float volume);
|
||||
extern int AUD_setVolumeMaximum(AUD_Handle* handle, float volume);
|
||||
|
||||
/**
|
||||
* Sets the minimum volume of a source.
|
||||
@ -318,7 +331,7 @@ extern int AUD_setVolumeMaximum(AUD_Channel* handle, float volume);
|
||||
* \param volume The new minimum volume.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setVolumeMinimum(AUD_Channel* handle, float volume);
|
||||
extern int AUD_setVolumeMinimum(AUD_Handle* handle, float volume);
|
||||
|
||||
/**
|
||||
* Sets the maximum distance of a source.
|
||||
@ -328,7 +341,7 @@ extern int AUD_setVolumeMinimum(AUD_Channel* handle, float volume);
|
||||
* \param distance The new maximum distance.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setDistanceMaximum(AUD_Channel* handle, float distance);
|
||||
extern int AUD_setDistanceMaximum(AUD_Handle* handle, float distance);
|
||||
|
||||
/**
|
||||
* Sets the reference distance of a source.
|
||||
@ -336,7 +349,7 @@ extern int AUD_setDistanceMaximum(AUD_Channel* handle, float distance);
|
||||
* \param distance The new reference distance.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setDistanceReference(AUD_Channel* handle, float distance);
|
||||
extern int AUD_setDistanceReference(AUD_Handle* handle, float distance);
|
||||
|
||||
/**
|
||||
* Sets the attenuation of a source.
|
||||
@ -345,7 +358,7 @@ extern int AUD_setDistanceReference(AUD_Channel* handle, float distance);
|
||||
* \param factor The new attenuation.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setAttenuation(AUD_Channel* handle, float factor);
|
||||
extern int AUD_setAttenuation(AUD_Handle* handle, float factor);
|
||||
|
||||
/**
|
||||
* Sets the outer angle of the cone of a source.
|
||||
@ -353,7 +366,7 @@ extern int AUD_setAttenuation(AUD_Channel* handle, float factor);
|
||||
* \param angle The new outer angle of the cone.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setConeAngleOuter(AUD_Channel* handle, float angle);
|
||||
extern int AUD_setConeAngleOuter(AUD_Handle* handle, float angle);
|
||||
|
||||
/**
|
||||
* Sets the inner angle of the cone of a source.
|
||||
@ -361,7 +374,7 @@ extern int AUD_setConeAngleOuter(AUD_Channel* handle, float angle);
|
||||
* \param angle The new inner angle of the cone.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setConeAngleInner(AUD_Channel* handle, float angle);
|
||||
extern int AUD_setConeAngleInner(AUD_Handle* handle, float angle);
|
||||
|
||||
/**
|
||||
* Sets the outer volume of the cone of a source.
|
||||
@ -371,7 +384,7 @@ extern int AUD_setConeAngleInner(AUD_Channel* handle, float angle);
|
||||
* \param volume The new outer volume of the cone.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume);
|
||||
extern int AUD_setConeVolumeOuter(AUD_Handle* handle, float volume);
|
||||
|
||||
/**
|
||||
* Sets the volume of a played back sound.
|
||||
@ -379,7 +392,7 @@ extern int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume);
|
||||
* \param volume The new volume, must be between 0.0 and 1.0.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setSoundVolume(AUD_Channel* handle, float volume);
|
||||
extern int AUD_setSoundVolume(AUD_Handle* handle, float volume);
|
||||
|
||||
/**
|
||||
* Sets the pitch of a played back sound.
|
||||
@ -387,7 +400,7 @@ extern int AUD_setSoundVolume(AUD_Channel* handle, float volume);
|
||||
* \param pitch The new pitch.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setSoundPitch(AUD_Channel* handle, float pitch);
|
||||
extern int AUD_setSoundPitch(AUD_Handle* handle, float pitch);
|
||||
|
||||
/**
|
||||
* Opens a read device, with which audio data can be read.
|
||||
@ -411,18 +424,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_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek);
|
||||
|
||||
/**
|
||||
* Sets the volume of a played back sound of a read device.
|
||||
* \param device The read device.
|
||||
* \param handle The handle to the sound.
|
||||
* \param volume The new volume, must be between 0.0 and 1.0.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setDeviceSoundVolume(AUD_Device* device,
|
||||
AUD_Channel* handle,
|
||||
float volume);
|
||||
extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek);
|
||||
|
||||
/**
|
||||
* Reads the next samples into the supplied buffer.
|
||||
@ -448,7 +450,7 @@ extern void AUD_closeReadDevice(AUD_Device* device);
|
||||
extern float* AUD_readSoundBuffer(const char* filename, float low, float high,
|
||||
float attack, float release, float threshold,
|
||||
int accumulate, int additive, int square,
|
||||
float sthreshold, int samplerate,
|
||||
float sthreshold, double samplerate,
|
||||
int* length);
|
||||
|
||||
/**
|
||||
@ -457,43 +459,302 @@ extern float* AUD_readSoundBuffer(const char* filename, float low, float high,
|
||||
* \param time The time in seconds.
|
||||
* \return The silence handle.
|
||||
*/
|
||||
extern AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds);
|
||||
extern AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds);
|
||||
|
||||
extern AUD_Sound* AUD_createSequencer(int muted, void* data, AUD_volumeFunction volume);
|
||||
/**
|
||||
* Creates a new sequenced sound scene.
|
||||
* \param fps The FPS of the scene.
|
||||
* \param muted Whether the scene is muted.
|
||||
* \return The new sound scene.
|
||||
*/
|
||||
extern AUD_Sound* AUD_createSequencer(float fps, int muted);
|
||||
|
||||
/**
|
||||
* Deletes a sound scene.
|
||||
* \param sequencer The sound scene.
|
||||
*/
|
||||
extern void AUD_destroySequencer(AUD_Sound* sequencer);
|
||||
|
||||
/**
|
||||
* Sets the muting state of the scene.
|
||||
* \param sequencer The sound scene.
|
||||
* \param muted Whether the scene is muted.
|
||||
*/
|
||||
extern void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted);
|
||||
|
||||
extern AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound,
|
||||
float begin, float end, float skip, void* data);
|
||||
/**
|
||||
* Sets the scene's FPS.
|
||||
* \param sequencer The sound scene.
|
||||
* \param fps The new FPS.
|
||||
*/
|
||||
extern void AUD_setSequencerFPS(AUD_Sound* sequencer, float fps);
|
||||
|
||||
extern void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry);
|
||||
|
||||
extern void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
|
||||
/**
|
||||
* Adds a new entry to the scene.
|
||||
* \param sequencer The sound scene.
|
||||
* \param sound The sound this entry should play.
|
||||
* \param begin The start time.
|
||||
* \param end The end time or a negative value if determined by the sound.
|
||||
* \param skip How much seconds should be skipped at the beginning.
|
||||
* \return The entry added.
|
||||
*/
|
||||
extern AUD_SEntry* AUD_addSequence(AUD_Sound* sequencer, AUD_Sound* sound,
|
||||
float begin, float end, float skip);
|
||||
|
||||
extern void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry,
|
||||
char mute);
|
||||
/**
|
||||
* Removes an entry from the scene.
|
||||
* \param sequencer The sound scene.
|
||||
* \param entry The entry to remove.
|
||||
*/
|
||||
extern void AUD_removeSequence(AUD_Sound* sequencer, AUD_SEntry* entry);
|
||||
|
||||
extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length);
|
||||
/**
|
||||
* Moves the entry.
|
||||
* \param entry The sequenced entry.
|
||||
* \param begin The new start time.
|
||||
* \param end The new end time or a negative value if unknown.
|
||||
* \param skip How many seconds to skip at the beginning.
|
||||
*/
|
||||
extern void AUD_moveSequence(AUD_SEntry* entry, float begin, float end, float skip);
|
||||
|
||||
/**
|
||||
* Sets the muting state of the entry.
|
||||
* \param entry The sequenced entry.
|
||||
* \param mute Whether the entry should be muted or not.
|
||||
*/
|
||||
extern void AUD_muteSequence(AUD_SEntry* entry, char mute);
|
||||
|
||||
/**
|
||||
* Sets whether the entrie's location, velocity and orientation are relative
|
||||
* to the listener.
|
||||
* \param entry The sequenced entry.
|
||||
* \param relative Whether the source is relative.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern void AUD_setRelativeSequence(AUD_SEntry* entry, char relative);
|
||||
|
||||
/**
|
||||
* Sets the sound of the entry.
|
||||
* \param entry The sequenced entry.
|
||||
* \param sound The new sound.
|
||||
*/
|
||||
extern void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound);
|
||||
|
||||
/**
|
||||
* Writes animation data to a sequenced entry.
|
||||
* \param entry The sequenced entry.
|
||||
* \param type The type of animation data.
|
||||
* \param frame The frame this data is for.
|
||||
* \param data The data to write.
|
||||
* \param animated Whether the attribute is animated.
|
||||
*/
|
||||
extern void AUD_setSequenceAnimData(AUD_SEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated);
|
||||
|
||||
/**
|
||||
* Writes animation data to a sequenced entry.
|
||||
* \param sequencer The sound scene.
|
||||
* \param type The type of animation data.
|
||||
* \param frame The frame this data is for.
|
||||
* \param data The data to write.
|
||||
* \param animated Whether the attribute is animated.
|
||||
*/
|
||||
extern void AUD_setSequencerAnimData(AUD_Sound* sequencer, AUD_AnimateablePropertyType type, int frame, float* data, char animated);
|
||||
|
||||
/**
|
||||
* Updates all non-animated parameters of the entry.
|
||||
* \param entry The sequenced entry.
|
||||
* \param volume_max The maximum volume.
|
||||
* \param volume_min The minimum volume.
|
||||
* \param distance_max The maximum distance.
|
||||
* \param distance_reference The reference distance.
|
||||
* \param attenuation The attenuation.
|
||||
* \param cone_angle_outer The outer cone opening angle.
|
||||
* \param cone_angle_inner The inner cone opening angle.
|
||||
* \param cone_volume_outer The volume outside the outer cone.
|
||||
*/
|
||||
extern void AUD_updateSequenceData(AUD_SEntry* entry, float volume_max, float volume_min,
|
||||
float distance_max, float distance_reference, float attenuation,
|
||||
float cone_angle_outer, float cone_angle_inner, float cone_volume_outer);
|
||||
|
||||
/**
|
||||
* Updates all non-animated parameters of the entry.
|
||||
* \param sequencer The sound scene.
|
||||
* \param speed_of_sound The speed of sound for doppler calculation.
|
||||
* \param factor The doppler factor to control the effect's strength.
|
||||
* \param model The distance model for distance calculation.
|
||||
*/
|
||||
extern void AUD_updateSequencerData(AUD_Sound* sequencer, float speed_of_sound,
|
||||
float factor, AUD_DistanceModel model);
|
||||
|
||||
/**
|
||||
* Sets the audio output specification of the sound scene to the specs of the
|
||||
* current playback device.
|
||||
* \param sequencer The sound scene.
|
||||
*/
|
||||
extern void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer);
|
||||
|
||||
/**
|
||||
* Sets the audio output specification of the sound scene.
|
||||
* \param sequencer The sound scene.
|
||||
* \param specs The new specification.
|
||||
*/
|
||||
extern void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs);
|
||||
|
||||
/**
|
||||
* Seeks sequenced sound scene playback.
|
||||
* \param handle Playback handle.
|
||||
* \param time Time in seconds to seek to.
|
||||
*/
|
||||
extern void AUD_seekSequencer(AUD_Handle* handle, float time);
|
||||
|
||||
/**
|
||||
* Returns the current sound scene playback time.
|
||||
* \param handle Playback handle.
|
||||
* \return The playback time in seconds.
|
||||
*/
|
||||
extern float AUD_getSequencerPosition(AUD_Handle* handle);
|
||||
|
||||
/**
|
||||
* Starts the playback of jack transport if possible.
|
||||
*/
|
||||
extern void AUD_startPlayback(void);
|
||||
|
||||
/**
|
||||
* Stops the playback of jack transport if possible.
|
||||
*/
|
||||
extern void AUD_stopPlayback(void);
|
||||
|
||||
extern void AUD_seekSequencer(AUD_Channel* handle, float time);
|
||||
|
||||
extern float AUD_getSequencerPosition(AUD_Channel* handle);
|
||||
|
||||
#ifdef WITH_JACK
|
||||
/**
|
||||
* Sets the sync callback for jack transport.
|
||||
* \param function The callback function.
|
||||
* \param data The data parameter for the callback.
|
||||
*/
|
||||
extern void AUD_setSyncCallback(AUD_syncFunction function, void* data);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns whether jack transport is currently playing.
|
||||
* \return Whether jack transport is currently playing.
|
||||
*/
|
||||
extern int AUD_doesPlayback(void);
|
||||
|
||||
/**
|
||||
* Reads a sound into a buffer for drawing at a specific sampling rate.
|
||||
* \param sound The sound to read.
|
||||
* \param buffer The buffer to write to. Must have a size of 3*4*length.
|
||||
* \param length How many samples to read from the sound.
|
||||
* \param samples_per_second How many samples to read per second of the sound.
|
||||
* \return How many samples really have been read. Always <= length.
|
||||
*/
|
||||
extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length, int samples_per_second);
|
||||
|
||||
/**
|
||||
* Copies a sound.
|
||||
* \param sound Sound to copy.
|
||||
* \return Copied sound.
|
||||
*/
|
||||
extern AUD_Sound* AUD_copy(AUD_Sound* sound);
|
||||
|
||||
/**
|
||||
* Frees a handle.
|
||||
* \param channel Handle to free.
|
||||
*/
|
||||
extern void AUD_freeHandle(AUD_Handle* channel);
|
||||
|
||||
/**
|
||||
* Creates a new set.
|
||||
* \return The new set.
|
||||
*/
|
||||
extern void* AUD_createSet(void);
|
||||
|
||||
/**
|
||||
* Deletes a set.
|
||||
* \param set The set to delete.
|
||||
*/
|
||||
extern void AUD_destroySet(void* set);
|
||||
|
||||
/**
|
||||
* Removes an entry from a set.
|
||||
* \param set The set work on.
|
||||
* \param entry The entry to remove.
|
||||
* \return Whether the entry was in the set or not.
|
||||
*/
|
||||
extern char AUD_removeSet(void* set, void* entry);
|
||||
|
||||
/**
|
||||
* Adds a new entry to a set.
|
||||
* \param set The set work on.
|
||||
* \param entry The entry to add.
|
||||
*/
|
||||
extern void AUD_addSet(void* set, void* entry);
|
||||
|
||||
/**
|
||||
* Removes one entry from a set and returns it.
|
||||
* \param set The set work on.
|
||||
* \return The entry or NULL if the set is empty.
|
||||
*/
|
||||
extern void* AUD_getSet(void* set);
|
||||
|
||||
/**
|
||||
* Mixes a sound down into a file.
|
||||
* \param sound The sound scene to mix down.
|
||||
* \param start The start frame.
|
||||
* \param length The count of frames to write.
|
||||
* \param buffersize How many samples should be written at once.
|
||||
* \param filename The file to write to.
|
||||
* \param specs The file's audio specification.
|
||||
* \param format The file's container format.
|
||||
* \param codec The codec used for encoding the audio data.
|
||||
* \param bitrate The bitrate for encoding.
|
||||
* \return An error message or NULL in case of success.
|
||||
*/
|
||||
extern const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate);
|
||||
|
||||
/**
|
||||
* Opens a read device and prepares it for mixdown of the sound scene.
|
||||
* \param specs Output audio specifications.
|
||||
* \param sequencer The sound scene to mix down.
|
||||
* \param volume The overall mixdown volume.
|
||||
* \param start The start time of the mixdown in the sound scene.
|
||||
* \return The read device for the mixdown.
|
||||
*/
|
||||
extern AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, float start);
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
/**
|
||||
* Retrieves the python factory of a sound.
|
||||
* \param sound The sound factory.
|
||||
* \return The python factory.
|
||||
*/
|
||||
extern PyObject* AUD_getPythonFactory(AUD_Sound* sound);
|
||||
|
||||
/**
|
||||
* Retrieves the sound factory of a python factory.
|
||||
* \param sound The python factory.
|
||||
* \return The sound factory.
|
||||
*/
|
||||
extern AUD_Sound* AUD_getPythonSound(PyObject* sound);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#include "AUD_Reference.h"
|
||||
class AUD_IDevice;
|
||||
class AUD_I3DDevice;
|
||||
|
||||
/**
|
||||
* Returns the current playback device.
|
||||
* \return The playback device.
|
||||
*/
|
||||
AUD_Reference<AUD_IDevice> AUD_getDevice();
|
||||
|
||||
/**
|
||||
* Returns the current playback 3D device.
|
||||
* \return The playback 3D device.
|
||||
*/
|
||||
AUD_I3DDevice* AUD_get3DDevice();
|
||||
#endif
|
||||
|
||||
#endif //AUD_CAPI
|
||||
|
@ -34,79 +34,14 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IFactory* factory,
|
||||
AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_Reference<AUD_IFactory> factory,
|
||||
AUD_DeviceSpecs specs) :
|
||||
AUD_MixerFactory(factory, specs)
|
||||
{
|
||||
memset(m_mapping, 0, sizeof(m_mapping));
|
||||
}
|
||||
|
||||
AUD_ChannelMapperFactory::~AUD_ChannelMapperFactory()
|
||||
AUD_Reference<AUD_IReader> AUD_ChannelMapperFactory::createReader()
|
||||
{
|
||||
for(int i = 1; i < 10; i++)
|
||||
deleteMapping(i);
|
||||
}
|
||||
|
||||
float** AUD_ChannelMapperFactory::getMapping(int ic)
|
||||
{
|
||||
ic--;
|
||||
if(ic > 8 || ic < 0)
|
||||
return 0;
|
||||
|
||||
if(m_mapping[ic])
|
||||
{
|
||||
int channels = -1;
|
||||
while(m_mapping[ic][++channels] != 0);
|
||||
if(channels != m_specs.channels)
|
||||
deleteMapping(ic+1);
|
||||
}
|
||||
|
||||
if(!m_mapping[ic])
|
||||
{
|
||||
int channels = m_specs.channels;
|
||||
|
||||
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];
|
||||
for(int j = 0; j <= ic; j++)
|
||||
m_mapping[ic][i][j] = ((i == j) || (channels == 1) ||
|
||||
(ic == 0)) ? 1.0f : 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return m_mapping[ic];
|
||||
}
|
||||
|
||||
void AUD_ChannelMapperFactory::deleteMapping(int ic)
|
||||
{
|
||||
ic--;
|
||||
if(ic > 8 || ic < 0)
|
||||
return;
|
||||
|
||||
if(m_mapping[ic])
|
||||
{
|
||||
for(int i = 0; 1; i++)
|
||||
{
|
||||
if(m_mapping[ic][i] != 0)
|
||||
{
|
||||
delete[] m_mapping[ic][i];
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
delete[] m_mapping[ic];
|
||||
m_mapping[ic] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_ChannelMapperFactory::createReader() const
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
int ic = reader->getSpecs().channels;
|
||||
|
||||
return new AUD_ChannelMapperReader(reader,
|
||||
const_cast<AUD_ChannelMapperFactory*>(this)->getMapping(ic));
|
||||
AUD_Reference<AUD_IReader> reader = getReader();
|
||||
return new AUD_ChannelMapperReader(reader, m_specs.channels);
|
||||
}
|
||||
|
@ -41,33 +41,19 @@
|
||||
class AUD_ChannelMapperFactory : public AUD_MixerFactory
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The mapping specification.
|
||||
*/
|
||||
float **m_mapping[9];
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_ChannelMapperFactory(const AUD_ChannelMapperFactory&);
|
||||
AUD_ChannelMapperFactory& operator=(const AUD_ChannelMapperFactory&);
|
||||
|
||||
public:
|
||||
AUD_ChannelMapperFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
|
||||
|
||||
virtual ~AUD_ChannelMapperFactory();
|
||||
|
||||
/**
|
||||
* Returns the mapping array for editing.
|
||||
* \param ic The count of input channels the array should have.
|
||||
* \note The count of output channels is read of the desired output specs.
|
||||
* Creates a new factory.
|
||||
* \param factory The input factory.
|
||||
* \param specs The target specifications.
|
||||
*/
|
||||
float** getMapping(int ic);
|
||||
AUD_ChannelMapperFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs);
|
||||
|
||||
/**
|
||||
* Deletes the current channel mapping.
|
||||
*/
|
||||
void deleteMapping(int ic);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_CHANNELMAPPERFACTORY
|
||||
|
@ -28,74 +28,343 @@
|
||||
* \ingroup audaspaceintern
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#ifndef M_PI_2
|
||||
#define M_PI_2 1.57079632679489661923
|
||||
#endif
|
||||
|
||||
#include "AUD_ChannelMapperReader.h"
|
||||
|
||||
AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader,
|
||||
float **mapping) :
|
||||
AUD_EffectReader(reader)
|
||||
AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_Reference<AUD_IReader> reader,
|
||||
AUD_Channels channels) :
|
||||
AUD_EffectReader(reader), m_target_channels(channels),
|
||||
m_source_channels(AUD_CHANNELS_INVALID), m_mapping(0), m_map_size(0), m_mono_angle(0)
|
||||
{
|
||||
m_specs = reader->getSpecs();
|
||||
|
||||
int channels = -1;
|
||||
m_rch = m_specs.channels;
|
||||
while(mapping[++channels] != 0);
|
||||
|
||||
m_mapping = new float*[channels];
|
||||
m_specs.channels = (AUD_Channels)channels;
|
||||
|
||||
float sum;
|
||||
int i;
|
||||
|
||||
while(channels--)
|
||||
{
|
||||
m_mapping[channels] = new float[m_rch];
|
||||
sum = 0.0f;
|
||||
for(i=0; i < m_rch; i++)
|
||||
sum += mapping[channels][i];
|
||||
for(i=0; i < m_rch; i++)
|
||||
m_mapping[channels][i] = sum > 0.0f ?
|
||||
mapping[channels][i]/sum : 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
AUD_ChannelMapperReader::~AUD_ChannelMapperReader()
|
||||
{
|
||||
int channels = m_specs.channels;
|
||||
delete[] m_mapping;
|
||||
}
|
||||
|
||||
while(channels--)
|
||||
void AUD_ChannelMapperReader::setChannels(AUD_Channels channels)
|
||||
{
|
||||
m_target_channels = channels;
|
||||
calculateMapping();
|
||||
}
|
||||
|
||||
void AUD_ChannelMapperReader::setMonoAngle(float angle)
|
||||
{
|
||||
if(angle != angle)
|
||||
angle = 0;
|
||||
m_mono_angle = angle;
|
||||
if(m_source_channels == AUD_CHANNELS_MONO)
|
||||
calculateMapping();
|
||||
}
|
||||
|
||||
float AUD_ChannelMapperReader::angleDistance(float alpha, float beta)
|
||||
{
|
||||
alpha = fabs(alpha - beta);
|
||||
|
||||
if(alpha > M_PI)
|
||||
alpha = fabs(alpha - 2 * M_PI);
|
||||
|
||||
return alpha;
|
||||
}
|
||||
|
||||
void AUD_ChannelMapperReader::calculateMapping()
|
||||
{
|
||||
if(m_map_size < m_source_channels * m_target_channels)
|
||||
{
|
||||
delete[] m_mapping[channels];
|
||||
delete[] m_mapping;
|
||||
m_mapping = new float[m_source_channels * m_target_channels];
|
||||
m_map_size = m_source_channels * m_target_channels;
|
||||
}
|
||||
|
||||
delete[] m_mapping;
|
||||
for(int i = 0; i < m_source_channels * m_target_channels; i++)
|
||||
m_mapping[i] = 0;
|
||||
|
||||
const AUD_Channel* source_channels = CHANNEL_MAPS[m_source_channels - 1];
|
||||
const AUD_Channel* target_channels = CHANNEL_MAPS[m_target_channels - 1];
|
||||
|
||||
int lfe = -1;
|
||||
|
||||
for(int i = 0; i < m_target_channels; i++)
|
||||
{
|
||||
if(target_channels[i] == AUD_CHANNEL_LFE)
|
||||
{
|
||||
lfe = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const float* source_angles = CHANNEL_ANGLES[m_source_channels - 1];
|
||||
const float* target_angles = CHANNEL_ANGLES[m_target_channels - 1];
|
||||
|
||||
if(m_source_channels == AUD_CHANNELS_MONO)
|
||||
source_angles = &m_mono_angle;
|
||||
|
||||
int channel_min1, channel_min2;
|
||||
float angle_min1, angle_min2, angle;
|
||||
|
||||
for(int i = 0; i < m_source_channels; i++)
|
||||
{
|
||||
if(source_channels[i] == AUD_CHANNEL_LFE)
|
||||
{
|
||||
if(lfe != -1)
|
||||
m_mapping[lfe * m_source_channels + i] = 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
channel_min1 = channel_min2 = -1;
|
||||
angle_min1 = angle_min2 = 2 * M_PI;
|
||||
|
||||
for(int j = 0; j < m_target_channels; j++)
|
||||
{
|
||||
if(j == lfe)
|
||||
continue;
|
||||
angle = angleDistance(source_angles[i], target_angles[j]);
|
||||
if(angle < angle_min1)
|
||||
{
|
||||
channel_min2 = channel_min1;
|
||||
angle_min2 = angle_min1;
|
||||
|
||||
channel_min1 = j;
|
||||
angle_min1 = angle;
|
||||
}
|
||||
else if(angle < angle_min2)
|
||||
{
|
||||
channel_min2 = j;
|
||||
angle_min2 = angle;
|
||||
}
|
||||
}
|
||||
|
||||
angle = angle_min1 + angle_min2;
|
||||
if(channel_min2 == -1 || angle == 0)
|
||||
{
|
||||
m_mapping[channel_min1 * m_source_channels + i] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mapping[channel_min1 * m_source_channels + i] = cos(M_PI_2 * angle_min1 / angle);
|
||||
m_mapping[channel_min2 * m_source_channels + i] = cos(M_PI_2 * angle_min2 / angle);
|
||||
}
|
||||
}
|
||||
|
||||
/* AUD_XXX for(int i = 0; i < m_source_channels; i++)
|
||||
{
|
||||
for(int j = 0; j < m_target_channels; j++)
|
||||
{
|
||||
std::cout << m_mapping[i * m_source_channels + j] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}*/
|
||||
}
|
||||
|
||||
AUD_Specs AUD_ChannelMapperReader::getSpecs() const
|
||||
{
|
||||
return m_specs;
|
||||
AUD_Specs specs = m_reader->getSpecs();
|
||||
specs.channels = m_target_channels;
|
||||
return specs;
|
||||
}
|
||||
|
||||
void AUD_ChannelMapperReader::read(int & length, sample_t* & buffer)
|
||||
void AUD_ChannelMapperReader::read(int& length, bool& eos, sample_t* buffer)
|
||||
{
|
||||
sample_t* in = buffer;
|
||||
AUD_Channels channels = m_reader->getSpecs().channels;
|
||||
if(channels != m_source_channels)
|
||||
{
|
||||
m_source_channels = channels;
|
||||
calculateMapping();
|
||||
}
|
||||
|
||||
m_reader->read(length, in);
|
||||
if(m_source_channels == m_target_channels)
|
||||
{
|
||||
m_reader->read(length, eos, buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(m_specs))
|
||||
m_buffer.resize(length * AUD_SAMPLE_SIZE(m_specs));
|
||||
m_buffer.assureSize(length * channels * sizeof(sample_t));
|
||||
|
||||
sample_t* in = m_buffer.getBuffer();
|
||||
|
||||
m_reader->read(length, eos, in);
|
||||
|
||||
buffer = m_buffer.getBuffer();
|
||||
sample_t sum;
|
||||
|
||||
for(int i = 0; i < length; i++)
|
||||
{
|
||||
for(int j = 0; j < m_specs.channels; j++)
|
||||
for(int j = 0; j < m_target_channels; j++)
|
||||
{
|
||||
sum = 0;
|
||||
for(int k = 0; k < m_rch; k++)
|
||||
sum += m_mapping[j][k] * in[i * m_rch + k];
|
||||
buffer[i * m_specs.channels + j] = sum;
|
||||
for(int k = 0; k < m_source_channels; k++)
|
||||
sum += m_mapping[j * m_source_channels + k] * in[i * m_source_channels + k];
|
||||
buffer[i * m_target_channels + j] = sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const AUD_Channel AUD_ChannelMapperReader::MONO_MAP[] =
|
||||
{
|
||||
AUD_CHANNEL_FRONT_CENTER
|
||||
};
|
||||
|
||||
const AUD_Channel AUD_ChannelMapperReader::STEREO_MAP[] =
|
||||
{
|
||||
AUD_CHANNEL_FRONT_LEFT,
|
||||
AUD_CHANNEL_FRONT_RIGHT
|
||||
};
|
||||
|
||||
const AUD_Channel AUD_ChannelMapperReader::STEREO_LFE_MAP[] =
|
||||
{
|
||||
AUD_CHANNEL_FRONT_LEFT,
|
||||
AUD_CHANNEL_FRONT_RIGHT,
|
||||
AUD_CHANNEL_LFE
|
||||
};
|
||||
|
||||
const AUD_Channel AUD_ChannelMapperReader::SURROUND4_MAP[] =
|
||||
{
|
||||
AUD_CHANNEL_FRONT_LEFT,
|
||||
AUD_CHANNEL_FRONT_RIGHT,
|
||||
AUD_CHANNEL_REAR_LEFT,
|
||||
AUD_CHANNEL_REAR_RIGHT
|
||||
};
|
||||
|
||||
const AUD_Channel AUD_ChannelMapperReader::SURROUND5_MAP[] =
|
||||
{
|
||||
AUD_CHANNEL_FRONT_LEFT,
|
||||
AUD_CHANNEL_FRONT_RIGHT,
|
||||
AUD_CHANNEL_FRONT_CENTER,
|
||||
AUD_CHANNEL_REAR_LEFT,
|
||||
AUD_CHANNEL_REAR_RIGHT
|
||||
};
|
||||
|
||||
const AUD_Channel AUD_ChannelMapperReader::SURROUND51_MAP[] =
|
||||
{
|
||||
AUD_CHANNEL_FRONT_LEFT,
|
||||
AUD_CHANNEL_FRONT_RIGHT,
|
||||
AUD_CHANNEL_FRONT_CENTER,
|
||||
AUD_CHANNEL_LFE,
|
||||
AUD_CHANNEL_REAR_LEFT,
|
||||
AUD_CHANNEL_REAR_RIGHT
|
||||
};
|
||||
|
||||
const AUD_Channel AUD_ChannelMapperReader::SURROUND61_MAP[] =
|
||||
{
|
||||
AUD_CHANNEL_FRONT_LEFT,
|
||||
AUD_CHANNEL_FRONT_RIGHT,
|
||||
AUD_CHANNEL_FRONT_CENTER,
|
||||
AUD_CHANNEL_LFE,
|
||||
AUD_CHANNEL_REAR_CENTER,
|
||||
AUD_CHANNEL_REAR_LEFT,
|
||||
AUD_CHANNEL_REAR_RIGHT
|
||||
};
|
||||
|
||||
const AUD_Channel AUD_ChannelMapperReader::SURROUND71_MAP[] =
|
||||
{
|
||||
AUD_CHANNEL_FRONT_LEFT,
|
||||
AUD_CHANNEL_FRONT_RIGHT,
|
||||
AUD_CHANNEL_FRONT_CENTER,
|
||||
AUD_CHANNEL_LFE,
|
||||
AUD_CHANNEL_REAR_LEFT,
|
||||
AUD_CHANNEL_REAR_RIGHT,
|
||||
AUD_CHANNEL_SIDE_LEFT,
|
||||
AUD_CHANNEL_SIDE_RIGHT
|
||||
};
|
||||
|
||||
const AUD_Channel* AUD_ChannelMapperReader::CHANNEL_MAPS[] =
|
||||
{
|
||||
AUD_ChannelMapperReader::MONO_MAP,
|
||||
AUD_ChannelMapperReader::STEREO_MAP,
|
||||
AUD_ChannelMapperReader::STEREO_LFE_MAP,
|
||||
AUD_ChannelMapperReader::SURROUND4_MAP,
|
||||
AUD_ChannelMapperReader::SURROUND5_MAP,
|
||||
AUD_ChannelMapperReader::SURROUND51_MAP,
|
||||
AUD_ChannelMapperReader::SURROUND61_MAP,
|
||||
AUD_ChannelMapperReader::SURROUND71_MAP
|
||||
};
|
||||
|
||||
const float AUD_ChannelMapperReader::MONO_ANGLES[] =
|
||||
{
|
||||
0.0f * M_PI / 180.0f
|
||||
};
|
||||
|
||||
const float AUD_ChannelMapperReader::STEREO_ANGLES[] =
|
||||
{
|
||||
-90.0f * M_PI / 180.0f,
|
||||
90.0f * M_PI / 180.0f
|
||||
};
|
||||
|
||||
const float AUD_ChannelMapperReader::STEREO_LFE_ANGLES[] =
|
||||
{
|
||||
-90.0f * M_PI / 180.0f,
|
||||
90.0f * M_PI / 180.0f,
|
||||
0.0f * M_PI / 180.0f
|
||||
};
|
||||
|
||||
const float AUD_ChannelMapperReader::SURROUND4_ANGLES[] =
|
||||
{
|
||||
-45.0f * M_PI / 180.0f,
|
||||
45.0f * M_PI / 180.0f,
|
||||
-135.0f * M_PI / 180.0f,
|
||||
135.0f * M_PI / 180.0f
|
||||
};
|
||||
|
||||
const float AUD_ChannelMapperReader::SURROUND5_ANGLES[] =
|
||||
{
|
||||
-30.0f * M_PI / 180.0f,
|
||||
30.0f * M_PI / 180.0f,
|
||||
0.0f * M_PI / 180.0f,
|
||||
-110.0f * M_PI / 180.0f,
|
||||
110.0f * M_PI / 180.0f
|
||||
};
|
||||
|
||||
const float AUD_ChannelMapperReader::SURROUND51_ANGLES[] =
|
||||
{
|
||||
-30.0f * M_PI / 180.0f,
|
||||
30.0f * M_PI / 180.0f,
|
||||
0.0f * M_PI / 180.0f,
|
||||
0.0f * M_PI / 180.0f,
|
||||
-110.0f * M_PI / 180.0f,
|
||||
110.0f * M_PI / 180.0f
|
||||
};
|
||||
|
||||
const float AUD_ChannelMapperReader::SURROUND61_ANGLES[] =
|
||||
{
|
||||
-30.0f * M_PI / 180.0f,
|
||||
30.0f * M_PI / 180.0f,
|
||||
0.0f * M_PI / 180.0f,
|
||||
0.0f * M_PI / 180.0f,
|
||||
180.0f * M_PI / 180.0f,
|
||||
-110.0f * M_PI / 180.0f,
|
||||
110.0f * M_PI / 180.0f
|
||||
};
|
||||
|
||||
const float AUD_ChannelMapperReader::SURROUND71_ANGLES[] =
|
||||
{
|
||||
-30.0f * M_PI / 180.0f,
|
||||
30.0f * M_PI / 180.0f,
|
||||
0.0f * M_PI / 180.0f,
|
||||
0.0f * M_PI / 180.0f,
|
||||
-110.0f * M_PI / 180.0f,
|
||||
110.0f * M_PI / 180.0f
|
||||
-150.0f * M_PI / 180.0f,
|
||||
150.0f * M_PI / 180.0f
|
||||
};
|
||||
|
||||
const float* AUD_ChannelMapperReader::CHANNEL_ANGLES[] =
|
||||
{
|
||||
AUD_ChannelMapperReader::MONO_ANGLES,
|
||||
AUD_ChannelMapperReader::STEREO_ANGLES,
|
||||
AUD_ChannelMapperReader::STEREO_LFE_ANGLES,
|
||||
AUD_ChannelMapperReader::SURROUND4_ANGLES,
|
||||
AUD_ChannelMapperReader::SURROUND5_ANGLES,
|
||||
AUD_ChannelMapperReader::SURROUND51_ANGLES,
|
||||
AUD_ChannelMapperReader::SURROUND61_ANGLES,
|
||||
AUD_ChannelMapperReader::SURROUND71_ANGLES
|
||||
};
|
||||
|
@ -43,44 +43,96 @@ class AUD_ChannelMapperReader : public AUD_EffectReader
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The sound output buffer.
|
||||
* The sound reading buffer.
|
||||
*/
|
||||
AUD_Buffer m_buffer;
|
||||
|
||||
/**
|
||||
* The output specification.
|
||||
*/
|
||||
AUD_Specs m_specs;
|
||||
AUD_Channels m_target_channels;
|
||||
|
||||
/**
|
||||
* The channel count of the reader.
|
||||
*/
|
||||
int m_rch;
|
||||
AUD_Channels m_source_channels;
|
||||
|
||||
/**
|
||||
* The mapping specification.
|
||||
*/
|
||||
float **m_mapping;
|
||||
float* m_mapping;
|
||||
|
||||
/**
|
||||
* The size of the mapping.
|
||||
*/
|
||||
int m_map_size;
|
||||
|
||||
/**
|
||||
* The mono source angle.
|
||||
*/
|
||||
float m_mono_angle;
|
||||
|
||||
static const AUD_Channel MONO_MAP[];
|
||||
static const AUD_Channel STEREO_MAP[];
|
||||
static const AUD_Channel STEREO_LFE_MAP[];
|
||||
static const AUD_Channel SURROUND4_MAP[];
|
||||
static const AUD_Channel SURROUND5_MAP[];
|
||||
static const AUD_Channel SURROUND51_MAP[];
|
||||
static const AUD_Channel SURROUND61_MAP[];
|
||||
static const AUD_Channel SURROUND71_MAP[];
|
||||
static const AUD_Channel* CHANNEL_MAPS[];
|
||||
|
||||
static const float MONO_ANGLES[];
|
||||
static const float STEREO_ANGLES[];
|
||||
static const float STEREO_LFE_ANGLES[];
|
||||
static const float SURROUND4_ANGLES[];
|
||||
static const float SURROUND5_ANGLES[];
|
||||
static const float SURROUND51_ANGLES[];
|
||||
static const float SURROUND61_ANGLES[];
|
||||
static const float SURROUND71_ANGLES[];
|
||||
static const float* CHANNEL_ANGLES[];
|
||||
|
||||
// hide copy constructor and operator=
|
||||
AUD_ChannelMapperReader(const AUD_ChannelMapperReader&);
|
||||
AUD_ChannelMapperReader& operator=(const AUD_ChannelMapperReader&);
|
||||
|
||||
/**
|
||||
* Calculates the mapping matrix.
|
||||
*/
|
||||
void calculateMapping();
|
||||
|
||||
/**
|
||||
* Calculates the distance between two angles.
|
||||
*/
|
||||
float angleDistance(float alpha, float beta);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a channel mapper reader.
|
||||
* \param reader The reader to map.
|
||||
* \param mapping The mapping specification as two dimensional float array.
|
||||
*/
|
||||
AUD_ChannelMapperReader(AUD_IReader* reader, float **mapping);
|
||||
AUD_ChannelMapperReader(AUD_Reference<AUD_IReader> reader, AUD_Channels channels);
|
||||
|
||||
/**
|
||||
* Destroys the reader.
|
||||
*/
|
||||
~AUD_ChannelMapperReader();
|
||||
|
||||
/**
|
||||
* Sets the requested channel output count.
|
||||
* \param channels The channel output count.
|
||||
*/
|
||||
void setChannels(AUD_Channels channels);
|
||||
|
||||
/**
|
||||
* Sets the angle for mono sources.
|
||||
* \param angle The angle for mono sources.
|
||||
*/
|
||||
void setMonoAngle(float angle);
|
||||
|
||||
virtual AUD_Specs getSpecs() const;
|
||||
virtual void read(int & length, sample_t* & buffer);
|
||||
virtual void read(int& length, bool& eos, sample_t* buffer);
|
||||
};
|
||||
|
||||
#endif //AUD_CHANNELMAPPERREADER
|
||||
|
@ -32,15 +32,15 @@
|
||||
#include "AUD_ConverterFactory.h"
|
||||
#include "AUD_ConverterReader.h"
|
||||
|
||||
AUD_ConverterFactory::AUD_ConverterFactory(AUD_IFactory* factory,
|
||||
AUD_ConverterFactory::AUD_ConverterFactory(AUD_Reference<AUD_IFactory> factory,
|
||||
AUD_DeviceSpecs specs) :
|
||||
AUD_MixerFactory(factory, specs)
|
||||
{
|
||||
}
|
||||
|
||||
AUD_IReader* AUD_ConverterFactory::createReader() const
|
||||
AUD_Reference<AUD_IReader> AUD_ConverterFactory::createReader()
|
||||
{
|
||||
AUD_IReader* reader = getReader();
|
||||
AUD_Reference<AUD_IReader> reader = getReader();
|
||||
|
||||
if(m_specs.format != AUD_FORMAT_FLOAT32)
|
||||
reader = new AUD_ConverterReader(reader, m_specs);
|
||||
|
@ -46,9 +46,14 @@ private:
|
||||
AUD_ConverterFactory& operator=(const AUD_ConverterFactory&);
|
||||
|
||||
public:
|
||||
AUD_ConverterFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs);
|
||||
/**
|
||||
* Creates a new factory.
|
||||
* \param factory The input factory.
|
||||
* \param specs The target specifications.
|
||||
*/
|
||||
AUD_ConverterFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs);
|
||||
|
||||
virtual AUD_IReader* createReader() const;
|
||||
virtual AUD_Reference<AUD_IReader> createReader();
|
||||
};
|
||||
|
||||
#endif //AUD_CONVERTERFACTORY
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user