diff options
Diffstat (limited to 'intern/audaspace')
144 files changed, 4494 insertions, 3529 deletions
diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt index 7eef13b103b..603e98a5782 100644 --- a/intern/audaspace/CMakeLists.txt +++ b/intern/audaspace/CMakeLists.txt @@ -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 @@ -82,13 +84,13 @@ 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_I3DDevice.h + intern/AUD_I3DHandle.h intern/AUD_IDevice.h intern/AUD_IFactory.h + intern/AUD_IHandle.h intern/AUD_IReader.h intern/AUD_LinearResampleFactory.cpp intern/AUD_LinearResampleFactory.h @@ -104,7 +106,9 @@ 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_SequencerFactory.cpp intern/AUD_SequencerFactory.h intern/AUD_SequencerReader.cpp @@ -131,6 +135,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 diff --git a/intern/audaspace/FX/AUD_AccumulatorFactory.cpp b/intern/audaspace/FX/AUD_AccumulatorFactory.cpp index d60924958b1..0dffa7fc9ea 100644 --- a/intern/audaspace/FX/AUD_AccumulatorFactory.cpp +++ b/intern/audaspace/FX/AUD_AccumulatorFactory.cpp @@ -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); diff --git a/intern/audaspace/FX/AUD_AccumulatorFactory.h b/intern/audaspace/FX/AUD_AccumulatorFactory.h index 3c3b32ce071..5838ccee7f0 100644 --- a/intern/audaspace/FX/AUD_AccumulatorFactory.h +++ b/intern/audaspace/FX/AUD_AccumulatorFactory.h @@ -33,6 +33,7 @@ #define AUD_ACCUMULATORFACTORY #include "AUD_EffectFactory.h" +class AUD_CallbackIIRFilterReader; /** * This factory creates an accumulator reader. @@ -55,9 +56,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 diff --git a/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp b/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp index 563722d9213..29ff6d90080 100644 --- a/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_BaseIIRFilterReader.cpp @@ -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); + + 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); + } + } + + delete[] m_x; + m_x = xn; + m_xpos = 0; + m_xlen = in; + } + + if(out != m_ylen) + { + sample_t* yn = new sample_t[out * m_specs.channels]; + memset(yn, 0, sizeof(sample_t) * out * m_specs.channels); + + 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); + } + } + + 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; - int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs()); + m_x = new sample_t[m_xlen * m_specs.channels]; + m_y = new sample_t[m_ylen * m_specs.channels]; - m_reader->read(length, buf); + 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(m_buffer.getSize() < length * samplesize) - m_buffer.resize(length * samplesize); + if(specs.rate != m_specs.rate) + { + m_specs = specs; + sampleRateChanged(m_specs.rate); + } - buffer = m_buffer.getBuffer(); + m_reader->read(length, eos, buffer); - for(m_channel = 0; m_channel < m_channels; m_channel++) + 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) +{ +} diff --git a/intern/audaspace/FX/AUD_BaseIIRFilterReader.h b/intern/audaspace/FX/AUD_BaseIIRFilterReader.h index 436e6469a58..644bcffbfaf 100644 --- a/intern/audaspace/FX/AUD_BaseIIRFilterReader.h +++ b/intern/audaspace/FX/AUD_BaseIIRFilterReader.h @@ -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,27 @@ 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: 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]; } 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); virtual sample_t filter()=0; + virtual void sampleRateChanged(AUD_SampleRate rate); }; #endif //AUD_BASEIIRFILTERREADER diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.cpp b/intern/audaspace/FX/AUD_ButterworthFactory.cpp index ea957c81ed3..4b45512ffa6 100644 --- a/intern/audaspace/FX/AUD_ButterworthFactory.cpp +++ b/intern/audaspace/FX/AUD_ButterworthFactory.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_ButterworthFactory.h b/intern/audaspace/FX/AUD_ButterworthFactory.h index c8b731449c4..16d0b3dbc23 100644 --- a/intern/audaspace/FX/AUD_ButterworthFactory.h +++ b/intern/audaspace/FX/AUD_ButterworthFactory.h @@ -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. */ -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 diff --git a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp index 2f9bb7762a0..e6c83322435 100644 --- a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.cpp @@ -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, diff --git a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h index a969db7297e..6d53edeecc2 100644 --- a/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h +++ b/intern/audaspace/FX/AUD_CallbackIIRFilterReader.h @@ -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); diff --git a/intern/audaspace/FX/AUD_DelayFactory.cpp b/intern/audaspace/FX/AUD_DelayFactory.cpp index 1d2d99adc03..e452870281d 100644 --- a/intern/audaspace/FX/AUD_DelayFactory.cpp +++ b/intern/audaspace/FX/AUD_DelayFactory.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_DelayFactory.h b/intern/audaspace/FX/AUD_DelayFactory.h index 1e67cd68990..5ab7f850d2f 100644 --- a/intern/audaspace/FX/AUD_DelayFactory.h +++ b/intern/audaspace/FX/AUD_DelayFactory.h @@ -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 diff --git a/intern/audaspace/FX/AUD_DelayReader.cpp b/intern/audaspace/FX/AUD_DelayReader.cpp index 374b876455d..7d58b3dae4f 100644 --- a/intern/audaspace/FX/AUD_DelayReader.cpp +++ b/intern/audaspace/FX/AUD_DelayReader.cpp @@ -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); + memset(buffer, 0, m_remdelay * samplesize); int len = length - m_remdelay; - sample_t* buf; - m_reader->read(len, buf); - - memcpy(buffer + m_remdelay * specs.channels, - buf, len * samplesize); + m_reader->read(len, eos, buffer + m_remdelay * specs.channels); - if(len < length-m_remdelay) - length = m_remdelay + len; + length = m_remdelay + len; m_remdelay = 0; - m_empty = false; } else { - if(!m_empty) - { - memset(buffer, 0, length * samplesize); - m_empty = true; - } + memset(buffer, 0, length * samplesize); m_remdelay -= length; } } else - m_reader->read(length, buffer); + m_reader->read(length, eos, buffer); } diff --git a/intern/audaspace/FX/AUD_DelayReader.h b/intern/audaspace/FX/AUD_DelayReader.h index 5f0af660bdf..a89afe73b37 100644 --- a/intern/audaspace/FX/AUD_DelayReader.h +++ b/intern/audaspace/FX/AUD_DelayReader.h @@ -42,11 +42,6 @@ class AUD_DelayReader : public AUD_EffectReader { private: /** - * The playback buffer. - */ - AUD_Buffer m_buffer; - - /** * The delay level. */ const int m_delay; @@ -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 diff --git a/intern/audaspace/FX/AUD_DoubleFactory.cpp b/intern/audaspace/FX/AUD_DoubleFactory.cpp index 7a40f1f8c96..e1e6ba50435 100644 --- a/intern/audaspace/FX/AUD_DoubleFactory.cpp +++ b/intern/audaspace/FX/AUD_DoubleFactory.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_DoubleFactory.h b/intern/audaspace/FX/AUD_DoubleFactory.h index 52a299c7157..f2be7132442 100644 --- a/intern/audaspace/FX/AUD_DoubleFactory.h +++ b/intern/audaspace/FX/AUD_DoubleFactory.h @@ -44,12 +44,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 +61,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 diff --git a/intern/audaspace/FX/AUD_DoubleReader.cpp b/intern/audaspace/FX/AUD_DoubleReader.cpp index 113bed14ce3..96352b0963c 100644 --- a/intern/audaspace/FX/AUD_DoubleReader.cpp +++ b/intern/audaspace/FX/AUD_DoubleReader.cpp @@ -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,19 @@ 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); - - 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; - } + m_reader1->read(length, m_finished1, buffer); } else { - m_reader2->read(length, buffer); + m_reader2->read(length, eos, buffer); } } diff --git a/intern/audaspace/FX/AUD_DoubleReader.h b/intern/audaspace/FX/AUD_DoubleReader.h index 7b3b812ef80..86f636e2cb2 100644 --- a/intern/audaspace/FX/AUD_DoubleReader.h +++ b/intern/audaspace/FX/AUD_DoubleReader.h @@ -34,6 +34,7 @@ #include "AUD_IReader.h" #include "AUD_Buffer.h" +#include "AUD_Reference.h" /** * This reader plays two readers with the same specs sequently. @@ -44,12 +45,12 @@ 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. @@ -72,7 +73,7 @@ public: * \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 +85,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 diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp new file mode 100644 index 00000000000..3018a2df571 --- /dev/null +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.cpp @@ -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); +} diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h new file mode 100644 index 00000000000..19c1a0f0a54 --- /dev/null +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterFactory.h @@ -0,0 +1,49 @@ +/* + * $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> + +class AUD_DynamicIIRFilterFactory : public AUD_EffectFactory +{ +public: + AUD_DynamicIIRFilterFactory(AUD_Reference<AUD_IFactory> factory); + + virtual AUD_Reference<AUD_IReader> createReader(); + + virtual void recalculateCoefficients(AUD_SampleRate rate, + std::vector<float>& b, + std::vector<float>& a)=0; +}; + +#endif // AUD_DYNAMICIIRFILTERFACTORY diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp new file mode 100644 index 00000000000..ed9b2d3871d --- /dev/null +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.cpp @@ -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); +} diff --git a/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h new file mode 100644 index 00000000000..92f491f04d4 --- /dev/null +++ b/intern/audaspace/FX/AUD_DynamicIIRFilterReader.h @@ -0,0 +1,52 @@ +/* + * $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" + +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 diff --git a/intern/audaspace/FX/AUD_EffectFactory.cpp b/intern/audaspace/FX/AUD_EffectFactory.cpp index a0d9256e691..6173ffb5a97 100644 --- a/intern/audaspace/FX/AUD_EffectFactory.cpp +++ b/intern/audaspace/FX/AUD_EffectFactory.cpp @@ -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; } diff --git a/intern/audaspace/FX/AUD_EffectFactory.h b/intern/audaspace/FX/AUD_EffectFactory.h index a6a28eea577..72fdb3f0833 100644 --- a/intern/audaspace/FX/AUD_EffectFactory.h +++ b/intern/audaspace/FX/AUD_EffectFactory.h @@ -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 diff --git a/intern/audaspace/FX/AUD_EffectReader.cpp b/intern/audaspace/FX/AUD_EffectReader.cpp index 3ad9f67bfd6..4d14af76438 100644 --- a/intern/audaspace/FX/AUD_EffectReader.cpp +++ b/intern/audaspace/FX/AUD_EffectReader.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_EffectReader.h b/intern/audaspace/FX/AUD_EffectReader.h index fb8066f36d8..c03abd11828 100644 --- a/intern/audaspace/FX/AUD_EffectReader.h +++ b/intern/audaspace/FX/AUD_EffectReader.h @@ -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 diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.cpp b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp index 069317d1c8b..80df7e9f874 100644 --- a/intern/audaspace/FX/AUD_EnvelopeFactory.cpp +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.cpp @@ -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, diff --git a/intern/audaspace/FX/AUD_EnvelopeFactory.h b/intern/audaspace/FX/AUD_EnvelopeFactory.h index 45ee811b6e0..a480a05d478 100644 --- a/intern/audaspace/FX/AUD_EnvelopeFactory.h +++ b/intern/audaspace/FX/AUD_EnvelopeFactory.h @@ -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 diff --git a/intern/audaspace/FX/AUD_FaderFactory.cpp b/intern/audaspace/FX/AUD_FaderFactory.cpp index d887e9e68d9..635873e0ee5 100644 --- a/intern/audaspace/FX/AUD_FaderFactory.cpp +++ b/intern/audaspace/FX/AUD_FaderFactory.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_FaderFactory.h b/intern/audaspace/FX/AUD_FaderFactory.h index b85475bc534..d8314c77ed4 100644 --- a/intern/audaspace/FX/AUD_FaderFactory.h +++ b/intern/audaspace/FX/AUD_FaderFactory.h @@ -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 diff --git a/intern/audaspace/FX/AUD_FaderReader.cpp b/intern/audaspace/FX/AUD_FaderReader.cpp index 6114bb486fc..4a6050cf0f3 100644 --- a/intern/audaspace/FX/AUD_FaderReader.cpp +++ b/intern/audaspace/FX/AUD_FaderReader.cpp @@ -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; - } + memset(buffer, 0, length * samplesize); } } 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; - } + memset(buffer, 0, length * samplesize); } } 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; } } diff --git a/intern/audaspace/FX/AUD_FaderReader.h b/intern/audaspace/FX/AUD_FaderReader.h index fb927192b45..e702ac0ec19 100644 --- a/intern/audaspace/FX/AUD_FaderReader.h +++ b/intern/audaspace/FX/AUD_FaderReader.h @@ -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 diff --git a/intern/audaspace/FX/AUD_HighpassFactory.cpp b/intern/audaspace/FX/AUD_HighpassFactory.cpp index 61008eea44e..399ec5ca406 100644 --- a/intern/audaspace/FX/AUD_HighpassFactory.cpp +++ b/intern/audaspace/FX/AUD_HighpassFactory.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_HighpassFactory.h b/intern/audaspace/FX/AUD_HighpassFactory.h index 48f4c1baefc..51d5f55cb36 100644 --- a/intern/audaspace/FX/AUD_HighpassFactory.h +++ b/intern/audaspace/FX/AUD_HighpassFactory.h @@ -32,12 +32,12 @@ #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: /** @@ -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 diff --git a/intern/audaspace/FX/AUD_IIRFilterFactory.cpp b/intern/audaspace/FX/AUD_IIRFilterFactory.cpp index ff90ce62739..f6ccda6f67e 100644 --- a/intern/audaspace/FX/AUD_IIRFilterFactory.cpp +++ b/intern/audaspace/FX/AUD_IIRFilterFactory.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_IIRFilterFactory.h b/intern/audaspace/FX/AUD_IIRFilterFactory.h index d48ad453ee4..0e92ab1a568 100644 --- a/intern/audaspace/FX/AUD_IIRFilterFactory.h +++ b/intern/audaspace/FX/AUD_IIRFilterFactory.h @@ -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 diff --git a/intern/audaspace/FX/AUD_IIRFilterReader.cpp b/intern/audaspace/FX/AUD_IIRFilterReader.cpp index 0d55421d2b4..1bfb9b97b62 100644 --- a/intern/audaspace/FX/AUD_IIRFilterReader.cpp +++ b/intern/audaspace/FX/AUD_IIRFilterReader.cpp @@ -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; +} diff --git a/intern/audaspace/FX/AUD_IIRFilterReader.h b/intern/audaspace/FX/AUD_IIRFilterReader.h index af50b6f1cdc..41de67d4d27 100644 --- a/intern/audaspace/FX/AUD_IIRFilterReader.h +++ b/intern/audaspace/FX/AUD_IIRFilterReader.h @@ -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 diff --git a/intern/audaspace/FX/AUD_LimiterFactory.cpp b/intern/audaspace/FX/AUD_LimiterFactory.cpp index 62ea01bb761..8d1dd14f3ae 100644 --- a/intern/audaspace/FX/AUD_LimiterFactory.cpp +++ b/intern/audaspace/FX/AUD_LimiterFactory.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_LimiterFactory.h b/intern/audaspace/FX/AUD_LimiterFactory.h index f93f4b3276c..c04bfe861b2 100644 --- a/intern/audaspace/FX/AUD_LimiterFactory.h +++ b/intern/audaspace/FX/AUD_LimiterFactory.h @@ -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 diff --git a/intern/audaspace/FX/AUD_LimiterReader.cpp b/intern/audaspace/FX/AUD_LimiterReader.cpp index d67fbb4d0e5..dc31477d2eb 100644 --- a/intern/audaspace/FX/AUD_LimiterReader.cpp +++ b/intern/audaspace/FX/AUD_LimiterReader.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_LimiterReader.h b/intern/audaspace/FX/AUD_LimiterReader.h index 4375ed9e10d..d9bee6f6463 100644 --- a/intern/audaspace/FX/AUD_LimiterReader.h +++ b/intern/audaspace/FX/AUD_LimiterReader.h @@ -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&); @@ -62,12 +62,12 @@ public: * \param end The desired end 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 diff --git a/intern/audaspace/FX/AUD_LoopFactory.cpp b/intern/audaspace/FX/AUD_LoopFactory.cpp index 49d3481757f..fd39ac901c1 100644 --- a/intern/audaspace/FX/AUD_LoopFactory.cpp +++ b/intern/audaspace/FX/AUD_LoopFactory.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_LoopFactory.h b/intern/audaspace/FX/AUD_LoopFactory.h index dfbbbe4fd20..03c00dc40ce 100644 --- a/intern/audaspace/FX/AUD_LoopFactory.h +++ b/intern/audaspace/FX/AUD_LoopFactory.h @@ -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 diff --git a/intern/audaspace/FX/AUD_LoopReader.cpp b/intern/audaspace/FX/AUD_LoopReader.cpp index b2e8e97a602..de67a445ab2 100644 --- a/intern/audaspace/FX/AUD_LoopReader.cpp +++ b/intern/audaspace/FX/AUD_LoopReader.cpp @@ -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; - - 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; + int pos = length; + length = 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; } diff --git a/intern/audaspace/FX/AUD_LoopReader.h b/intern/audaspace/FX/AUD_LoopReader.h index 45017901c56..5ccf7e543a0 100644 --- a/intern/audaspace/FX/AUD_LoopReader.h +++ b/intern/audaspace/FX/AUD_LoopReader.h @@ -43,11 +43,6 @@ class AUD_LoopReader : public AUD_EffectReader { private: /** - * The playback buffer. - */ - AUD_Buffer m_buffer; - - /** * The loop count. */ const int m_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 diff --git a/intern/audaspace/FX/AUD_LowpassFactory.cpp b/intern/audaspace/FX/AUD_LowpassFactory.cpp index d24a04b5a94..3ef25c3c16e 100644 --- a/intern/audaspace/FX/AUD_LowpassFactory.cpp +++ b/intern/audaspace/FX/AUD_LowpassFactory.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_LowpassFactory.h b/intern/audaspace/FX/AUD_LowpassFactory.h index d60c0bd22d1..6558663df4e 100644 --- a/intern/audaspace/FX/AUD_LowpassFactory.h +++ b/intern/audaspace/FX/AUD_LowpassFactory.h @@ -32,12 +32,12 @@ #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: /** @@ -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 diff --git a/intern/audaspace/FX/AUD_PingPongFactory.cpp b/intern/audaspace/FX/AUD_PingPongFactory.cpp index fa140555943..e5f2193ea56 100644 --- a/intern/audaspace/FX/AUD_PingPongFactory.cpp +++ b/intern/audaspace/FX/AUD_PingPongFactory.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_PingPongFactory.h b/intern/audaspace/FX/AUD_PingPongFactory.h index 4ae0c494eb7..908591a6ebe 100644 --- a/intern/audaspace/FX/AUD_PingPongFactory.h +++ b/intern/audaspace/FX/AUD_PingPongFactory.h @@ -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 diff --git a/intern/audaspace/FX/AUD_PitchFactory.cpp b/intern/audaspace/FX/AUD_PitchFactory.cpp index b4ae8582caf..e52028754e9 100644 --- a/intern/audaspace/FX/AUD_PitchFactory.cpp +++ b/intern/audaspace/FX/AUD_PitchFactory.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_PitchFactory.h b/intern/audaspace/FX/AUD_PitchFactory.h index 8fa5be9293f..2642d41af89 100644 --- a/intern/audaspace/FX/AUD_PitchFactory.h +++ b/intern/audaspace/FX/AUD_PitchFactory.h @@ -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 diff --git a/intern/audaspace/FX/AUD_PitchReader.cpp b/intern/audaspace/FX/AUD_PitchReader.cpp index e2e89e2c457..81dd6e4355c 100644 --- a/intern/audaspace/FX/AUD_PitchReader.cpp +++ b/intern/audaspace/FX/AUD_PitchReader.cpp @@ -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; +} diff --git a/intern/audaspace/FX/AUD_PitchReader.h b/intern/audaspace/FX/AUD_PitchReader.h index 120cebc58be..7418531ca55 100644 --- a/intern/audaspace/FX/AUD_PitchReader.h +++ b/intern/audaspace/FX/AUD_PitchReader.h @@ -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&); @@ -55,9 +55,12 @@ public: * \param reader The reader to read from. * \param pitch The size of the buffer. */ - AUD_PitchReader(AUD_IReader* reader, float pitch); + AUD_PitchReader(AUD_Reference<AUD_IReader> reader, float pitch); virtual AUD_Specs getSpecs() const; + + float getPitch() const; + void setPitch(float pitch); }; #endif //AUD_PITCHREADER diff --git a/intern/audaspace/FX/AUD_RectifyFactory.cpp b/intern/audaspace/FX/AUD_RectifyFactory.cpp index 609d827cce4..cbb676a9a32 100644 --- a/intern/audaspace/FX/AUD_RectifyFactory.cpp +++ b/intern/audaspace/FX/AUD_RectifyFactory.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_RectifyFactory.h b/intern/audaspace/FX/AUD_RectifyFactory.h index c3529c7beef..16b44469c05 100644 --- a/intern/audaspace/FX/AUD_RectifyFactory.h +++ b/intern/audaspace/FX/AUD_RectifyFactory.h @@ -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 diff --git a/intern/audaspace/FX/AUD_ReverseFactory.cpp b/intern/audaspace/FX/AUD_ReverseFactory.cpp index 22b12e31420..060a618dd68 100644 --- a/intern/audaspace/FX/AUD_ReverseFactory.cpp +++ b/intern/audaspace/FX/AUD_ReverseFactory.cpp @@ -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()); } diff --git a/intern/audaspace/FX/AUD_ReverseFactory.h b/intern/audaspace/FX/AUD_ReverseFactory.h index 7b20546302e..b501b4e76c8 100644 --- a/intern/audaspace/FX/AUD_ReverseFactory.h +++ b/intern/audaspace/FX/AUD_ReverseFactory.h @@ -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 diff --git a/intern/audaspace/FX/AUD_ReverseReader.cpp b/intern/audaspace/FX/AUD_ReverseReader.cpp index a4a03936c76..73f6830f3fa 100644 --- a/intern/audaspace/FX/AUD_ReverseReader.cpp +++ b/intern/audaspace/FX/AUD_ReverseReader.cpp @@ -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++) + 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, - buf + (len - 1 - i) * specs.channels, + temp, samplesize); + } m_position += length; - - buffer = m_buffer.getBuffer(); + eos = false; } diff --git a/intern/audaspace/FX/AUD_ReverseReader.h b/intern/audaspace/FX/AUD_ReverseReader.h index e12f2b21191..da0add9464e 100644 --- a/intern/audaspace/FX/AUD_ReverseReader.h +++ b/intern/audaspace/FX/AUD_ReverseReader.h @@ -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 diff --git a/intern/audaspace/FX/AUD_SquareFactory.cpp b/intern/audaspace/FX/AUD_SquareFactory.cpp index a075773d2cb..226085a1814 100644 --- a/intern/audaspace/FX/AUD_SquareFactory.cpp +++ b/intern/audaspace/FX/AUD_SquareFactory.cpp @@ -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, diff --git a/intern/audaspace/FX/AUD_SquareFactory.h b/intern/audaspace/FX/AUD_SquareFactory.h index 8060e98e281..21284361cca 100644 --- a/intern/audaspace/FX/AUD_SquareFactory.h +++ b/intern/audaspace/FX/AUD_SquareFactory.h @@ -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 diff --git a/intern/audaspace/FX/AUD_SumFactory.cpp b/intern/audaspace/FX/AUD_SumFactory.cpp index 6d8368d6e35..befcc30360f 100644 --- a/intern/audaspace/FX/AUD_SumFactory.cpp +++ b/intern/audaspace/FX/AUD_SumFactory.cpp @@ -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); diff --git a/intern/audaspace/FX/AUD_SumFactory.h b/intern/audaspace/FX/AUD_SumFactory.h index ed19a0f258a..cdb4caf6e49 100644 --- a/intern/audaspace/FX/AUD_SumFactory.h +++ b/intern/audaspace/FX/AUD_SumFactory.h @@ -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 diff --git a/intern/audaspace/FX/AUD_SuperposeFactory.cpp b/intern/audaspace/FX/AUD_SuperposeFactory.cpp index c13a0d0dd95..d514bfd8fca 100644 --- a/intern/audaspace/FX/AUD_SuperposeFactory.cpp +++ b/intern/audaspace/FX/AUD_SuperposeFactory.cpp @@ -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); } diff --git a/intern/audaspace/FX/AUD_SuperposeFactory.h b/intern/audaspace/FX/AUD_SuperposeFactory.h index 32232012e4e..ac7ec080134 100644 --- a/intern/audaspace/FX/AUD_SuperposeFactory.h +++ b/intern/audaspace/FX/AUD_SuperposeFactory.h @@ -44,12 +44,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 +61,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 diff --git a/intern/audaspace/FX/AUD_SuperposeReader.cpp b/intern/audaspace/FX/AUD_SuperposeReader.cpp index e64cf79188e..a0dc12fea96 100644 --- a/intern/audaspace/FX/AUD_SuperposeReader.cpp +++ b/intern/audaspace/FX/AUD_SuperposeReader.cpp @@ -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(memcmp(&specs, &s2, sizeof(AUD_Specs))) + 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; } diff --git a/intern/audaspace/FX/AUD_SuperposeReader.h b/intern/audaspace/FX/AUD_SuperposeReader.h index b256aade7ba..a87f1fdb739 100644 --- a/intern/audaspace/FX/AUD_SuperposeReader.h +++ b/intern/audaspace/FX/AUD_SuperposeReader.h @@ -34,6 +34,7 @@ #include "AUD_IReader.h" #include "AUD_Buffer.h" +#include "AUD_Reference.h" /** * This reader plays two readers with the same specs sequently. @@ -44,12 +45,12 @@ 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. @@ -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 diff --git a/intern/audaspace/FX/AUD_VolumeFactory.cpp b/intern/audaspace/FX/AUD_VolumeFactory.cpp index 166fbf61512..17cefd4f3c3 100644 --- a/intern/audaspace/FX/AUD_VolumeFactory.cpp +++ b/intern/audaspace/FX/AUD_VolumeFactory.cpp @@ -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); diff --git a/intern/audaspace/FX/AUD_VolumeFactory.h b/intern/audaspace/FX/AUD_VolumeFactory.h index fa40ca11082..bcc08e7d04a 100644 --- a/intern/audaspace/FX/AUD_VolumeFactory.h +++ b/intern/audaspace/FX/AUD_VolumeFactory.h @@ -57,14 +57,14 @@ 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. */ float getVolume() const; - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader(); }; #endif //AUD_VOLUMEFACTORY diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp index b9e30bbf62a..65b1d3f3b64 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp @@ -43,56 +43,726 @@ #include <unistd.h> #endif -#define AUD_OPENAL_CYCLE_BUFFERS 3 +/*struct AUD_OpenALBufferedFactory +{ + /// The factory. + AUD_IFactory* factory; + + /// The OpenAL buffer. + ALuint buffer; +};*/ + +//typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator; + + +/******************************************************************************/ +/*********************** AUD_OpenALHandle Handle Code *************************/ +/******************************************************************************/ + +static const char* genbuffer_error = "AUD_OpenALDevice: Buffer couldn't be " + "generated."; +static const char* gensource_error = "AUD_OpenALDevice: Source couldn't be " + "generated."; +static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be " + "queued to the source."; +static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be " + "filled with data."; -/// Saves the data for playback. -struct AUD_OpenALHandle : AUD_Handle +AUD_OpenALDevice::AUD_OpenALHandle::AUD_OpenALHandle(AUD_OpenALDevice* device, ALenum format, AUD_Reference<AUD_IReader> reader, bool keep) : + m_isBuffered(false), m_reader(reader), m_keep(keep), m_format(format), m_current(0), + m_eos(false), m_loopcount(0), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), + m_device(device) { - /// Whether it's a buffered or a streamed source. - bool isBuffered; + AUD_DeviceSpecs specs = m_device->m_specs; + specs.specs = m_reader->getSpecs(); - /// The reader source. - AUD_IReader* reader; + // OpenAL playback code + alGenBuffers(CYCLE_BUFFERS, m_buffers); + if(alGetError() != AL_NO_ERROR) + AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error); - /// Whether to keep the source if end of it is reached. - bool keep; + try + { + m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs)); + int length; + bool eos; - /// OpenAL sample format. - ALenum format; + for(int i = 0; i < CYCLE_BUFFERS; i++) + { + length = m_device->m_buffersize; + reader->read(length, eos, m_device->m_buffer.getBuffer()); + alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(), + length * AUD_DEVICE_SAMPLE_SIZE(specs), + specs.rate); + if(alGetError() != AL_NO_ERROR) + AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error); + } - /// OpenAL source. - ALuint source; + alGenSources(1, &m_source); + if(alGetError() != AL_NO_ERROR) + AUD_THROW(AUD_ERROR_OPENAL, gensource_error); - /// OpenAL buffers. - ALuint buffers[AUD_OPENAL_CYCLE_BUFFERS]; + try + { + alSourceQueueBuffers(m_source, CYCLE_BUFFERS, + m_buffers); + if(alGetError() != AL_NO_ERROR) + AUD_THROW(AUD_ERROR_OPENAL, queue_error); + } + catch(AUD_Exception&) + { + alDeleteSources(1, &m_source); + throw; + } + } + catch(AUD_Exception&) + { + alDeleteBuffers(CYCLE_BUFFERS, m_buffers); + throw; + } + alSourcei(m_source, AL_SOURCE_RELATIVE, 1); +} - /// The first buffer to be read next. - int current; +bool AUD_OpenALDevice::AUD_OpenALHandle::pause() +{ + if(m_status) + { + m_device->lock(); - /// Whether the stream doesn't return any more data. - bool data_end; + if(m_status == AUD_STATUS_PLAYING) + { + m_device->m_playingSounds.remove(this); + m_device->m_pausedSounds.push_back(this); - /// The loop count of the source. - int loopcount; + alSourcePause(m_source); - /// The stop callback. - stopCallback stop; + m_status = AUD_STATUS_PAUSED; + m_device->unlock(); - /// Stop callback data. - void* stop_data; -}; + return true; + } + + m_device->unlock(); + } -struct AUD_OpenALBufferedFactory + return false; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::resume() { - /// The factory. - AUD_IFactory* factory; + if(m_status) + { + m_device->lock(); - /// The OpenAL buffer. - ALuint buffer; -}; + if(m_status == AUD_STATUS_PAUSED) + { + m_device->m_pausedSounds.remove(this); + m_device->m_playingSounds.push_back(this); + + m_device->start(); + m_status = AUD_STATUS_PLAYING; + m_device->unlock(); + return true; + } + + m_device->unlock(); + } + + return false; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::stop() +{ + if(!m_status) + return false; + + m_device->lock(); + + // AUD_XXX Create a reference of our own object so that it doesn't get + // deleted before the end of this function + AUD_Reference<AUD_OpenALHandle> This = this; + + if(m_status == AUD_STATUS_PLAYING) + m_device->m_playingSounds.remove(This); + else + m_device->m_pausedSounds.remove(This); + + m_device->unlock(); + + alDeleteSources(1, &m_source); + if(!m_isBuffered) + alDeleteBuffers(CYCLE_BUFFERS, m_buffers); + + m_status = AUD_STATUS_INVALID; + return true; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::getKeep() +{ + if(m_status) + return m_keep; + + return false; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setKeep(bool keep) +{ + if(!m_status) + return false; + + m_device->lock(); + + m_keep = keep; + + m_device->unlock(); + + return true; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::seek(float position) +{ + if(!m_status) + return false; + + m_device->lock(); + + if(m_isBuffered) + alSourcef(m_source, AL_SEC_OFFSET, position); + else + { + m_reader->seek((int)(position * m_reader->getSpecs().rate)); + m_eos = false; + + ALint info; + + alGetSourcei(m_source, AL_SOURCE_STATE, &info); + + if(info != AL_PLAYING) + { + if(info == AL_PAUSED) + alSourceStop(m_source); + + alSourcei(m_source, AL_BUFFER, 0); + m_current = 0; + + ALenum err; + if((err = alGetError()) == AL_NO_ERROR) + { + int length; + AUD_DeviceSpecs specs = m_device->m_specs; + specs.specs = m_reader->getSpecs(); + m_device->m_buffer.assureSize(m_device->m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs)); + + for(int i = 0; i < CYCLE_BUFFERS; i++) + { + length = m_device->m_buffersize; + m_reader->read(length, m_eos, m_device->m_buffer.getBuffer()); + alBufferData(m_buffers[i], m_format, m_device->m_buffer.getBuffer(), + length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); + + if(alGetError() != AL_NO_ERROR) + break; + } + + if(m_loopcount != 0) + m_eos = false; + + alSourceQueueBuffers(m_source, CYCLE_BUFFERS, m_buffers); + } + + alSourceRewind(m_source); + } + } + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getPosition() +{ + if(!m_status) + return 0.0f; + + m_device->lock(); + + float position = 0.0f; + + alGetSourcef(m_source, AL_SEC_OFFSET, &position); + + if(!m_isBuffered) + { + AUD_Specs specs = m_reader->getSpecs(); + position += (m_reader->getPosition() - m_device->m_buffersize * + CYCLE_BUFFERS) / (float)specs.rate; + } + + m_device->unlock(); + + return position; +} + +AUD_Status AUD_OpenALDevice::AUD_OpenALHandle::getStatus() +{ + return m_status; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getVolume() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_GAIN, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setVolume(float volume) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_GAIN, volume); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getPitch() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_PITCH, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setPitch(float pitch) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_PITCH, pitch); + + m_device->unlock(); + + return true; +} + +int AUD_OpenALDevice::AUD_OpenALHandle::getLoopCount() +{ + if(!m_status) + return 0; + return m_loopcount; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setLoopCount(int count) +{ + if(!m_status) + return false; + m_loopcount = count; + return true; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setStopCallback(stopCallback callback, void* data) +{ + if(!m_status) + return false; + + m_device->lock(); + + m_stop = callback; + m_stop_data = data; + + m_device->unlock(); + + return true; +} + +/******************************************************************************/ +/********************* AUD_OpenALHandle 3DHandle Code *************************/ +/******************************************************************************/ + +AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceLocation() +{ + AUD_Vector3 result = AUD_Vector3(0, 0, 0); + + if(!m_status) + return result; + + m_device->lock(); + + ALfloat p[3]; + alGetSourcefv(m_source, AL_POSITION, p); + + m_device->unlock(); + + result = AUD_Vector3(p[0], p[1], p[2]); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceLocation(const AUD_Vector3& location) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcefv(m_source, AL_POSITION, (ALfloat*)location.get()); + + m_device->unlock(); + + return true; +} + +AUD_Vector3 AUD_OpenALDevice::AUD_OpenALHandle::getSourceVelocity() +{ + AUD_Vector3 result = AUD_Vector3(0, 0, 0); + + if(!m_status) + return result; + + m_device->lock(); + + ALfloat v[3]; + alGetSourcefv(m_source, AL_VELOCITY, v); + + m_device->unlock(); + + result = AUD_Vector3(v[0], v[1], v[2]); + + return result; +} -typedef std::list<AUD_OpenALHandle*>::iterator AUD_HandleIterator; -typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator; +bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceVelocity(const AUD_Vector3& velocity) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcefv(m_source, AL_VELOCITY, (ALfloat*)velocity.get()); + + m_device->unlock(); + + return true; +} + +AUD_Quaternion AUD_OpenALDevice::AUD_OpenALHandle::getSourceOrientation() +{ + // AUD_XXX not implemented yet + return AUD_Quaternion(0, 0, 0, 0); +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setSourceOrientation(const AUD_Quaternion& orientation) +{ + if(!m_status) + return false; + + ALfloat direction[3]; + direction[0] = -2 * (orientation.w() * orientation.y() + + orientation.x() * orientation.z()); + direction[1] = 2 * (orientation.x() * orientation.w() - + orientation.z() * orientation.y()); + direction[2] = 2 * (orientation.x() * orientation.x() + + orientation.y() * orientation.y()) - 1; + m_device->lock(); + + alSourcefv(m_source, AL_DIRECTION, direction); + + m_device->unlock(); + + return true; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::isRelative() +{ + int result; + + if(!m_status) + return false; + + m_device->lock(); + + alGetSourcei(m_source, AL_SOURCE_RELATIVE, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setRelative(bool relative) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcei(m_source, AL_SOURCE_RELATIVE, relative); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMaximum() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_MAX_GAIN, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMaximum(float volume) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_MAX_GAIN, volume); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getVolumeMinimum() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_MIN_GAIN, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setVolumeMinimum(float volume) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_MIN_GAIN, volume); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceMaximum() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_MAX_DISTANCE, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceMaximum(float distance) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_MAX_DISTANCE, distance); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getDistanceReference() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setDistanceReference(float distance) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_REFERENCE_DISTANCE, distance); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getAttenuation() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setAttenuation(float factor) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_ROLLOFF_FACTOR, factor); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleOuter() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_CONE_OUTER_ANGLE, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleOuter(float angle) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_CONE_OUTER_ANGLE, angle); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getConeAngleInner() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_CONE_INNER_ANGLE, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setConeAngleInner(float angle) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_CONE_INNER_ANGLE, angle); + + m_device->unlock(); + + return true; +} + +float AUD_OpenALDevice::AUD_OpenALHandle::getConeVolumeOuter() +{ + float result = std::numeric_limits<float>::quiet_NaN(); + + if(!m_status) + return result; + + m_device->lock(); + + alGetSourcef(m_source, AL_CONE_OUTER_GAIN, &result); + + m_device->unlock(); + + return result; +} + +bool AUD_OpenALDevice::AUD_OpenALHandle::setConeVolumeOuter(float volume) +{ + if(!m_status) + return false; + + m_device->lock(); + + alSourcef(m_source, AL_CONE_OUTER_GAIN, volume); + + m_device->unlock(); + + return true; +} /******************************************************************************/ /**************************** Threading Code **********************************/ @@ -127,16 +797,15 @@ void AUD_OpenALDevice::start() void AUD_OpenALDevice::updateStreams() { - AUD_OpenALHandle* sound; + AUD_Reference<AUD_OpenALHandle> sound; int length; - sample_t* buffer; ALint info; AUD_DeviceSpecs specs = m_specs; ALCenum cerr; - std::list<AUD_OpenALHandle*> stopSounds; - std::list<AUD_OpenALHandle*> pauseSounds; + std::list<AUD_Reference<AUD_OpenALHandle> > stopSounds; + std::list<AUD_Reference<AUD_OpenALHandle> > pauseSounds; AUD_HandleIterator it; while(1) @@ -148,83 +817,86 @@ void AUD_OpenALDevice::updateStreams() if(cerr == ALC_NO_ERROR) { // for all sounds - for(it = m_playingSounds->begin(); it != m_playingSounds->end(); it++) + for(it = m_playingSounds.begin(); it != m_playingSounds.end(); it++) { sound = *it; // is it a streamed sound? - if(!sound->isBuffered) + if(!sound->m_isBuffered) { // check for buffer refilling - alGetSourcei(sound->source, AL_BUFFERS_PROCESSED, &info); + alGetSourcei(sound->m_source, AL_BUFFERS_PROCESSED, &info); if(info) { - specs.specs = sound->reader->getSpecs(); + specs.specs = sound->m_reader->getSpecs(); + m_buffer.assureSize(m_buffersize * AUD_DEVICE_SAMPLE_SIZE(specs)); // for all empty buffers while(info--) { // if there's still data to play back - if(!sound->data_end) + if(!sound->m_eos) { // read data length = m_buffersize; - sound->reader->read(length, buffer); + sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer()); // looping necessary? - if(length == 0 && sound->loopcount) + if(length == 0 && sound->m_loopcount) { - if(sound->loopcount > 0) - sound->loopcount--; + if(sound->m_loopcount > 0) + sound->m_loopcount--; - sound->reader->seek(0); + sound->m_reader->seek(0); length = m_buffersize; - sound->reader->read(length, buffer); + sound->m_reader->read(length, sound->m_eos, m_buffer.getBuffer()); } + if(sound->m_loopcount != 0) + sound->m_eos = false; + // read nothing? if(length == 0) { - sound->data_end = true; break; } // unqueue buffer - alSourceUnqueueBuffers(sound->source, 1, - &sound->buffers[sound->current]); + alSourceUnqueueBuffers(sound->m_source, 1, + &sound->m_buffers[sound->m_current]); ALenum err; if((err = alGetError()) != AL_NO_ERROR) { - sound->data_end = true; + sound->m_eos = true; break; } // fill with new data - alBufferData(sound->buffers[sound->current], - sound->format, - buffer, length * + alBufferData(sound->m_buffers[sound->m_current], + sound->m_format, + m_buffer.getBuffer(), length * AUD_DEVICE_SAMPLE_SIZE(specs), specs.rate); if((err = alGetError()) != AL_NO_ERROR) { - sound->data_end = true; + sound->m_eos = true; break; } // and queue again - alSourceQueueBuffers(sound->source, 1, - &sound->buffers[sound->current]); + alSourceQueueBuffers(sound->m_source, 1, + &sound->m_buffers[sound->m_current]); if(alGetError() != AL_NO_ERROR) { - sound->data_end = true; + sound->m_eos = true; break; } - sound->current = (sound->current+1) % - AUD_OPENAL_CYCLE_BUFFERS; + sound->m_current = (sound->m_current+1) % + AUD_OpenALHandle::CYCLE_BUFFERS; } else break; @@ -233,18 +905,18 @@ void AUD_OpenALDevice::updateStreams() } // check if the sound has been stopped - alGetSourcei(sound->source, AL_SOURCE_STATE, &info); + alGetSourcei(sound->m_source, AL_SOURCE_STATE, &info); if(info != AL_PLAYING) { // if it really stopped - if(sound->data_end) + if(sound->m_eos) { - if(sound->stop) - sound->stop(sound->stop_data); + if(sound->m_stop) + sound->m_stop(sound->m_stop_data); // pause or - if(sound->keep) + if(sound->m_keep) pauseSounds.push_back(sound); // stop else @@ -252,15 +924,15 @@ void AUD_OpenALDevice::updateStreams() } // continue playing else - alSourcePlay(sound->source); + alSourcePlay(sound->m_source); } } for(it = pauseSounds.begin(); it != pauseSounds.end(); it++) - pause(*it); + (*it)->pause(); for(it = stopSounds.begin(); it != stopSounds.end(); it++) - stop(*it); + (*it)->stop(); pauseSounds.clear(); stopSounds.clear(); @@ -269,7 +941,7 @@ void AUD_OpenALDevice::updateStreams() } // stop thread - if(m_playingSounds->empty() || (cerr != ALC_NO_ERROR)) + if(m_playingSounds.empty() || (cerr != ALC_NO_ERROR)) { unlock(); m_playing = false; @@ -290,19 +962,6 @@ void AUD_OpenALDevice::updateStreams() /**************************** IDevice Code ************************************/ /******************************************************************************/ -bool AUD_OpenALDevice::isValid(AUD_Handle* handle) -{ - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) - if(*i == handle) - return true; - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) - if(*i == handle) - return true; - return false; -} - static const char* open_error = "AUD_OpenALDevice: Device couldn't be opened."; AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) @@ -355,9 +1014,7 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) m_buffersize = buffersize; m_playing = false; - m_playingSounds = new std::list<AUD_OpenALHandle*>(); - m_pausedSounds = new std::list<AUD_OpenALHandle*>(); - m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>(); +// m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>(); pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); @@ -370,46 +1027,23 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) AUD_OpenALDevice::~AUD_OpenALDevice() { - AUD_OpenALHandle* sound; - lock(); alcSuspendContext(m_context); - // delete all playing sounds - while(!m_playingSounds->empty()) - { - sound = *(m_playingSounds->begin()); - alDeleteSources(1, &sound->source); - if(!sound->isBuffered) - { - delete sound->reader; - alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); - } - delete sound; - m_playingSounds->erase(m_playingSounds->begin()); - } + while(!m_playingSounds.empty()) + m_playingSounds.front()->stop(); + + while(!m_pausedSounds.empty()) + m_pausedSounds.front()->stop(); - // delete all paused sounds - while(!m_pausedSounds->empty()) - { - sound = *(m_pausedSounds->begin()); - alDeleteSources(1, &sound->source); - if(!sound->isBuffered) - { - delete sound->reader; - alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); - } - delete sound; - m_pausedSounds->erase(m_pausedSounds->begin()); - } // delete all buffered factories - while(!m_bufferedFactories->empty()) + /*while(!m_bufferedFactories->empty()) { alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer); delete *m_bufferedFactories->begin(); m_bufferedFactories->erase(m_bufferedFactories->begin()); - } + }*/ alcProcessContext(m_context); @@ -422,9 +1056,7 @@ AUD_OpenALDevice::~AUD_OpenALDevice() else unlock(); - delete m_playingSounds; - delete m_pausedSounds; - delete m_bufferedFactories; + //delete m_bufferedFactories; // quit OpenAL alcMakeContextCurrent(NULL); @@ -530,120 +1162,54 @@ bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs) return valid; } -static const char* genbuffer_error = "AUD_OpenALDevice: Buffer couldn't be " - "generated."; -static const char* gensource_error = "AUD_OpenALDevice: Source couldn't be " - "generated."; -static const char* queue_error = "AUD_OpenALDevice: Buffer couldn't be " - "queued to the source."; -static const char* bufferdata_error = "AUD_OpenALDevice: Buffer couldn't be " - "filled with data."; - -AUD_Handle* AUD_OpenALDevice::play(AUD_IReader* reader, bool keep) +AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IReader> reader, bool keep) { - AUD_OpenALHandle* sound = NULL; - - AUD_DeviceSpecs specs = m_specs; - specs.specs = reader->getSpecs(); + AUD_Specs specs = reader->getSpecs(); // check format - bool valid = specs.channels != AUD_CHANNELS_INVALID; + if(specs.channels == AUD_CHANNELS_INVALID) + return NULL; if(m_specs.format != AUD_FORMAT_FLOAT32) reader = new AUD_ConverterReader(reader, m_specs); - // create the handle - sound = new AUD_OpenALHandle; - sound->keep = keep; - sound->reader = reader; - sound->current = 0; - sound->isBuffered = false; - sound->data_end = false; - sound->loopcount = 0; - sound->stop = NULL; - sound->stop_data = NULL; - - valid &= getFormat(sound->format, specs.specs); + ALenum format; - if(!valid) - { - delete sound; - delete reader; + if(!getFormat(format, specs)) return NULL; - } lock(); alcSuspendContext(m_context); - // OpenAL playback code + AUD_Reference<AUD_OpenALDevice::AUD_OpenALHandle> sound; + try { - alGenBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); - if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL, genbuffer_error); - - try - { - sample_t* buf; - int length; - - for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++) - { - length = m_buffersize; - reader->read(length, buf); - alBufferData(sound->buffers[i], sound->format, buf, - length * AUD_DEVICE_SAMPLE_SIZE(specs), - specs.rate); - if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL, bufferdata_error); - } - - alGenSources(1, &sound->source); - if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL, gensource_error); - - try - { - alSourceQueueBuffers(sound->source, AUD_OPENAL_CYCLE_BUFFERS, - sound->buffers); - if(alGetError() != AL_NO_ERROR) - AUD_THROW(AUD_ERROR_OPENAL, queue_error); - } - catch(AUD_Exception&) - { - alDeleteSources(1, &sound->source); - throw; - } - } - catch(AUD_Exception&) - { - alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); - throw; - } + // create the handle + sound = new AUD_OpenALDevice::AUD_OpenALHandle(this, format, reader, keep); } catch(AUD_Exception&) { - delete sound; - delete reader; alcProcessContext(m_context); unlock(); throw; } + alcProcessContext(m_context); + // play sound - m_playingSounds->push_back(sound); - alSourcei(sound->source, AL_SOURCE_RELATIVE, 1); + m_playingSounds.push_back(sound); start(); - alcProcessContext(m_context); unlock(); - return sound; + return AUD_Reference<AUD_IHandle>(sound); } -AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) +AUD_Reference<AUD_IHandle> AUD_OpenALDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep) { + /* AUD_XXX disabled AUD_OpenALHandle* sound = NULL; lock(); @@ -661,7 +1227,7 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) sound->keep = keep; sound->current = -1; sound->isBuffered = true; - sound->data_end = true; + sound->eos = true; sound->loopcount = 0; sound->stop = NULL; sound->stop_data = NULL; @@ -713,266 +1279,11 @@ AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep) unlock(); if(sound) - return sound; + return sound;*/ return play(factory->createReader(), keep); } -bool AUD_OpenALDevice::pause(AUD_Handle* handle) -{ - bool result = false; - - lock(); - - // only songs that are played can be paused - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) - { - if(*i == handle) - { - m_pausedSounds->push_back(*i); - alSourcePause((*i)->source); - m_playingSounds->erase(i); - result = true; - break; - } - } - - unlock(); - - return result; -} - -bool AUD_OpenALDevice::resume(AUD_Handle* handle) -{ - bool result = false; - - lock(); - - // only songs that are paused can be resumed - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) - { - if(*i == handle) - { - m_playingSounds->push_back(*i); - start(); - m_pausedSounds->erase(i); - result = true; - break; - } - } - - unlock(); - - return result; -} - -bool AUD_OpenALDevice::stop(AUD_Handle* handle) -{ - AUD_OpenALHandle* sound; - - bool result = false; - - lock(); - - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) - { - if(*i == handle) - { - sound = *i; - alDeleteSources(1, &sound->source); - if(!sound->isBuffered) - { - delete sound->reader; - alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); - } - delete *i; - m_playingSounds->erase(i); - result = true; - break; - } - } - if(!result) - { - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) - { - if(*i == handle) - { - sound = *i; - alDeleteSources(1, &sound->source); - if(!sound->isBuffered) - { - delete sound->reader; - alDeleteBuffers(AUD_OPENAL_CYCLE_BUFFERS, sound->buffers); - } - delete *i; - m_pausedSounds->erase(i); - result = true; - break; - } - } - } - - unlock(); - - return result; -} - -bool AUD_OpenALDevice::getKeep(AUD_Handle* handle) -{ - bool result = false; - - lock(); - - if(isValid(handle)) - result = ((AUD_OpenALHandle*)handle)->keep; - - unlock(); - - return result; -} - -bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep) -{ - bool result = false; - - lock(); - - if(isValid(handle)) - { - ((AUD_OpenALHandle*)handle)->keep = keep; - result = true; - } - - unlock(); - - return result; -} - -bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position) -{ - bool result = false; - - lock(); - - if(isValid(handle)) - { - AUD_OpenALHandle* alhandle = (AUD_OpenALHandle*)handle; - if(alhandle->isBuffered) - alSourcef(alhandle->source, AL_SEC_OFFSET, position); - else - { - alhandle->reader->seek((int)(position * - alhandle->reader->getSpecs().rate)); - alhandle->data_end = false; - - ALint info; - - alGetSourcei(alhandle->source, AL_SOURCE_STATE, &info); - - if(info != AL_PLAYING) - { - if(info == AL_PAUSED) - alSourceStop(alhandle->source); - - alSourcei(alhandle->source, AL_BUFFER, 0); - alhandle->current = 0; - - ALenum err; - if((err = alGetError()) == AL_NO_ERROR) - { - sample_t* buf; - int length; - AUD_DeviceSpecs specs = m_specs; - specs.specs = alhandle->reader->getSpecs(); - - for(int i = 0; i < AUD_OPENAL_CYCLE_BUFFERS; i++) - { - length = m_buffersize; - alhandle->reader->read(length, buf); - alBufferData(alhandle->buffers[i], alhandle->format, - buf, - length * AUD_DEVICE_SAMPLE_SIZE(specs), - specs.rate); - - if(alGetError() != AL_NO_ERROR) - break; - } - - alSourceQueueBuffers(alhandle->source, - AUD_OPENAL_CYCLE_BUFFERS, - alhandle->buffers); - } - - alSourceRewind(alhandle->source); - } - } - result = true; - } - - unlock(); - return result; -} - -float AUD_OpenALDevice::getPosition(AUD_Handle* handle) -{ - float position = 0.0f; - - lock(); - - if(isValid(handle)) - { - AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle; - alGetSourcef(h->source, AL_SEC_OFFSET, &position); - if(!h->isBuffered) - { - AUD_Specs specs = h->reader->getSpecs(); - position += (h->reader->getPosition() - m_buffersize * - AUD_OPENAL_CYCLE_BUFFERS) / - (float)specs.rate; - } - } - - unlock(); - return position; -} - -AUD_Status AUD_OpenALDevice::getStatus(AUD_Handle* handle) -{ - AUD_Status status = AUD_STATUS_INVALID; - - lock(); - - for(AUD_HandleIterator i = m_playingSounds->begin(); - i != m_playingSounds->end(); i++) - { - if(*i == handle) - { - status = AUD_STATUS_PLAYING; - break; - } - } - if(status == AUD_STATUS_INVALID) - { - for(AUD_HandleIterator i = m_pausedSounds->begin(); - i != m_pausedSounds->end(); i++) - { - if(*i == handle) - { - status = AUD_STATUS_PAUSED; - break; - } - } - } - - unlock(); - - return status; -} - void AUD_OpenALDevice::lock() { pthread_mutex_lock(&m_mutex); @@ -995,80 +1306,6 @@ void AUD_OpenALDevice::setVolume(float volume) alListenerf(AL_GAIN, volume); } -float AUD_OpenALDevice::getVolume(AUD_Handle* handle) -{ - lock(); - float result = std::numeric_limits<float>::quiet_NaN(); - if(isValid(handle)) - alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_GAIN, &result); - unlock(); - return result; -} - -bool AUD_OpenALDevice::setVolume(AUD_Handle* handle, float volume) -{ - lock(); - bool result = isValid(handle); - if(result) - alSourcef(((AUD_OpenALHandle*)handle)->source, AL_GAIN, volume); - unlock(); - return result; -} - -float AUD_OpenALDevice::getPitch(AUD_Handle* handle) -{ - lock(); - float result = std::numeric_limits<float>::quiet_NaN(); - if(isValid(handle)) - alGetSourcef(((AUD_OpenALHandle*)handle)->source,AL_PITCH, &result); - unlock(); - return result; -} - -bool AUD_OpenALDevice::setPitch(AUD_Handle* handle, float pitch) -{ - lock(); - bool result = isValid(handle); - if(result) - alSourcef(((AUD_OpenALHandle*)handle)->source, AL_PITCH, pitch); - unlock(); - return result; -} - -int AUD_OpenALDevice::getLoopCount(AUD_Handle* handle) -{ - lock(); - int result = 0; - if(isValid(handle)) - result = ((AUD_OpenALHandle*)handle)->loopcount; - unlock(); - return result; -} - -bool AUD_OpenALDevice::setLoopCount(AUD_Handle* handle, int count) -{ - lock(); - bool result = isValid(handle); - if(result) - ((AUD_OpenALHandle*)handle)->loopcount = count; - unlock(); - return result; -} - -bool AUD_OpenALDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data) -{ - lock(); - bool result = isValid(handle); - if(result) - { - AUD_OpenALHandle* h = (AUD_OpenALHandle*)handle; - h->stop = callback; - h->stop_data = data; - } - unlock(); - return result; -} - /* AUD_XXX Temorary disabled bool AUD_OpenALDevice::bufferFactory(void *value) @@ -1109,7 +1346,6 @@ bool AUD_OpenALDevice::bufferFactory(void *value) if(!getFormat(format, specs.specs)) { - delete reader; return false; } @@ -1147,7 +1383,6 @@ bool AUD_OpenALDevice::bufferFactory(void *value) catch(AUD_Exception&) { delete bf; - delete reader; alcProcessContext(m_context); unlock(); return false; @@ -1308,333 +1543,3 @@ void AUD_OpenALDevice::setDistanceModel(AUD_DistanceModel model) alDistanceModel(AL_NONE); } } - -AUD_Vector3 AUD_OpenALDevice::getSourceLocation(AUD_Handle* handle) -{ - AUD_Vector3 result = AUD_Vector3(0, 0, 0); - ALfloat p[3]; - lock(); - - if(isValid(handle)) - { - alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION, p); - result = AUD_Vector3(p[0], p[1], p[2]); - } - - unlock(); - return result; -} - -bool AUD_OpenALDevice::setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location) -{ - lock(); - bool result = isValid(handle); - - if(result) - alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_POSITION, - (ALfloat*)location.get()); - - unlock(); - return result; -} - -AUD_Vector3 AUD_OpenALDevice::getSourceVelocity(AUD_Handle* handle) -{ - AUD_Vector3 result = AUD_Vector3(0, 0, 0); - ALfloat v[3]; - lock(); - - if(isValid(handle)) - { - alGetSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY, v); - result = AUD_Vector3(v[0], v[1], v[2]); - } - - unlock(); - return result; -} - -bool AUD_OpenALDevice::setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity) -{ - lock(); - bool result = isValid(handle); - - if(result) - alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_VELOCITY, - (ALfloat*)velocity.get()); - - unlock(); - return result; -} - -AUD_Quaternion AUD_OpenALDevice::getSourceOrientation(AUD_Handle* handle) -{ - // AUD_XXX not implemented yet - return AUD_Quaternion(0, 0, 0, 0); -} - -bool AUD_OpenALDevice::setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation) -{ - lock(); - bool result = isValid(handle); - - if(result) - { - ALfloat direction[3]; - direction[0] = -2 * (orientation.w() * orientation.y() + - orientation.x() * orientation.z()); - direction[1] = 2 * (orientation.x() * orientation.w() - - orientation.z() * orientation.y()); - direction[2] = 2 * (orientation.x() * orientation.x() + - orientation.y() * orientation.y()) - 1; - alSourcefv(((AUD_OpenALHandle*)handle)->source, AL_DIRECTION, - direction); - } - - unlock(); - return result; -} - -bool AUD_OpenALDevice::isRelative(AUD_Handle* handle) -{ - int result = std::numeric_limits<float>::quiet_NaN();; - - lock(); - - if(isValid(handle)) - alGetSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE, - &result); - - unlock(); - return result; -} - -bool AUD_OpenALDevice::setRelative(AUD_Handle* handle, bool relative) -{ - lock(); - bool result = isValid(handle); - - if(result) - alSourcei(((AUD_OpenALHandle*)handle)->source, AL_SOURCE_RELATIVE, - relative); - - unlock(); - return result; -} - -float AUD_OpenALDevice::getVolumeMaximum(AUD_Handle* handle) -{ - float result = std::numeric_limits<float>::quiet_NaN();; - - lock(); - - if(isValid(handle)) - alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN, - &result); - - unlock(); - return result; -} - -bool AUD_OpenALDevice::setVolumeMaximum(AUD_Handle* handle, float volume) -{ - lock(); - bool result = isValid(handle); - - if(result) - - alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_GAIN, - volume); - - unlock(); - return result; -} - -float AUD_OpenALDevice::getVolumeMinimum(AUD_Handle* handle) -{ - float result = std::numeric_limits<float>::quiet_NaN();; - - lock(); - - if(isValid(handle)) - alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN, - &result); - - unlock(); - return result; -} - -bool AUD_OpenALDevice::setVolumeMinimum(AUD_Handle* handle, float volume) -{ - lock(); - bool result = isValid(handle); - - if(result) - alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MIN_GAIN, - volume); - - unlock(); - return result; -} - -float AUD_OpenALDevice::getDistanceMaximum(AUD_Handle* handle) -{ - float result = std::numeric_limits<float>::quiet_NaN();; - - lock(); - - if(isValid(handle)) - alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE, - &result); - - unlock(); - return result; -} - -bool AUD_OpenALDevice::setDistanceMaximum(AUD_Handle* handle, float distance) -{ - lock(); - bool result = isValid(handle); - - if(result) - alSourcef(((AUD_OpenALHandle*)handle)->source, AL_MAX_DISTANCE, - distance); - - unlock(); - return result; -} - -float AUD_OpenALDevice::getDistanceReference(AUD_Handle* handle) -{ - float result = std::numeric_limits<float>::quiet_NaN();; - - lock(); - - if(isValid(handle)) - alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE, - &result); - - unlock(); - return result; -} - -bool AUD_OpenALDevice::setDistanceReference(AUD_Handle* handle, float distance) -{ - lock(); - bool result = isValid(handle); - - if(result) - alSourcef(((AUD_OpenALHandle*)handle)->source, AL_REFERENCE_DISTANCE, - distance); - - unlock(); - return result; -} - -float AUD_OpenALDevice::getAttenuation(AUD_Handle* handle) -{ - float result = std::numeric_limits<float>::quiet_NaN();; - - lock(); - - if(isValid(handle)) - alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR, - &result); - - unlock(); - return result; -} - -bool AUD_OpenALDevice::setAttenuation(AUD_Handle* handle, float factor) -{ - lock(); - bool result = isValid(handle); - - if(result) - alSourcef(((AUD_OpenALHandle*)handle)->source, AL_ROLLOFF_FACTOR, - factor); - - unlock(); - return result; -} - -float AUD_OpenALDevice::getConeAngleOuter(AUD_Handle* handle) -{ - float result = std::numeric_limits<float>::quiet_NaN();; - - lock(); - - if(isValid(handle)) - alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE, - &result); - - unlock(); - return result; -} - -bool AUD_OpenALDevice::setConeAngleOuter(AUD_Handle* handle, float angle) -{ - lock(); - bool result = isValid(handle); - - if(result) - alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_ANGLE, - angle); - - unlock(); - return result; -} - -float AUD_OpenALDevice::getConeAngleInner(AUD_Handle* handle) -{ - float result = std::numeric_limits<float>::quiet_NaN();; - - lock(); - - if(isValid(handle)) - alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE, - &result); - - unlock(); - return result; -} - -bool AUD_OpenALDevice::setConeAngleInner(AUD_Handle* handle, float angle) -{ - lock(); - bool result = isValid(handle); - - if(result) - alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_INNER_ANGLE, - angle); - - unlock(); - return result; -} - -float AUD_OpenALDevice::getConeVolumeOuter(AUD_Handle* handle) -{ - float result = std::numeric_limits<float>::quiet_NaN();; - - lock(); - - if(isValid(handle)) - alGetSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN, - &result); - - unlock(); - return result; -} - -bool AUD_OpenALDevice::setConeVolumeOuter(AUD_Handle* handle, float volume) -{ - lock(); - bool result = isValid(handle); - - if(result) - alSourcef(((AUD_OpenALHandle*)handle)->source, AL_CONE_OUTER_GAIN, - volume); - - unlock(); - return result; -} diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.h b/intern/audaspace/OpenAL/AUD_OpenALDevice.h index 3bbbe85d7e6..ea4f9ca1ea8 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.h +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.h @@ -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,100 @@ 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; + + /// Current status of the handle + AUD_Status m_status; + + /// Own device. + AUD_OpenALDevice* m_device; + + public: + + 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 +167,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 +200,14 @@ private: int m_buffersize; /** - * Starts the streaming thread. + * Device buffer. */ - void start(); + AUD_Buffer m_buffer; /** - * Checks if a handle is valid. - * \param handle The handle to check. - * \return Whether the handle is valid. + * Starts the streaming thread. */ - bool isValid(AUD_Handle* handle); + void start(); /** * Gets the format according to the specs. @@ -147,27 +241,12 @@ 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 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 +260,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 diff --git a/intern/audaspace/Python/AUD_PyAPI.cpp b/intern/audaspace/Python/AUD_PyAPI.cpp index 22376a2fcd1..12bb19644f0 100644 --- a/intern/audaspace/Python/AUD_PyAPI.cpp +++ b/intern/audaspace/Python/AUD_PyAPI.cpp @@ -33,6 +33,7 @@ #include "structmember.h" #include "AUD_I3DDevice.h" +#include "AUD_I3DHandle.h" #include "AUD_NULLDevice.h" #include "AUD_DelayFactory.h" #include "AUD_DoubleFactory.h" @@ -91,7 +92,7 @@ static void Factory_dealloc(Factory* self) { if(self->factory) - delete self->factory; + delete reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory); Py_XDECREF(self->child_list); Py_TYPE(self)->tp_free((PyObject*)self); } @@ -115,7 +116,7 @@ Factory_new(PyTypeObject *type, PyObject *args, PyObject *kwds) try { - self->factory = new AUD_FileFactory(filename); + self->factory = new AUD_Reference<AUD_IFactory>(new AUD_FileFactory(filename)); } catch(AUD_Exception& e) { @@ -155,7 +156,7 @@ Factory_sine(PyTypeObject* type, PyObject* args) { try { - self->factory = new AUD_SinusFactory(frequency, (AUD_SampleRate)rate); + self->factory = new AUD_Reference<AUD_IFactory>(new AUD_SinusFactory(frequency, (AUD_SampleRate)rate)); } catch(AUD_Exception& e) { @@ -194,7 +195,7 @@ Factory_file(PyTypeObject* type, PyObject* args) { try { - self->factory = new AUD_FileFactory(filename); + self->factory = new AUD_Reference<AUD_IFactory>(new AUD_FileFactory(filename)); } catch(AUD_Exception& e) { @@ -237,7 +238,7 @@ Factory_lowpass(Factory* self, PyObject* args) try { - parent->factory = new AUD_LowpassFactory(self->factory, frequency, Q); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LowpassFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), frequency, Q)); } catch(AUD_Exception& e) { @@ -278,7 +279,7 @@ Factory_delay(Factory* self, PyObject* args) try { - parent->factory = new AUD_DelayFactory(self->factory, delay); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_DelayFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), delay)); } catch(AUD_Exception& e) { @@ -322,7 +323,7 @@ Factory_join(Factory* self, PyObject* object) try { - parent->factory = new AUD_DoubleFactory(self->factory, child->factory); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_DoubleFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), *reinterpret_cast<AUD_Reference<AUD_IFactory>*>(child->factory))); } catch(AUD_Exception& e) { @@ -365,7 +366,7 @@ Factory_highpass(Factory* self, PyObject* args) try { - parent->factory = new AUD_HighpassFactory(self->factory, frequency, Q); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_HighpassFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), frequency, Q)); } catch(AUD_Exception& e) { @@ -406,7 +407,7 @@ Factory_limit(Factory* self, PyObject* args) try { - parent->factory = new AUD_LimiterFactory(self->factory, start, end); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LimiterFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), start, end)); } catch(AUD_Exception& e) { @@ -450,7 +451,7 @@ Factory_pitch(Factory* self, PyObject* args) try { - parent->factory = new AUD_PitchFactory(self->factory, factor); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_PitchFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), factor)); } catch(AUD_Exception& e) { @@ -492,7 +493,7 @@ Factory_volume(Factory* self, PyObject* args) try { - parent->factory = new AUD_VolumeFactory(self->factory, volume); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_VolumeFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), volume)); } catch(AUD_Exception& e) { @@ -535,7 +536,7 @@ Factory_fadein(Factory* self, PyObject* args) try { - parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_IN, start, length); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_FaderFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), AUD_FADE_IN, start, length)); } catch(AUD_Exception& e) { @@ -579,7 +580,7 @@ Factory_fadeout(Factory* self, PyObject* args) try { - parent->factory = new AUD_FaderFactory(self->factory, AUD_FADE_OUT, start, length); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_FaderFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), AUD_FADE_OUT, start, length)); } catch(AUD_Exception& e) { @@ -621,7 +622,7 @@ Factory_loop(Factory* self, PyObject* args) try { - parent->factory = new AUD_LoopFactory(self->factory, loop); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_LoopFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), loop)); } catch(AUD_Exception& e) { @@ -664,7 +665,7 @@ Factory_mix(Factory* self, PyObject* object) try { - parent->factory = new AUD_SuperposeFactory(self->factory, child->factory); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_SuperposeFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), *reinterpret_cast<AUD_Reference<AUD_IFactory>*>(child->factory))); } catch(AUD_Exception& e) { @@ -697,7 +698,7 @@ Factory_pingpong(Factory* self) try { - parent->factory = new AUD_PingPongFactory(self->factory); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_PingPongFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory))); } catch(AUD_Exception& e) { @@ -736,7 +737,7 @@ Factory_reverse(Factory* self) try { - parent->factory = new AUD_ReverseFactory(self->factory); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_ReverseFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory))); } catch(AUD_Exception& e) { @@ -771,7 +772,7 @@ Factory_buffer(Factory* self) { try { - parent->factory = new AUD_StreamBufferFactory(self->factory); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_StreamBufferFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory))); } catch(AUD_Exception& e) { @@ -813,7 +814,7 @@ Factory_square(Factory* self, PyObject* args) try { - parent->factory = new AUD_SquareFactory(self->factory, threshold); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_SquareFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), threshold)); } catch(AUD_Exception& e) { @@ -910,7 +911,7 @@ Factory_filter(Factory* self, PyObject* args) try { - parent->factory = new AUD_IIRFilterFactory(self->factory, b, a); + parent->factory = new AUD_Reference<AUD_IFactory>(new AUD_IIRFilterFactory(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(self->factory), b, a)); } catch(AUD_Exception& e) { @@ -1033,7 +1034,8 @@ static PyTypeObject FactoryType = { static void Handle_dealloc(Handle* self) { - Py_XDECREF(self->device); + if(self->handle) + delete reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle); Py_TYPE(self)->tp_free((PyObject*)self); } @@ -1046,11 +1048,9 @@ PyDoc_STRVAR(M_aud_Handle_pause_doc, static PyObject * Handle_pause(Handle *self) { - Device* device = (Device*)self->device; - try { - return PyBool_FromLong((long)device->device->pause(self->handle)); + return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->pause()); } catch(AUD_Exception& e) { @@ -1068,11 +1068,9 @@ PyDoc_STRVAR(M_aud_Handle_resume_doc, static PyObject * Handle_resume(Handle *self) { - Device* device = (Device*)self->device; - try { - return PyBool_FromLong((long)device->device->resume(self->handle)); + return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->resume()); } catch(AUD_Exception& e) { @@ -1091,11 +1089,9 @@ PyDoc_STRVAR(M_aud_Handle_stop_doc, static PyObject * Handle_stop(Handle *self) { - Device* device = (Device*)self->device; - try { - return PyBool_FromLong((long)device->device->stop(self->handle)); + return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->stop()); } catch(AUD_Exception& e) { @@ -1123,11 +1119,9 @@ PyDoc_STRVAR(M_aud_Handle_position_doc, static PyObject * Handle_get_position(Handle *self, void* nothing) { - Device* device = (Device*)self->device; - try { - return Py_BuildValue("f", device->device->getPosition(self->handle)); + return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getPosition()); } catch(AUD_Exception& e) { @@ -1144,11 +1138,9 @@ Handle_set_position(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "f:position", &position)) return -1; - Device* device = (Device*)self->device; - try { - if(device->device->seek(self->handle, position)) + if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->seek(position)) return 0; PyErr_SetString(AUDError, "Couldn't seek the sound!"); } @@ -1172,11 +1164,9 @@ PyDoc_STRVAR(M_aud_Handle_keep_doc, static PyObject * Handle_get_keep(Handle *self, void* nothing) { - Device* device = (Device*)self->device; - try { - return PyBool_FromLong((long)device->device->getKeep(self->handle)); + return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getKeep()); } catch(AUD_Exception& e) { @@ -1195,11 +1185,10 @@ Handle_set_keep(Handle *self, PyObject* args, void* nothing) } bool keep = args == Py_True; - Device* device = (Device*)self->device; try { - if(device->device->setKeep(self->handle, keep)) + if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setKeep(keep)) return 0; PyErr_SetString(AUDError, "Couldn't set keep of the sound!"); } @@ -1217,11 +1206,9 @@ PyDoc_STRVAR(M_aud_Handle_status_doc, static PyObject * Handle_get_status(Handle *self, void* nothing) { - Device* device = (Device*)self->device; - try { - return PyBool_FromLong((long)device->device->getStatus(self->handle)); + return PyBool_FromLong((long)(*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getStatus()); } catch(AUD_Exception& e) { @@ -1236,11 +1223,9 @@ PyDoc_STRVAR(M_aud_Handle_volume_doc, static PyObject * Handle_get_volume(Handle *self, void* nothing) { - Device* device = (Device*)self->device; - try { - return Py_BuildValue("f", device->device->getVolume(self->handle)); + return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getVolume()); } catch(AUD_Exception& e) { @@ -1257,11 +1242,9 @@ Handle_set_volume(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "f:volume", &volume)) return -1; - Device* device = (Device*)self->device; - try { - if(device->device->setVolume(self->handle, volume)) + if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setVolume(volume)) return 0; PyErr_SetString(AUDError, "Couldn't set the sound volume!"); } @@ -1279,11 +1262,9 @@ PyDoc_STRVAR(M_aud_Handle_pitch_doc, static PyObject * Handle_get_pitch(Handle *self, void* nothing) { - Device* device = (Device*)self->device; - try { - return Py_BuildValue("f", device->device->getPitch(self->handle)); + return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getPitch()); } catch(AUD_Exception& e) { @@ -1300,11 +1281,9 @@ Handle_set_pitch(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "f:pitch", &pitch)) return -1; - Device* device = (Device*)self->device; - try { - if(device->device->setPitch(self->handle, pitch)) + if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setPitch(pitch)) return 0; PyErr_SetString(AUDError, "Couldn't set the sound pitch!"); } @@ -1322,11 +1301,9 @@ PyDoc_STRVAR(M_aud_Handle_loop_count_doc, static PyObject * Handle_get_loop_count(Handle *self, void* nothing) { - Device* device = (Device*)self->device; - try { - return Py_BuildValue("i", device->device->getLoopCount(self->handle)); + return Py_BuildValue("i", (*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->getLoopCount()); } catch(AUD_Exception& e) { @@ -1343,11 +1320,9 @@ Handle_set_loop_count(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "i:loop_count", &loops)) return -1; - Device* device = (Device*)self->device; - try { - if(device->device->setLoopCount(self->handle, loops)) + if((*reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle))->setLoopCount(loops)) return 0; PyErr_SetString(AUDError, "Couldn't set the loop count!"); } @@ -1365,14 +1340,12 @@ PyDoc_STRVAR(M_aud_Handle_location_doc, static PyObject * Handle_get_location(Handle *self, void* nothing) { - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - AUD_Vector3 v = device->getSourceLocation(self->handle); + AUD_Vector3 v = handle->getSourceLocation(); return Py_BuildValue("(fff)", v.x(), v.y(), v.z()); } else @@ -1396,15 +1369,13 @@ Handle_set_location(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "(fff):location", &x, &y, &z)) return -1; - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { AUD_Vector3 location(x, y, z); - if(device->setSourceLocation(self->handle, location)) + if(handle->setSourceLocation(location)) return 0; PyErr_SetString(AUDError, "Location couldn't be set!"); } @@ -1425,14 +1396,12 @@ PyDoc_STRVAR(M_aud_Handle_velocity_doc, static PyObject * Handle_get_velocity(Handle *self, void* nothing) { - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - AUD_Vector3 v = device->getSourceVelocity(self->handle); + AUD_Vector3 v = handle->getSourceVelocity(); return Py_BuildValue("(fff)", v.x(), v.y(), v.z()); } else @@ -1456,15 +1425,13 @@ Handle_set_velocity(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z)) return -1; - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { AUD_Vector3 velocity(x, y, z); - if(device->setSourceVelocity(self->handle, velocity)) + if(handle->setSourceVelocity(velocity)) return 0; PyErr_SetString(AUDError, "Couldn't set the velocity!"); } @@ -1485,14 +1452,12 @@ PyDoc_STRVAR(M_aud_Handle_orientation_doc, static PyObject * Handle_get_orientation(Handle *self, void* nothing) { - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - AUD_Quaternion o = device->getSourceOrientation(self->handle); + AUD_Quaternion o = handle->getSourceOrientation(); return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z()); } else @@ -1516,15 +1481,13 @@ Handle_set_orientation(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z)) return -1; - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { AUD_Quaternion orientation(w, x, y, z); - if(device->setSourceOrientation(self->handle, orientation)) + if(handle->setSourceOrientation(orientation)) return 0; PyErr_SetString(AUDError, "Couldn't set the orientation!"); } @@ -1545,14 +1508,12 @@ PyDoc_STRVAR(M_aud_Handle_relative_doc, static PyObject * Handle_get_relative(Handle *self, void* nothing) { - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - return PyBool_FromLong((long)device->isRelative(self->handle)); + return PyBool_FromLong((long)handle->isRelative()); } else { @@ -1577,14 +1538,13 @@ Handle_set_relative(Handle *self, PyObject* args, void* nothing) } bool relative = (args == Py_True); - Device* dev = (Device*)self->device; try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - if(device->setRelative(self->handle, relative)) + if(handle->setRelative(relative)) return 0; PyErr_SetString(AUDError, "Couldn't set the relativeness!"); } @@ -1606,14 +1566,12 @@ PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc, static PyObject * Handle_get_volume_minimum(Handle *self, void* nothing) { - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - return Py_BuildValue("f", device->getVolumeMinimum(self->handle)); + return Py_BuildValue("f", handle->getVolumeMinimum()); } else { @@ -1636,14 +1594,12 @@ Handle_set_volume_minimum(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "f:volume_minimum", &volume)) return -1; - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - if(device->setVolumeMinimum(self->handle, volume)) + if(handle->setVolumeMinimum(volume)) return 0; PyErr_SetString(AUDError, "Couldn't set the minimum volume!"); } @@ -1665,14 +1621,12 @@ PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc, static PyObject * Handle_get_volume_maximum(Handle *self, void* nothing) { - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - return Py_BuildValue("f", device->getVolumeMaximum(self->handle)); + return Py_BuildValue("f", handle->getVolumeMaximum()); } else { @@ -1695,14 +1649,12 @@ Handle_set_volume_maximum(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "f:volume_maximum", &volume)) return -1; - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - if(device->setVolumeMaximum(self->handle, volume)) + if(handle->setVolumeMaximum(volume)) return 0; PyErr_SetString(AUDError, "Couldn't set the maximum volume!"); } @@ -1725,14 +1677,12 @@ PyDoc_STRVAR(M_aud_Handle_distance_reference_doc, static PyObject * Handle_get_distance_reference(Handle *self, void* nothing) { - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - return Py_BuildValue("f", device->getDistanceReference(self->handle)); + return Py_BuildValue("f", handle->getDistanceReference()); } else { @@ -1755,14 +1705,12 @@ Handle_set_distance_reference(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "f:distance_reference", &distance)) return -1; - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - if(device->setDistanceReference(self->handle, distance)) + if(handle->setDistanceReference(distance)) return 0; PyErr_SetString(AUDError, "Couldn't set the reference distance!"); } @@ -1785,14 +1733,12 @@ PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc, static PyObject * Handle_get_distance_maximum(Handle *self, void* nothing) { - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - return Py_BuildValue("f", device->getDistanceMaximum(self->handle)); + return Py_BuildValue("f", handle->getDistanceMaximum()); } else { @@ -1815,14 +1761,12 @@ Handle_set_distance_maximum(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "f:distance_maximum", &distance)) return -1; - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - if(device->setDistanceMaximum(self->handle, distance)) + if(handle->setDistanceMaximum(distance)) return 0; PyErr_SetString(AUDError, "Couldn't set the maximum distance!"); } @@ -1845,14 +1789,12 @@ PyDoc_STRVAR(M_aud_Handle_attenuation_doc, static PyObject * Handle_get_attenuation(Handle *self, void* nothing) { - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - return Py_BuildValue("f", device->getAttenuation(self->handle)); + return Py_BuildValue("f", handle->getAttenuation()); } else { @@ -1875,14 +1817,12 @@ Handle_set_attenuation(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "f:attenuation", &factor)) return -1; - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - if(device->setAttenuation(self->handle, factor)) + if(handle->setAttenuation(factor)) return 0; PyErr_SetString(AUDError, "Couldn't set the attenuation!"); } @@ -1910,14 +1850,12 @@ PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc, static PyObject * Handle_get_cone_angle_inner(Handle *self, void* nothing) { - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - return Py_BuildValue("f", device->getConeAngleInner(self->handle)); + return Py_BuildValue("f", handle->getConeAngleInner()); } else { @@ -1940,14 +1878,12 @@ Handle_set_cone_angle_inner(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "f:cone_angle_inner", &angle)) return -1; - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - if(device->setConeAngleInner(self->handle, angle)) + if(handle->setConeAngleInner(angle)) return 0; PyErr_SetString(AUDError, "Couldn't set the cone inner angle!"); } @@ -1969,14 +1905,12 @@ PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc, static PyObject * Handle_get_cone_angle_outer(Handle *self, void* nothing) { - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - return Py_BuildValue("f", device->getConeAngleOuter(self->handle)); + return Py_BuildValue("f", handle->getConeAngleOuter()); } else { @@ -1999,14 +1933,12 @@ Handle_set_cone_angle_outer(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "f:cone_angle_outer", &angle)) return -1; - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - if(device->setConeAngleOuter(self->handle, angle)) + if(handle->setConeAngleOuter(angle)) return 0; PyErr_SetString(AUDError, "Couldn't set the cone outer angle!"); } @@ -2028,14 +1960,12 @@ PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc, static PyObject * Handle_get_cone_volume_outer(Handle *self, void* nothing) { - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - return Py_BuildValue("f", device->getConeVolumeOuter(self->handle)); + return Py_BuildValue("f", handle->getConeVolumeOuter()); } else { @@ -2058,14 +1988,12 @@ Handle_set_cone_volume_outer(Handle *self, PyObject* args, void* nothing) if(!PyArg_Parse(args, "f:cone_volume_outer", &volume)) return -1; - Device* dev = (Device*)self->device; - try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(dev->device); - if(device) + AUD_I3DHandle* handle = dynamic_cast<AUD_I3DHandle*>(reinterpret_cast<AUD_Reference<AUD_IHandle>*>(self->handle)->get()); + if(handle) { - if(device->setConeVolumeOuter(self->handle, volume)) + if(handle->setConeVolumeOuter(volume)) return 0; PyErr_SetString(AUDError, "Couldn't set the cone outer volume!"); } @@ -2172,7 +2100,7 @@ static void Device_dealloc(Device* self) { if(self->device) - delete self->device; + delete reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device); Py_TYPE(self)->tp_free((PyObject*)self); } @@ -2183,13 +2111,13 @@ Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static const char *kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", NULL}; int device; - int rate = AUD_RATE_44100; + double rate = AUD_RATE_44100; int channels = AUD_CHANNELS_STEREO; int format = AUD_FORMAT_FLOAT32; int buffersize = AUD_DEFAULT_BUFFER_SIZE; const char* name = "Audaspace"; - if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|iiiis:Device", const_cast<char**>(kwlist), + if(!PyArg_ParseTupleAndKeywords(args, kwds, "i|diiis:Device", const_cast<char**>(kwlist), &device, &rate, &channels, &format, &buffersize, &name)) return NULL; @@ -2215,21 +2143,21 @@ Device_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { case AUD_DEVICE_NULL: (void)specs; /* quiet warning when others disabled */ - self->device = new AUD_NULLDevice(); + self->device = new AUD_Reference<AUD_IDevice>(new AUD_NULLDevice()); break; case AUD_DEVICE_OPENAL: #ifdef WITH_OPENAL - self->device = new AUD_OpenALDevice(specs, buffersize); + self->device = new AUD_Reference<AUD_IDevice>(new AUD_OpenALDevice(specs, buffersize)); #endif break; case AUD_DEVICE_SDL: #ifdef WITH_SDL - self->device = new AUD_SDLDevice(specs, buffersize); + self->device = new AUD_Reference<AUD_IDevice>(new AUD_SDLDevice(specs, buffersize)); #endif break; case AUD_DEVICE_JACK: #ifdef WITH_JACK - self->device = new AUD_JackDevice(name, specs, buffersize); + self->device = new AUD_Reference<AUD_IDevice>(new AUD_JackDevice(name, specs, buffersize)); #endif break; case AUD_DEVICE_READ: @@ -2302,12 +2230,9 @@ Device_play(Device *self, PyObject *args, PyObject *kwds) handle = (Handle*)HandleType.tp_alloc(&HandleType, 0); if(handle != NULL) { - handle->device = (PyObject*)self; - Py_INCREF(self); - try { - handle->handle = self->device->play(sound->factory, keep); + handle->handle = new AUD_Reference<AUD_IHandle>((*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->play(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(sound->factory), keep)); } catch(AUD_Exception& e) { @@ -2336,7 +2261,7 @@ Device_lock(Device *self) { try { - self->device->lock(); + (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->lock(); Py_RETURN_NONE; } catch(AUD_Exception& e) @@ -2356,7 +2281,7 @@ Device_unlock(Device *self) { try { - self->device->unlock(); + (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->unlock(); Py_RETURN_NONE; } catch(AUD_Exception& e) @@ -2387,7 +2312,7 @@ Device_get_rate(Device *self, void* nothing) { try { - AUD_DeviceSpecs specs = self->device->getSpecs(); + AUD_DeviceSpecs specs = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getSpecs(); return Py_BuildValue("i", specs.rate); } catch(AUD_Exception& e) @@ -2405,7 +2330,7 @@ Device_get_format(Device *self, void* nothing) { try { - AUD_DeviceSpecs specs = self->device->getSpecs(); + AUD_DeviceSpecs specs = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getSpecs(); return Py_BuildValue("i", specs.format); } catch(AUD_Exception& e) @@ -2423,7 +2348,7 @@ Device_get_channels(Device *self, void* nothing) { try { - AUD_DeviceSpecs specs = self->device->getSpecs(); + AUD_DeviceSpecs specs = (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getSpecs(); return Py_BuildValue("i", specs.channels); } catch(AUD_Exception& e) @@ -2441,7 +2366,7 @@ Device_get_volume(Device *self, void* nothing) { try { - return Py_BuildValue("f", self->device->getVolume()); + return Py_BuildValue("f", (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->getVolume()); } catch(AUD_Exception& e) { @@ -2460,7 +2385,7 @@ Device_set_volume(Device *self, PyObject* args, void* nothing) try { - self->device->setVolume(volume); + (*reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device))->setVolume(volume); return 0; } catch(AUD_Exception& e) @@ -2478,7 +2403,7 @@ Device_get_listener_location(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Vector3 v = device->getListenerLocation(); @@ -2507,7 +2432,7 @@ Device_set_listener_location(Device *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Vector3 location(x, y, z); @@ -2533,7 +2458,7 @@ Device_get_listener_velocity(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Vector3 v = device->getListenerVelocity(); @@ -2562,7 +2487,7 @@ Device_set_listener_velocity(Device *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Vector3 velocity(x, y, z); @@ -2588,7 +2513,7 @@ Device_get_listener_orientation(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Quaternion o = device->getListenerOrientation(); @@ -2617,7 +2542,7 @@ Device_set_listener_orientation(Device *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { AUD_Quaternion orientation(w, x, y, z); @@ -2644,7 +2569,7 @@ Device_get_speed_of_sound(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { return Py_BuildValue("f", device->getSpeedOfSound()); @@ -2672,7 +2597,7 @@ Device_set_speed_of_sound(Device *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { device->setSpeedOfSound(speed); @@ -2700,7 +2625,7 @@ Device_get_doppler_factor(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { return Py_BuildValue("f", device->getDopplerFactor()); @@ -2728,7 +2653,7 @@ Device_set_doppler_factor(Device *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { device->setDopplerFactor(factor); @@ -2754,7 +2679,7 @@ Device_get_distance_model(Device *self, void* nothing) { try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { return Py_BuildValue("i", int(device->getDistanceModel())); @@ -2782,7 +2707,7 @@ Device_set_distance_model(Device *self, PyObject* args, void* nothing) try { - AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(self->device); + AUD_I3DDevice* device = dynamic_cast<AUD_I3DDevice*>(reinterpret_cast<AUD_Reference<AUD_IDevice>*>(self->device)->get()); if(device) { device->setDistanceModel(AUD_DistanceModel(model)); @@ -2875,6 +2800,25 @@ Device_empty() return DeviceType.tp_alloc(&DeviceType, 0); } +PyObject * +Factory_empty() +{ + return FactoryType.tp_alloc(&FactoryType, 0); +} + +Factory* +checkFactory(PyObject* factory) +{ + if(!PyObject_TypeCheck(factory, &FactoryType)) + { + PyErr_SetString(PyExc_TypeError, "Object is not of type Factory!"); + return NULL; + } + + return (Factory*)factory; +} + + // ==================================================================== PyDoc_STRVAR(M_aud_doc, diff --git a/intern/audaspace/Python/AUD_PyAPI.h b/intern/audaspace/Python/AUD_PyAPI.h index 6e217b07213..e234ad4dded 100644 --- a/intern/audaspace/Python/AUD_PyAPI.h +++ b/intern/audaspace/Python/AUD_PyAPI.h @@ -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 } diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp index 17cf09efc1d..c4402e88c65 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp +++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp @@ -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); } diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.h b/intern/audaspace/SRC/AUD_SRCResampleFactory.h index 716def960fd..2f5fe30ac47 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleFactory.h +++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.h @@ -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,9 @@ private: AUD_SRCResampleFactory& operator=(const AUD_SRCResampleFactory&); public: - AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_SRCResampleFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader(); }; #endif //AUD_SRCRESAMPLEFACTORY diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp index 1026514a9b8..a72d8ba393b 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp +++ b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp @@ -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; + + int length = m_buffer.getSize() / AUD_SAMPLE_SIZE(specs); - m_reader->read(length, buffer); + *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(); + + double factor = double(m_rate) / double(specs.rate); - if(m_buffer.getSize() < size) - m_buffer.resize(size); + specs.rate = m_rate; - buffer = m_buffer.getBuffer(); + int size = length; - length = src_callback_read(m_src, m_factor, length, buffer); + 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); } diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.h b/intern/audaspace/SRC/AUD_SRCResampleReader.h index 27019c0ed9f..dddfeb6a452 100644 --- a/intern/audaspace/SRC/AUD_SRCResampleReader.h +++ b/intern/audaspace/SRC/AUD_SRCResampleReader.h @@ -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 diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp index 38de3e8867a..909f41302d7 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp @@ -46,13 +46,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); } diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h index 12687402fb6..af95e3a3b81 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.h @@ -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 diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp index 4597432e7d1..b7690d55383 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp @@ -255,12 +255,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 +276,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 +341,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 +382,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 +391,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 +399,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 +416,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 +432,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; } diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h index 26e66859451..06d6fe1e5f6 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h @@ -61,11 +61,6 @@ private: int m_position; /** - * The playback buffer. - */ - AUD_Buffer m_buffer; - - /** * The specification of the audio data. */ AUD_DeviceSpecs m_specs; @@ -167,7 +162,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 diff --git a/intern/audaspace/fftw/AUD_BandPassReader.cpp b/intern/audaspace/fftw/AUD_BandPassReader.cpp index 06f0a2af0ad..22c65b18d76 100644 --- a/intern/audaspace/fftw/AUD_BandPassReader.cpp +++ b/intern/audaspace/fftw/AUD_BandPassReader.cpp @@ -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) { diff --git a/intern/audaspace/intern/AUD_3DMath.h b/intern/audaspace/intern/AUD_3DMath.h index fc095ebaca7..3a6abf811ce 100644 --- a/intern/audaspace/intern/AUD_3DMath.h +++ b/intern/audaspace/intern/AUD_3DMath.h @@ -32,15 +32,16 @@ #ifndef AUD_3DMATH #define AUD_3DMATH -class AUD_Quaternion +#include <cmath> + +class AUD_Vector3 { private: union { - float m_v[4]; + float m_v[3]; struct { - float m_w; float m_x; float m_y; float m_z; @@ -49,28 +50,18 @@ private: public: /** - * Creates a new quaternion. - * \param w The w component. + * Creates a new 3 dimensional vector. * \param x The x component. * \param y The y component. * \param z The z component. */ - inline AUD_Quaternion(float w, float x, float y, float z) : - m_w(w), m_x(x), m_y(y), m_z(z) - { - } - - /** - * Retrieves the w component of the quarternion. - * \return The w component. - */ - inline const float& w() const + inline AUD_Vector3(float x = 0, float y = 0, float z = 0) : + m_x(x), m_y(y), m_z(z) { - return m_w; } /** - * Retrieves the x component of the quarternion. + * Retrieves the x component of the vector. * \return The x component. */ inline const float& x() const @@ -79,7 +70,7 @@ public: } /** - * Retrieves the y component of the quarternion. + * Retrieves the y component of the vector. * \return The y component. */ inline const float& y() const @@ -88,7 +79,7 @@ public: } /** - * Retrieves the z component of the quarternion. + * Retrieves the z component of the vector. * \return The z component. */ inline const float& z() const @@ -98,34 +89,80 @@ public: /** * Retrieves the components of the vector. - * \param destination Where the 4 float values should be saved to. + * \param destination Where the 3 float values should be saved to. */ inline void get(float* destination) const { - destination[0] = m_w; - destination[1] = m_x; - destination[2] = m_y; - destination[3] = m_z; + destination[0] = m_x; + destination[1] = m_y; + destination[2] = m_z; } /** * Retrieves the components of the vector. - * \return The components as float[4]. + * \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); + } + + 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; + } + + inline AUD_Vector3 operator*(const float& op) const + { + return AUD_Vector3(m_x * op, m_y * op, m_z * op); + } + + 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); + } + + 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); + } + + inline AUD_Vector3 operator-() const + { + return AUD_Vector3(-m_x, -m_y, -m_z); + } }; -class AUD_Vector3 +class AUD_Quaternion { private: union { - float m_v[3]; + float m_v[4]; struct { + float m_w; float m_x; float m_y; float m_z; @@ -134,18 +171,28 @@ private: public: /** - * Creates a new 3 dimensional vector. + * Creates a new quaternion. + * \param w The w component. * \param x The x component. * \param y The y component. * \param z The z component. */ - inline AUD_Vector3(float x, float y, float z) : - m_x(x), m_y(y), m_z(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) { } /** - * Retrieves the x component of the vector. + * Retrieves the w component of the quarternion. + * \return The w component. + */ + inline const float& w() const + { + return m_w; + } + + /** + * Retrieves the x component of the quarternion. * \return The x component. */ inline const float& x() const @@ -154,7 +201,7 @@ public: } /** - * Retrieves the y component of the vector. + * Retrieves the y component of the quarternion. * \return The y component. */ inline const float& y() const @@ -163,7 +210,7 @@ public: } /** - * Retrieves the z component of the vector. + * Retrieves the z component of the quarternion. * \return The z component. */ inline const float& z() const @@ -173,23 +220,38 @@ public: /** * Retrieves the components of the vector. - * \param destination Where the 3 float values should be saved to. + * \param destination Where the 4 float values should be saved to. */ inline void get(float* destination) const { - destination[0] = m_x; - destination[1] = m_y; - destination[2] = m_z; + destination[0] = m_w; + destination[1] = m_x; + destination[2] = m_y; + destination[3] = m_z; } /** * Retrieves the components of the vector. - * \return The components as float[3]. + * \return The components as float[4]. */ inline const float* get() const { return m_v; } + + 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); + } + + inline AUD_Vector3 getUp() const + { + 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)); + } }; #endif //AUD_3DMATH diff --git a/intern/audaspace/intern/AUD_Buffer.cpp b/intern/audaspace/intern/AUD_Buffer.cpp index 37c05fd1cc0..43955b54988 100644 --- a/intern/audaspace/intern/AUD_Buffer.cpp +++ b/intern/audaspace/intern/AUD_Buffer.cpp @@ -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); +} diff --git a/intern/audaspace/intern/AUD_Buffer.h b/intern/audaspace/intern/AUD_Buffer.h index 9b199d82fbb..4a37bc17464 100644 --- a/intern/audaspace/intern/AUD_Buffer.h +++ b/intern/audaspace/intern/AUD_Buffer.h @@ -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 diff --git a/intern/audaspace/intern/AUD_BufferReader.cpp b/intern/audaspace/intern/AUD_BufferReader.cpp index 78111ba104c..99a99069378 100644 --- a/intern/audaspace/intern/AUD_BufferReader.cpp +++ b/intern/audaspace/intern/AUD_BufferReader.cpp @@ -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); } diff --git a/intern/audaspace/intern/AUD_BufferReader.h b/intern/audaspace/intern/AUD_BufferReader.h index 3369672703c..5ba6c503855 100644 --- a/intern/audaspace/intern/AUD_BufferReader.h +++ b/intern/audaspace/intern/AUD_BufferReader.h @@ -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 diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp index 0119bb105d8..db76b9b4faf 100644 --- a/intern/audaspace/intern/AUD_C-API.cpp +++ b/intern/audaspace/intern/AUD_C-API.cpp @@ -37,9 +37,6 @@ #ifdef WITH_PYTHON #include "AUD_PyInit.h" #include "AUD_PyAPI.h" - -Device* g_device; -bool g_pyinitialized = false; #endif #include <cstdlib> @@ -48,6 +45,7 @@ bool g_pyinitialized = false; #include "AUD_NULLDevice.h" #include "AUD_I3DDevice.h" +#include "AUD_I3DHandle.h" #include "AUD_FileFactory.h" #include "AUD_StreamBufferFactory.h" #include "AUD_DelayFactory.h" @@ -90,9 +88,10 @@ extern "C" { #include <cassert> -typedef AUD_IFactory AUD_Sound; -typedef AUD_ReadDevice AUD_Device; -typedef AUD_Handle AUD_Channel; +typedef AUD_Reference<AUD_IFactory> AUD_Sound; +typedef AUD_Reference<AUD_ReadDevice> AUD_Device; +typedef AUD_Reference<AUD_IHandle> AUD_Handle; +typedef AUD_Reference<AUD_SequencerEntry> AUD_SEntry; #define AUD_CAPI_IMPLEMENTATION #include "AUD_C-API.h" @@ -101,8 +100,8 @@ typedef AUD_Handle AUD_Channel; #define NULL 0 #endif -static AUD_IDevice* AUD_device = NULL; -static AUD_I3DDevice* AUD_3ddevice = NULL; +static AUD_Reference<AUD_IDevice> AUD_device; +static AUD_I3DDevice* AUD_3ddevice; void AUD_initOnce() { @@ -113,9 +112,9 @@ void AUD_initOnce() int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) { - AUD_IDevice* dev = NULL; + AUD_Reference<AUD_IDevice> dev = NULL; - if(AUD_device) + if(!AUD_device.isNull()) AUD_exit(); try @@ -145,18 +144,7 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) } AUD_device = dev; - AUD_3ddevice = dynamic_cast<AUD_I3DDevice*>(AUD_device); - -#ifdef WITH_PYTHON - if(g_pyinitialized) - { - g_device = (Device*)Device_empty(); - if(g_device != NULL) - { - g_device->device = dev; - } - } -#endif + AUD_3ddevice = dynamic_cast<AUD_I3DDevice*>(AUD_device.get()); return true; } @@ -168,16 +156,6 @@ int AUD_init(AUD_DeviceType device, AUD_DeviceSpecs specs, int buffersize) void AUD_exit() { -#ifdef WITH_PYTHON - if(g_device) - { - Py_XDECREF(g_device); - g_device = NULL; - } - else -#endif - if(AUD_device) - delete AUD_device; AUD_device = NULL; AUD_3ddevice = NULL; } @@ -185,11 +163,16 @@ void AUD_exit() #ifdef WITH_PYTHON static PyObject* AUD_getCDevice(PyObject* self) { - if(g_device) + if(!AUD_device.isNull()) { - Py_INCREF(g_device); - return (PyObject*)g_device; + Device* device = (Device*)Device_empty(); + if(device != NULL) + { + device->device = new AUD_Reference<AUD_IDevice>(AUD_device); + return (PyObject*)device; + } } + Py_RETURN_NONE; } @@ -199,34 +182,87 @@ static PyMethodDef meth_getcdevice[] = {{ "device", (PyCFunction)AUD_getCDevice, ":return: The application's :class:`Device`.\n" ":rtype: :class:`Device`"}}; +extern "C" { +extern void* sound_get_factory(void* sound); +} + +static PyObject* AUD_getSoundFromPointer(PyObject* self, PyObject* args) +{ + long int lptr; + + if(PyArg_Parse(args, "l:_sound_from_pointer", &lptr)) + { + if(lptr) + { + AUD_Reference<AUD_IFactory>* factory = (AUD_Reference<AUD_IFactory>*) sound_get_factory((void*) lptr); + + if(factory) + { + Factory* obj = (Factory*) Factory_empty(); + if(obj) + { + obj->factory = new AUD_Reference<AUD_IFactory>(*factory); + return (PyObject*) obj; + } + } + } + } + + Py_RETURN_NONE; +} + +static PyMethodDef meth_sound_from_pointer[] = {{ "_sound_from_pointer", (PyCFunction)AUD_getSoundFromPointer, METH_O, + "_sound_from_pointer(pointer)\n\n" + "Returns the corresponding :class:`Factory` object.\n\n" + ":arg pointer: The pointer to the bSound object as long.\n" + ":type pointer: long\n" + ":return: The corresponding :class:`Factory` object.\n" + ":rtype: :class:`Factory`"}}; + PyObject* AUD_initPython() { PyObject* module = PyInit_aud(); - PyModule_AddObject(module, "device", (PyObject *)PyCFunction_New(meth_getcdevice, NULL)); + PyModule_AddObject(module, "device", (PyObject*)PyCFunction_New(meth_getcdevice, NULL)); + PyModule_AddObject(module, "_sound_from_pointer", (PyObject*)PyCFunction_New(meth_sound_from_pointer, NULL)); PyDict_SetItemString(PyImport_GetModuleDict(), "aud", module); - if(AUD_device) + + return module; +} + +PyObject* AUD_getPythonFactory(AUD_Sound* sound) +{ + if(sound) { - g_device = (Device*)Device_empty(); - if(g_device != NULL) + Factory* obj = (Factory*) Factory_empty(); + if(obj) { - g_device->device = AUD_device; + obj->factory = new AUD_Reference<AUD_IFactory>(*sound); + return (PyObject*) obj; } } - g_pyinitialized = true; - return module; + return NULL; +} + +AUD_Sound* AUD_getPythonSound(PyObject* sound) +{ + Factory* factory = checkFactory(sound); + + if(!factory) + return NULL; + + return new AUD_Reference<AUD_IFactory>(*reinterpret_cast<AUD_Reference<AUD_IFactory>*>(factory->factory)); } + #endif void AUD_lock() { - assert(AUD_device); AUD_device->lock(); } void AUD_unlock() { - assert(AUD_device); AUD_device->unlock(); } @@ -241,13 +277,12 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound* sound) try { - AUD_IReader* reader = sound->createReader(); + AUD_Reference<AUD_IReader> reader = (*sound)->createReader(); - if(reader) + if(!reader.isNull()) { info.specs = reader->getSpecs(); info.length = reader->getLength() / (float) info.specs.rate; - delete reader; } } catch(AUD_Exception&) @@ -260,13 +295,13 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound* sound) AUD_Sound* AUD_load(const char* filename) { assert(filename); - return new AUD_FileFactory(filename); + return new AUD_Sound(new AUD_FileFactory(filename)); } AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size) { assert(buffer); - return new AUD_FileFactory(buffer, size); + return new AUD_Sound(new AUD_FileFactory(buffer, size)); } AUD_Sound* AUD_bufferSound(AUD_Sound* sound) @@ -275,7 +310,7 @@ AUD_Sound* AUD_bufferSound(AUD_Sound* sound) try { - return new AUD_StreamBufferFactory(sound); + return new AUD_Sound(new AUD_StreamBufferFactory(*sound)); } catch(AUD_Exception&) { @@ -289,7 +324,7 @@ AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay) try { - return new AUD_DelayFactory(sound, delay); + return new AUD_Sound(new AUD_DelayFactory(*sound, delay)); } catch(AUD_Exception&) { @@ -303,7 +338,7 @@ AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end) try { - return new AUD_LimiterFactory(sound, start, end); + return new AUD_Sound(new AUD_LimiterFactory(*sound, start, end)); } catch(AUD_Exception&) { @@ -317,7 +352,7 @@ AUD_Sound* AUD_pingpongSound(AUD_Sound* sound) try { - return new AUD_PingPongFactory(sound); + return new AUD_Sound(new AUD_PingPongFactory(*sound)); } catch(AUD_Exception&) { @@ -331,7 +366,7 @@ AUD_Sound* AUD_loopSound(AUD_Sound* sound) try { - return new AUD_LoopFactory(sound); + return new AUD_Sound(new AUD_LoopFactory(*sound)); } catch(AUD_Exception&) { @@ -339,18 +374,18 @@ AUD_Sound* AUD_loopSound(AUD_Sound* sound) } } -int AUD_setLoop(AUD_Channel* handle, int loops) +int AUD_setLoop(AUD_Handle* handle, int loops) { - if(handle) + assert(handle); + + try + { + return (*handle)->setLoopCount(loops); + } + catch(AUD_Exception&) { - try - { - return AUD_device->setLoopCount(handle, loops); - } - catch(AUD_Exception&) - { - } } + return false; } @@ -360,7 +395,7 @@ AUD_Sound* AUD_rectifySound(AUD_Sound* sound) try { - return new AUD_RectifyFactory(sound); + return new AUD_Sound(new AUD_RectifyFactory(*sound)); } catch(AUD_Exception&) { @@ -374,67 +409,67 @@ void AUD_unload(AUD_Sound* sound) delete sound; } -AUD_Channel* AUD_play(AUD_Sound* sound, int keep) +AUD_Handle* AUD_play(AUD_Sound* sound, int keep) { - assert(AUD_device); assert(sound); try { - return AUD_device->play(sound, keep); + AUD_Handle handle = AUD_device->play(*sound, keep); + if(!handle.isNull()) + return new AUD_Handle(handle); } catch(AUD_Exception&) { - return NULL; } + return NULL; } -int AUD_pause(AUD_Channel* handle) +int AUD_pause(AUD_Handle* handle) { - assert(AUD_device); - return AUD_device->pause(handle); + assert(handle); + return (*handle)->pause(); } -int AUD_resume(AUD_Channel* handle) +int AUD_resume(AUD_Handle* handle) { - assert(AUD_device); - return AUD_device->resume(handle); + assert(handle); + return (*handle)->resume(); } -int AUD_stop(AUD_Channel* handle) +int AUD_stop(AUD_Handle* handle) { - if(AUD_device) - return AUD_device->stop(handle); - return false; + assert(handle); + int result = (*handle)->stop(); + delete handle; + return result; } -int AUD_setKeep(AUD_Channel* handle, int keep) +int AUD_setKeep(AUD_Handle* handle, int keep) { - assert(AUD_device); - return AUD_device->setKeep(handle, keep); + assert(handle); + return (*handle)->setKeep(keep); } -int AUD_seek(AUD_Channel* handle, float seekTo) +int AUD_seek(AUD_Handle* handle, float seekTo) { - assert(AUD_device); - return AUD_device->seek(handle, seekTo); + assert(handle); + return (*handle)->seek(seekTo); } -float AUD_getPosition(AUD_Channel* handle) +float AUD_getPosition(AUD_Handle* handle) { - assert(AUD_device); - return AUD_device->getPosition(handle); + assert(handle); + return (*handle)->getPosition(); } -AUD_Status AUD_getStatus(AUD_Channel* handle) +AUD_Status AUD_getStatus(AUD_Handle* handle) { - assert(AUD_device); - return AUD_device->getStatus(handle); + assert(handle); + return (*handle)->getStatus(); } int AUD_setListenerLocation(const float* location) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_Vector3 v(location[0], location[1], location[2]); @@ -447,8 +482,6 @@ int AUD_setListenerLocation(const float* location) int AUD_setListenerVelocity(const float* velocity) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_Vector3 v(velocity[0], velocity[1], velocity[2]); @@ -461,8 +494,6 @@ int AUD_setListenerVelocity(const float* velocity) int AUD_setListenerOrientation(const float* orientation) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]); @@ -475,8 +506,6 @@ int AUD_setListenerOrientation(const float* orientation) int AUD_setSpeedOfSound(float speed) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_3ddevice->setSpeedOfSound(speed); @@ -488,8 +517,6 @@ int AUD_setSpeedOfSound(float speed) int AUD_setDopplerFactor(float factor) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_3ddevice->setDopplerFactor(factor); @@ -501,8 +528,6 @@ int AUD_setDopplerFactor(float factor) int AUD_setDistanceModel(AUD_DistanceModel model) { - assert(AUD_device); - if(AUD_3ddevice) { AUD_3ddevice->setDistanceModel(model); @@ -512,180 +537,184 @@ int AUD_setDistanceModel(AUD_DistanceModel model) return false; } -int AUD_setSourceLocation(AUD_Channel* handle, const float* location) +int AUD_setSourceLocation(AUD_Handle* handle, const float* location) { - assert(AUD_device); + assert(handle); + AUD_Reference<AUD_I3DHandle> h(*handle); - if(AUD_3ddevice) + if(!h.isNull()) { AUD_Vector3 v(location[0], location[1], location[2]); - return AUD_3ddevice->setSourceLocation(handle, v); + return h->setSourceLocation(v); } return false; } -int AUD_setSourceVelocity(AUD_Channel* handle, const float* velocity) +int AUD_setSourceVelocity(AUD_Handle* handle, const float* velocity) { - assert(AUD_device); + assert(handle); + AUD_Reference<AUD_I3DHandle> h(*handle); - if(AUD_3ddevice) + if(!h.isNull()) { AUD_Vector3 v(velocity[0], velocity[1], velocity[2]); - return AUD_3ddevice->setSourceVelocity(handle, v); + return h->setSourceVelocity(v); } return false; } -int AUD_setSourceOrientation(AUD_Channel* handle, const float* orientation) +int AUD_setSourceOrientation(AUD_Handle* handle, const float* orientation) { - assert(AUD_device); + assert(handle); + AUD_Reference<AUD_I3DHandle> h(*handle); - if(AUD_3ddevice) + if(!h.isNull()) { AUD_Quaternion q(orientation[3], orientation[0], orientation[1], orientation[2]); - return AUD_3ddevice->setSourceOrientation(handle, q); + return h->setSourceOrientation(q); } return false; } -int AUD_setRelative(AUD_Channel* handle, int relative) +int AUD_setRelative(AUD_Handle* handle, int relative) { - assert(AUD_device); + assert(handle); + AUD_Reference<AUD_I3DHandle> h(*handle); - if(AUD_3ddevice) + if(!h.isNull()) { - return AUD_3ddevice->setRelative(handle, relative); + return h->setRelative(relative); } return false; } -int AUD_setVolumeMaximum(AUD_Channel* handle, float volume) +int AUD_setVolumeMaximum(AUD_Handle* handle, float volume) { - assert(AUD_device); + assert(handle); + AUD_Reference<AUD_I3DHandle> h(*handle); - if(AUD_3ddevice) + if(!h.isNull()) { - return AUD_3ddevice->setVolumeMaximum(handle, volume); + return h->setVolumeMaximum(volume); } return false; } -int AUD_setVolumeMinimum(AUD_Channel* handle, float volume) +int AUD_setVolumeMinimum(AUD_Handle* handle, float volume) { - assert(AUD_device); + assert(handle); + AUD_Reference<AUD_I3DHandle> h(*handle); - if(AUD_3ddevice) + if(!h.isNull()) { - return AUD_3ddevice->setVolumeMinimum(handle, volume); + return h->setVolumeMinimum(volume); } return false; } -int AUD_setDistanceMaximum(AUD_Channel* handle, float distance) +int AUD_setDistanceMaximum(AUD_Handle* handle, float distance) { - assert(AUD_device); + assert(handle); + AUD_Reference<AUD_I3DHandle> h(*handle); - if(AUD_3ddevice) + if(!h.isNull()) { - return AUD_3ddevice->setDistanceMaximum(handle, distance); + return h->setDistanceMaximum(distance); } return false; } -int AUD_setDistanceReference(AUD_Channel* handle, float distance) +int AUD_setDistanceReference(AUD_Handle* handle, float distance) { - assert(AUD_device); + assert(handle); + AUD_Reference<AUD_I3DHandle> h(*handle); - if(AUD_3ddevice) + if(!h.isNull()) { - return AUD_3ddevice->setDistanceReference(handle, distance); + return h->setDistanceReference(distance); } return false; } -int AUD_setAttenuation(AUD_Channel* handle, float factor) +int AUD_setAttenuation(AUD_Handle* handle, float factor) { - assert(AUD_device); + assert(handle); + AUD_Reference<AUD_I3DHandle> h(*handle); - if(AUD_3ddevice) + if(!h.isNull()) { - return AUD_3ddevice->setAttenuation(handle, factor); + return h->setAttenuation(factor); } return false; } -int AUD_setConeAngleOuter(AUD_Channel* handle, float angle) +int AUD_setConeAngleOuter(AUD_Handle* handle, float angle) { - assert(AUD_device); + assert(handle); + AUD_Reference<AUD_I3DHandle> h(*handle); - if(AUD_3ddevice) + if(!h.isNull()) { - return AUD_3ddevice->setConeAngleOuter(handle, angle); + return h->setConeAngleOuter(angle); } return false; } -int AUD_setConeAngleInner(AUD_Channel* handle, float angle) +int AUD_setConeAngleInner(AUD_Handle* handle, float angle) { - assert(AUD_device); + assert(handle); + AUD_Reference<AUD_I3DHandle> h(*handle); - if(AUD_3ddevice) + if(!h.isNull()) { - return AUD_3ddevice->setConeAngleInner(handle, angle); + return h->setConeAngleInner(angle); } return false; } -int AUD_setConeVolumeOuter(AUD_Channel* handle, float volume) +int AUD_setConeVolumeOuter(AUD_Handle* handle, float volume) { - assert(AUD_device); + assert(handle); + AUD_Reference<AUD_I3DHandle> h(*handle); - if(AUD_3ddevice) + if(!h.isNull()) { - return AUD_3ddevice->setConeVolumeOuter(handle, volume); + return h->setConeVolumeOuter(volume); } return false; } -int AUD_setSoundVolume(AUD_Channel* handle, float volume) +int AUD_setSoundVolume(AUD_Handle* handle, float volume) { - if(handle) + assert(handle); + try { - assert(AUD_device); - - try - { - return AUD_device->setVolume(handle, volume); - } - catch(AUD_Exception&) {} + return (*handle)->setVolume(volume); } + catch(AUD_Exception&) {} return false; } -int AUD_setSoundPitch(AUD_Channel* handle, float pitch) +int AUD_setSoundPitch(AUD_Handle* handle, float pitch) { - if(handle) + assert(handle); + try { - assert(AUD_device); - - try - { - return AUD_device->setPitch(handle, pitch); - } - catch(AUD_Exception&) {} + return (*handle)->setPitch(pitch); } + catch(AUD_Exception&) {} return false; } @@ -693,7 +722,7 @@ AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs) { try { - return new AUD_ReadDevice(specs); + return new AUD_Device(new AUD_ReadDevice(specs)); } catch(AUD_Exception&) { @@ -701,21 +730,24 @@ AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs) } } -AUD_Channel* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek) +AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek) { assert(device); assert(sound); try { - AUD_Channel* handle = device->play(sound); - device->seek(handle, seek); - return handle; + AUD_Handle handle = (*device)->play(*sound); + if(!handle.isNull()) + { + handle->seek(seek); + return new AUD_Handle(handle); + } } catch(AUD_Exception&) { - return NULL; } + return NULL; } int AUD_setDeviceVolume(AUD_Device* device, float volume) @@ -724,7 +756,7 @@ int AUD_setDeviceVolume(AUD_Device* device, float volume) try { - device->setVolume(volume); + (*device)->setVolume(volume); return true; } catch(AUD_Exception&) {} @@ -732,22 +764,6 @@ int AUD_setDeviceVolume(AUD_Device* device, float volume) return false; } -int AUD_setDeviceSoundVolume(AUD_Device* device, AUD_Channel* handle, - float volume) -{ - if(handle) - { - assert(device); - - try - { - return device->setVolume(handle, volume); - } - catch(AUD_Exception&) {} - } - return false; -} - int AUD_readDevice(AUD_Device* device, data_t* buffer, int length) { assert(device); @@ -755,7 +771,7 @@ int AUD_readDevice(AUD_Device* device, data_t* buffer, int length) try { - return device->read(buffer, length); + return (*device)->read(buffer, length); } catch(AUD_Exception&) { @@ -779,58 +795,52 @@ void AUD_closeReadDevice(AUD_Device* device) float* AUD_readSoundBuffer(const char* filename, float low, float high, float attack, float release, float threshold, int accumulate, int additive, int square, - float sthreshold, int samplerate, int* length) + float sthreshold, double samplerate, int* length) { AUD_Buffer buffer; AUD_DeviceSpecs specs; specs.channels = AUD_CHANNELS_MONO; specs.rate = (AUD_SampleRate)samplerate; - AUD_Sound* sound; + AUD_Reference<AUD_IFactory> sound; - AUD_FileFactory file(filename); + AUD_Reference<AUD_IFactory> file = new AUD_FileFactory(filename); - AUD_IReader* reader = file.createReader(); + AUD_Reference<AUD_IReader> reader = file->createReader(); AUD_SampleRate rate = reader->getSpecs().rate; - delete reader; - AUD_ChannelMapperFactory mapper(&file, specs); - sound = &mapper; - AUD_LowpassFactory lowpass(sound, high); + sound = new AUD_ChannelMapperFactory(file, specs); + if(high < rate) - sound = &lowpass; - AUD_HighpassFactory highpass(sound, low); + sound = new AUD_LowpassFactory(sound, high); if(low > 0) - sound = &highpass; - AUD_EnvelopeFactory envelope(sound, attack, release, threshold, 0.1f); - AUD_LinearResampleFactory resampler(&envelope, specs); - sound = &resampler; - AUD_SquareFactory squaref(sound, sthreshold); + sound = new AUD_HighpassFactory(sound, low);; + + sound = new AUD_EnvelopeFactory(sound, attack, release, threshold, 0.1f); + sound = new AUD_LinearResampleFactory(sound, specs); + if(square) - sound = &squaref; - AUD_AccumulatorFactory accumulator(sound, additive); - AUD_SumFactory sum(sound); + sound = new AUD_SquareFactory(sound, sthreshold); + if(accumulate) - sound = &accumulator; + sound = new AUD_AccumulatorFactory(sound, additive); else if(additive) - sound = ∑ + sound = new AUD_SumFactory(sound); reader = sound->createReader(); - if(reader == NULL) + if(reader.isNull()) return NULL; int len; int position = 0; - sample_t* readbuffer; + bool eos; do { len = samplerate; buffer.resize((position + len) * sizeof(float), true); - reader->read(len, readbuffer); - memcpy(buffer.getBuffer() + position, readbuffer, len * sizeof(float)); + reader->read(len, eos, buffer.getBuffer() + position); position += len; - } while(len != 0); - delete reader; + } while(!eos); float* result = (float*)malloc(position * sizeof(float)); memcpy(result, buffer.getBuffer(), position * sizeof(float)); @@ -838,100 +848,121 @@ float* AUD_readSoundBuffer(const char* filename, float low, float high, return result; } -static void pauseSound(AUD_Channel* handle) +static void pauseSound(AUD_Handle* handle) { - assert(AUD_device); - - AUD_device->pause(handle); + assert(handle); + (*handle)->pause(); } -AUD_Channel* AUD_pauseAfter(AUD_Channel* handle, float seconds) +AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds) { - assert(AUD_device); + AUD_Reference<AUD_IFactory> silence = new AUD_SilenceFactory; + AUD_Reference<AUD_IFactory> limiter = new AUD_LimiterFactory(silence, 0, seconds); - AUD_SilenceFactory silence; - AUD_LimiterFactory limiter(&silence, 0, seconds); + AUD_device->lock(); try { - AUD_Channel* channel = AUD_device->play(&limiter); - AUD_device->setStopCallback(channel, (stopCallback)pauseSound, handle); - return channel; + AUD_Handle handle2 = AUD_device->play(limiter); + if(!handle2.isNull()) + { + handle2->setStopCallback((stopCallback)pauseSound, handle); + AUD_device->unlock(); + return new AUD_Handle(handle2); + } } catch(AUD_Exception&) { - return NULL; } + + AUD_device->unlock(); + + return NULL; } AUD_Sound* AUD_createSequencer(int muted, void* data, AUD_volumeFunction volume) { -/* AUD_XXX should be this: but AUD_createSequencer is called before the device - * is initialized. - - return new AUD_SequencerFactory(AUD_device->getSpecs().specs, data, volume); -*/ + // specs are changed at a later point! AUD_Specs specs; specs.channels = AUD_CHANNELS_STEREO; specs.rate = AUD_RATE_44100; - return new AUD_SequencerFactory(specs, muted, data, volume); + AUD_Reference<AUD_SequencerFactory>* sequencer = new AUD_Reference<AUD_SequencerFactory>(new AUD_SequencerFactory(specs, muted, data, volume)); + return reinterpret_cast<AUD_Sound*>(sequencer); } void AUD_destroySequencer(AUD_Sound* sequencer) { - delete ((AUD_SequencerFactory*)sequencer); + delete sequencer; } void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted) { - ((AUD_SequencerFactory*)sequencer)->mute(muted); + ((AUD_SequencerFactory*)sequencer->get())->mute(muted); } -AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound, +AUD_Reference<AUD_SequencerEntry>* AUD_addSequencer(AUD_Sound* sequencer, AUD_Sound** sound, float begin, float end, float skip, void* data) { - return ((AUD_SequencerFactory*)sequencer)->add((AUD_IFactory**) sound, begin, end, skip, data); + return new AUD_Reference<AUD_SequencerEntry>(((AUD_SequencerFactory*)sequencer->get())->add(sound, begin, end, skip, data)); } -void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry) +void AUD_removeSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry) { - ((AUD_SequencerFactory*)sequencer)->remove(entry); + ((AUD_SequencerFactory*)sequencer->get())->remove(*entry); + delete entry; } -void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, +void AUD_moveSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry, float begin, float end, float skip) { - ((AUD_SequencerFactory*)sequencer)->move(entry, begin, end, skip); + ((AUD_SequencerFactory*)sequencer->get())->move(*entry, begin, end, skip); +} + +void AUD_muteSequencer(AUD_Sound* sequencer, AUD_Reference<AUD_SequencerEntry>* entry, char mute) +{ + ((AUD_SequencerFactory*)sequencer->get())->mute(*entry, mute); +} + +void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer) +{ + ((AUD_SequencerFactory*)sequencer->get())->setSpecs(AUD_device->getSpecs().specs); } -void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, char mute) +void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs) { - ((AUD_SequencerFactory*)sequencer)->mute(entry, mute); + ((AUD_SequencerFactory*)sequencer->get())->setSpecs(specs); } int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length) { AUD_DeviceSpecs specs; sample_t* buf; + AUD_Buffer aBuffer; specs.rate = AUD_RATE_INVALID; specs.channels = AUD_CHANNELS_MONO; specs.format = AUD_FORMAT_INVALID; - AUD_ChannelMapperFactory mapper(sound, specs); - - AUD_IReader* reader = mapper.createReader(); + AUD_Reference<AUD_IReader> reader = AUD_ChannelMapperFactory(*sound, specs).createReader(); int len = reader->getLength(); float samplejump = (float)len / (float)length; float min, max; + bool eos; for(int i = 0; i < length; i++) { len = floor(samplejump * (i+1)) - floor(samplejump * i); - reader->read(len, buf); - if(len < 1) + if(aBuffer.getSize() < len * AUD_SAMPLE_SIZE(reader->getSpecs())) + { + aBuffer.resize(len * AUD_SAMPLE_SIZE(reader->getSpecs())); + buf = aBuffer.getBuffer(); + } + + reader->read(len, eos, buf); + + if(eos) { length = i; break; @@ -949,15 +980,13 @@ int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length) } } - delete reader; - return length; } void AUD_startPlayback() { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); + AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get()); if(device) device->startPlayback(); #endif @@ -966,42 +995,44 @@ void AUD_startPlayback() void AUD_stopPlayback() { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); + AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get()); if(device) device->stopPlayback(); #endif } -void AUD_seekSequencer(AUD_Channel* handle, float time) +void AUD_seekSequencer(AUD_Handle* handle, float time) { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); + AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get()); if(device) device->seekPlayback(time); else #endif { - AUD_device->seek(handle, time); + assert(handle); + (*handle)->seek(time); } } -float AUD_getSequencerPosition(AUD_Channel* handle) +float AUD_getSequencerPosition(AUD_Handle* handle) { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); + AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get()); if(device) return device->getPlaybackPosition(); else #endif { - return AUD_device->getPosition(handle); + assert(handle); + return (*handle)->getPosition(); } } #ifdef WITH_JACK void AUD_setSyncCallback(AUD_syncFunction function, void* data) { - AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); + AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get()); if(device) device->setSyncCallback(function, data); } @@ -1010,9 +1041,19 @@ void AUD_setSyncCallback(AUD_syncFunction function, void* data) int AUD_doesPlayback() { #ifdef WITH_JACK - AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device); + AUD_JackDevice* device = dynamic_cast<AUD_JackDevice*>(AUD_device.get()); if(device) return device->doesPlayback(); #endif return -1; } + +AUD_Sound* AUD_copy(AUD_Sound* sound) +{ + return new AUD_Reference<AUD_IFactory>(*sound); +} + +void AUD_freeHandle(AUD_Handle* handle) +{ + delete handle; +} diff --git a/intern/audaspace/intern/AUD_C-API.h b/intern/audaspace/intern/AUD_C-API.h index b2242f09547..72d423e847b 100644 --- a/intern/audaspace/intern/AUD_C-API.h +++ b/intern/audaspace/intern/AUD_C-API.h @@ -31,6 +31,10 @@ #ifndef AUD_CAPI #define AUD_CAPI +#ifdef WITH_PYTHON +#include "Python.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -53,9 +57,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 @@ -155,7 +159,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 +181,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 +211,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 +219,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 +227,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 +281,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 +289,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 +297,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 +306,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 +314,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 +322,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 +332,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 +340,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 +349,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 +357,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 +365,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 +375,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 +383,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 +391,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 +415,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 +441,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,7 +450,7 @@ 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); @@ -465,26 +458,30 @@ extern void AUD_destroySequencer(AUD_Sound* sequencer); extern void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted); -extern AUD_SequencerEntry* AUD_addSequencer(AUD_Sound** sequencer, AUD_Sound* sound, +extern AUD_SEntry* AUD_addSequencer(AUD_Sound* sequencer, AUD_Sound** sound, float begin, float end, float skip, void* data); -extern void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry); +extern void AUD_removeSequencer(AUD_Sound* sequencer, AUD_SEntry* entry); -extern void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, +extern void AUD_moveSequencer(AUD_Sound* sequencer, AUD_SEntry* entry, float begin, float end, float skip); -extern void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SequencerEntry* entry, +extern void AUD_muteSequencer(AUD_Sound* sequencer, AUD_SEntry* entry, char mute); +extern void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer); + +extern void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs); + extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length); extern void AUD_startPlayback(void); extern void AUD_stopPlayback(void); -extern void AUD_seekSequencer(AUD_Channel* handle, float time); +extern void AUD_seekSequencer(AUD_Handle* handle, float time); -extern float AUD_getSequencerPosition(AUD_Channel* handle); +extern float AUD_getSequencerPosition(AUD_Handle* handle); #ifdef WITH_JACK extern void AUD_setSyncCallback(AUD_syncFunction function, void* data); @@ -492,6 +489,16 @@ extern void AUD_setSyncCallback(AUD_syncFunction function, void* data); extern int AUD_doesPlayback(void); +extern AUD_Sound* AUD_copy(AUD_Sound* sound); + +extern void AUD_freeHandle(AUD_Handle* channel); + +#ifdef WITH_PYTHON +extern PyObject* AUD_getPythonFactory(AUD_Sound* sound); + +extern AUD_Sound* AUD_getPythonSound(PyObject* sound); +#endif + #ifdef __cplusplus } #endif diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp index b474fbad444..ea6c738cb58 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp @@ -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); } diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.h b/intern/audaspace/intern/AUD_ChannelMapperFactory.h index 9d622f5e322..ce43c6462de 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperFactory.h +++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.h @@ -41,33 +41,14 @@ 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. - */ - float** getMapping(int ic); - - /** - * Deletes the current channel mapping. - */ - void deleteMapping(int ic); + AUD_ChannelMapperFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader(); }; #endif //AUD_CHANNELMAPPERFACTORY diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp index dec70aaecf6..27d10ce6dc8 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp +++ b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp @@ -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); +AUD_ChannelMapperReader::~AUD_ChannelMapperReader() +{ + delete[] m_mapping; +} - m_mapping = new float*[channels]; - m_specs.channels = (AUD_Channels)channels; +void AUD_ChannelMapperReader::setChannels(AUD_Channels channels) +{ + m_target_channels = channels; + calculateMapping(); +} - float sum; - int i; +void AUD_ChannelMapperReader::setMonoAngle(float angle) +{ + if(angle != angle) + angle = 0; + m_mono_angle = angle; + if(m_source_channels == AUD_CHANNELS_MONO) + calculateMapping(); +} - 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; - } +float AUD_ChannelMapperReader::angleDistance(float alpha, float beta) +{ + alpha = fabs(alpha - beta); + + if(alpha > M_PI) + alpha = fabs(alpha - 2 * M_PI); + + return alpha; } -AUD_ChannelMapperReader::~AUD_ChannelMapperReader() +void AUD_ChannelMapperReader::calculateMapping() { - int channels = m_specs.channels; + if(m_map_size < m_source_channels * m_target_channels) + { + delete[] m_mapping; + m_mapping = new float[m_source_channels * m_target_channels]; + m_map_size = m_source_channels * m_target_channels; + } + + 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]; - while(channels--) + int lfe = -1; + + for(int i = 0; i < m_target_channels; i++) { - delete[] m_mapping[channels]; + if(target_channels[i] == AUD_CHANNEL_LFE) + { + lfe = i; + break; + } } - delete[] m_mapping; + 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 +}; diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.h b/intern/audaspace/intern/AUD_ChannelMapperReader.h index 091ed06db15..fa035531763 100644 --- a/intern/audaspace/intern/AUD_ChannelMapperReader.h +++ b/intern/audaspace/intern/AUD_ChannelMapperReader.h @@ -43,44 +43,88 @@ 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(); + void setChannels(AUD_Channels channels); + + 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 diff --git a/intern/audaspace/intern/AUD_ConverterFactory.cpp b/intern/audaspace/intern/AUD_ConverterFactory.cpp index cce0f273616..bf9a3586616 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.cpp +++ b/intern/audaspace/intern/AUD_ConverterFactory.cpp @@ -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); diff --git a/intern/audaspace/intern/AUD_ConverterFactory.h b/intern/audaspace/intern/AUD_ConverterFactory.h index b9eac94de40..8f0221addb7 100644 --- a/intern/audaspace/intern/AUD_ConverterFactory.h +++ b/intern/audaspace/intern/AUD_ConverterFactory.h @@ -46,9 +46,9 @@ private: AUD_ConverterFactory& operator=(const AUD_ConverterFactory&); public: - AUD_ConverterFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_ConverterFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader(); }; #endif //AUD_CONVERTERFACTORY diff --git a/intern/audaspace/intern/AUD_ConverterFunctions.cpp b/intern/audaspace/intern/AUD_ConverterFunctions.cpp index d3cc9fa8202..c45fde72b1b 100644 --- a/intern/audaspace/intern/AUD_ConverterFunctions.cpp +++ b/intern/audaspace/intern/AUD_ConverterFunctions.cpp @@ -45,13 +45,13 @@ void AUD_convert_u8_s16(data_t* target, data_t* source, int length) { int16_t* t = (int16_t*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) t[i] = (((int16_t)source[i]) - AUD_U8_0) << 8; } void AUD_convert_u8_s24_be(data_t* target, data_t* source, int length) { - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) { target[i*3] = source[i] - AUD_U8_0; target[i*3+1] = 0; @@ -61,7 +61,7 @@ void AUD_convert_u8_s24_be(data_t* target, data_t* source, int length) void AUD_convert_u8_s24_le(data_t* target, data_t* source, int length) { - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) { target[i*3+2] = source[i] - AUD_U8_0; target[i*3+1] = 0; @@ -72,21 +72,21 @@ void AUD_convert_u8_s24_le(data_t* target, data_t* source, int length) void AUD_convert_u8_s32(data_t* target, data_t* source, int length) { int32_t* t = (int32_t*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) t[i] = (((int32_t)source[i]) - AUD_U8_0) << 24; } void AUD_convert_u8_float(data_t* target, data_t* source, int length) { float* t = (float*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((float)AUD_U8_0); } void AUD_convert_u8_double(data_t* target, data_t* source, int length) { double* t = (double*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((double)AUD_U8_0); } @@ -100,10 +100,12 @@ void AUD_convert_s16_u8(data_t* target, data_t* source, int length) void AUD_convert_s16_s24_be(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; - for(int i = 0; i < length; i++) + int16_t t; + for(int i = length - 1; i >= 0; i--) { - target[i*3] = s[i] >> 8 & 0xFF; - target[i*3+1] = s[i] & 0xFF; + t = s[i]; + target[i*3] = t >> 8 & 0xFF; + target[i*3+1] = t & 0xFF; target[i*3+2] = 0; } } @@ -111,10 +113,12 @@ void AUD_convert_s16_s24_be(data_t* target, data_t* source, int length) void AUD_convert_s16_s24_le(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; - for(int i = 0; i < length; i++) + int16_t t; + for(int i = length - 1; i >= 0; i--) { - target[i*3+2] = s[i] >> 8 & 0xFF; - target[i*3+1] = s[i] & 0xFF; + t = s[i]; + target[i*3+2] = t >> 8 & 0xFF; + target[i*3+1] = t & 0xFF; target[i*3] = 0; } } @@ -123,7 +127,7 @@ void AUD_convert_s16_s32(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; int32_t* t = (int32_t*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) t[i] = ((int32_t)s[i]) << 16; } @@ -131,7 +135,7 @@ void AUD_convert_s16_float(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; float* t = (float*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) t[i] = s[i] / AUD_S16_FLT; } @@ -139,7 +143,7 @@ void AUD_convert_s16_double(data_t* target, data_t* source, int length) { int16_t* s = (int16_t*) source; double* t = (double*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) t[i] = s[i] / AUD_S16_FLT; } @@ -177,14 +181,14 @@ void AUD_convert_s24_s24(data_t* target, data_t* source, int length) void AUD_convert_s24_s32_be(data_t* target, data_t* source, int length) { int32_t* t = (int32_t*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) t[i] = source[i*3] << 24 | source[i*3+1] << 16 | source[i*3+2] << 8; } void AUD_convert_s24_s32_le(data_t* target, data_t* source, int length) { int32_t* t = (int32_t*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) t[i] = source[i*3+2] << 24 | source[i*3+1] << 16 | source[i*3] << 8; } @@ -192,7 +196,7 @@ void AUD_convert_s24_float_be(data_t* target, data_t* source, int length) { float* t = (float*) target; int32_t s; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) { s = source[i*3] << 24 | source[i*3+1] << 16 | source[i*3+2] << 8; t[i] = s / AUD_S32_FLT; @@ -203,7 +207,7 @@ void AUD_convert_s24_float_le(data_t* target, data_t* source, int length) { float* t = (float*) target; int32_t s; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) { s = source[i*3+2] << 24 | source[i*3+1] << 16 | source[i*3] << 8; t[i] = s / AUD_S32_FLT; @@ -214,7 +218,7 @@ void AUD_convert_s24_double_be(data_t* target, data_t* source, int length) { double* t = (double*) target; int32_t s; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) { s = source[i*3] << 24 | source[i*3+1] << 16 | source[i*3+2] << 8; t[i] = s / AUD_S32_FLT; @@ -225,7 +229,7 @@ void AUD_convert_s24_double_le(data_t* target, data_t* source, int length) { double* t = (double*) target; int32_t s; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) { s = source[i*3+2] << 24 | source[i*3+1] << 16 | source[i*3] << 8; t[i] = s / AUD_S32_FLT; @@ -250,22 +254,26 @@ void AUD_convert_s32_s16(data_t* target, data_t* source, int length) void AUD_convert_s32_s24_be(data_t* target, data_t* source, int length) { int32_t* s = (int32_t*) source; + int32_t t; for(int i = 0; i < length; i++) { - target[i*3] = s[i] >> 24 & 0xFF; - target[i*3+1] = s[i] >> 16 & 0xFF; - target[i*3+2] = s[i] >> 8 & 0xFF; + t = s[i]; + target[i*3] = t >> 24 & 0xFF; + target[i*3+1] = t >> 16 & 0xFF; + target[i*3+2] = t >> 8 & 0xFF; } } void AUD_convert_s32_s24_le(data_t* target, data_t* source, int length) { - int16_t* s = (int16_t*) source; + int32_t* s = (int32_t*) source; + int32_t t; for(int i = 0; i < length; i++) { - target[i*3+2] = s[i] >> 24 & 0xFF; - target[i*3+1] = s[i] >> 16 & 0xFF; - target[i*3] = s[i] >> 8 & 0xFF; + t = s[i]; + target[i*3+2] = t >> 24 & 0xFF; + target[i*3+1] = t >> 16 & 0xFF; + target[i*3] = t >> 8 & 0xFF; } } @@ -281,7 +289,7 @@ void AUD_convert_s32_double(data_t* target, data_t* source, int length) { int32_t* s = (int32_t*) source; double* t = (double*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i--) t[i] = s[i] / AUD_S32_FLT; } @@ -371,7 +379,7 @@ void AUD_convert_float_double(data_t* target, data_t* source, int length) { float* s = (float*) source; double* t = (double*) target; - for(int i = 0; i < length; i++) + for(int i = length - 1; i >= 0; i++) t[i] = s[i]; } diff --git a/intern/audaspace/intern/AUD_ConverterReader.cpp b/intern/audaspace/intern/AUD_ConverterReader.cpp index 70297b8f5e8..b3d669379f8 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.cpp +++ b/intern/audaspace/intern/AUD_ConverterReader.cpp @@ -31,16 +31,15 @@ #include "AUD_ConverterReader.h" -AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader, +AUD_ConverterReader::AUD_ConverterReader(AUD_Reference<AUD_IReader> reader, AUD_DeviceSpecs specs) : - AUD_EffectReader(reader) + AUD_EffectReader(reader), + m_format(specs.format) { - m_specs.specs = reader->getSpecs(); - int bigendian = 1; bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian - switch(specs.format) + switch(m_format) { case AUD_FORMAT_U8: m_convert = AUD_convert_float_u8; @@ -66,26 +65,17 @@ AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader, default: break; } - - m_specs.format = specs.format; -} - -AUD_Specs AUD_ConverterReader::getSpecs() const -{ - return m_specs.specs; } -void AUD_ConverterReader::read(int & length, sample_t* & buffer) +void AUD_ConverterReader::read(int& length, bool& eos, sample_t* buffer) { - m_reader->read(length, buffer); - - int samplesize = AUD_SAMPLE_SIZE(m_specs); + AUD_Specs specs = m_reader->getSpecs(); + int samplesize = AUD_SAMPLE_SIZE(specs); - if(m_buffer.getSize() < length * samplesize) - m_buffer.resize(length * samplesize); + m_buffer.assureSize(length * samplesize); - m_convert((data_t*)m_buffer.getBuffer(), (data_t*)buffer, - length * m_specs.channels); + m_reader->read(length, eos, m_buffer.getBuffer()); - buffer = m_buffer.getBuffer(); + m_convert((data_t*)buffer, (data_t*)m_buffer.getBuffer(), + length * specs.channels); } diff --git a/intern/audaspace/intern/AUD_ConverterReader.h b/intern/audaspace/intern/AUD_ConverterReader.h index a7a425adc54..4a637becbb5 100644 --- a/intern/audaspace/intern/AUD_ConverterReader.h +++ b/intern/audaspace/intern/AUD_ConverterReader.h @@ -50,7 +50,7 @@ private: /** * The target specification. */ - AUD_DeviceSpecs m_specs; + AUD_SampleFormat m_format; /** * Converter function. @@ -67,10 +67,9 @@ public: * \param reader The reader to convert. * \param specs The target specification. */ - AUD_ConverterReader(AUD_IReader* reader, AUD_DeviceSpecs specs); + AUD_ConverterReader(AUD_Reference<AUD_IReader> reader, AUD_DeviceSpecs specs); - 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_CONVERTERREADER diff --git a/intern/audaspace/intern/AUD_DefaultMixer.cpp b/intern/audaspace/intern/AUD_DefaultMixer.cpp deleted file mode 100644 index 20471d6e874..00000000000 --- a/intern/audaspace/intern/AUD_DefaultMixer.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * $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_DefaultMixer.cpp - * \ingroup audaspaceintern - */ - - -#include "AUD_DefaultMixer.h" -#ifdef WITH_SAMPLERATE -#include "AUD_SRCResampleReader.h" -#else -#include "AUD_LinearResampleReader.h" -#endif -#include "AUD_ChannelMapperReader.h" -#include "AUD_ChannelMapperFactory.h" - -#include <cstring> - -AUD_DefaultMixer::AUD_DefaultMixer(AUD_DeviceSpecs specs) : - AUD_Mixer(specs) -{ -} - -AUD_IReader* AUD_DefaultMixer::prepare(AUD_IReader* reader) -{ - // hacky for now, until a better channel mapper reader is available - AUD_ChannelMapperFactory cmf(NULL, m_specs); - - AUD_Specs specs = reader->getSpecs(); - - // if channel count is lower in output, rechannel before resampling - if(specs.channels < m_specs.channels) - { - reader = new AUD_ChannelMapperReader(reader, - cmf.getMapping(specs.channels)); - specs.channels = m_specs.channels; - } - - // resample - if(specs.rate != m_specs.rate) -#ifdef WITH_SAMPLERATE - reader = new AUD_SRCResampleReader(reader, m_specs.specs); -#else - reader = new AUD_LinearResampleReader(reader, m_specs.specs); -#endif - - // rechannel - if(specs.channels != m_specs.channels) - reader = new AUD_ChannelMapperReader(reader, - cmf.getMapping(specs.channels)); - - return reader; -} diff --git a/intern/audaspace/intern/AUD_FileFactory.cpp b/intern/audaspace/intern/AUD_FileFactory.cpp index 1c8bb03bc92..684fbb13fb2 100644 --- a/intern/audaspace/intern/AUD_FileFactory.cpp +++ b/intern/audaspace/intern/AUD_FileFactory.cpp @@ -54,20 +54,20 @@ AUD_FileFactory::AUD_FileFactory(std::string filename) : AUD_FileFactory::AUD_FileFactory(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); } static const char* read_error = "AUD_FileFactory: File couldn't be read."; -AUD_IReader* AUD_FileFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_FileFactory::createReader() { #ifdef WITH_SNDFILE try { - if(m_buffer.get()) - return new AUD_SndFileReader(m_buffer); - else + if(m_buffer.isNull()) return new AUD_SndFileReader(m_filename); + else + return new AUD_SndFileReader(m_buffer); } catch(AUD_Exception&) {} #endif @@ -75,10 +75,10 @@ AUD_IReader* AUD_FileFactory::createReader() const #ifdef WITH_FFMPEG try { - 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); } catch(AUD_Exception&) {} #endif diff --git a/intern/audaspace/intern/AUD_FileFactory.h b/intern/audaspace/intern/AUD_FileFactory.h index a2ab94ae148..dfca70bc3fd 100644 --- a/intern/audaspace/intern/AUD_FileFactory.h +++ b/intern/audaspace/intern/AUD_FileFactory.h @@ -72,7 +72,7 @@ public: */ AUD_FileFactory(const data_t* buffer, int size); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader(); }; #endif //AUD_FILEFACTORY diff --git a/intern/audaspace/intern/AUD_I3DDevice.h b/intern/audaspace/intern/AUD_I3DDevice.h index df341dbb319..036f7b1fa94 100644 --- a/intern/audaspace/intern/AUD_I3DDevice.h +++ b/intern/audaspace/intern/AUD_I3DDevice.h @@ -35,8 +35,6 @@ #include "AUD_Space.h" #include "AUD_3DMath.h" -struct AUD_Handle; - /** * This class represents an output device for 3D sound. */ @@ -121,200 +119,6 @@ public: * \param model distance model. */ virtual void setDistanceModel(AUD_DistanceModel model)=0; - - - - /** - * Retrieves the location of a source. - * \param handle The handle of the source. - * \return The location. - */ - virtual AUD_Vector3 getSourceLocation(AUD_Handle* handle)=0; - - /** - * Sets the location of a source. - * \param handle The handle of the source. - * \param location The new location. - * \return Whether the action succeeded. - */ - virtual bool setSourceLocation(AUD_Handle* handle, const AUD_Vector3& location)=0; - - /** - * Retrieves the velocity of a source. - * \param handle The handle of the source. - * \return The velocity. - */ - virtual AUD_Vector3 getSourceVelocity(AUD_Handle* handle)=0; - - /** - * Sets the velocity of a source. - * \param handle The handle of the source. - * \param velocity The new velocity. - * \return Whether the action succeeded. - */ - virtual bool setSourceVelocity(AUD_Handle* handle, const AUD_Vector3& velocity)=0; - - /** - * Retrieves the orientation of a source. - * \param handle The handle of the source. - * \return The orientation as quaternion. - */ - virtual AUD_Quaternion getSourceOrientation(AUD_Handle* handle)=0; - - /** - * Sets the orientation of a source. - * \param handle The handle of the source. - * \param orientation The new orientation as quaternion. - * \return Whether the action succeeded. - */ - virtual bool setSourceOrientation(AUD_Handle* handle, const AUD_Quaternion& orientation)=0; - - - /** - * Checks whether the source location, velocity and orientation are relative - * to the listener. - * \param handle The handle of the source. - * \return Whether the source is relative. - */ - virtual bool isRelative(AUD_Handle* handle)=0; - - /** - * Sets whether the source location, velocity and orientation are relative - * to the listener. - * \param handle The handle of the source. - * \param relative Whether the source is relative. - * \return Whether the action succeeded. - */ - virtual bool setRelative(AUD_Handle* handle, bool relative)=0; - - /** - * Retrieves the maximum volume of a source. - * \param handle The handle of the source. - * \return The maximum volume. - */ - virtual float getVolumeMaximum(AUD_Handle* handle)=0; - - /** - * Sets the maximum volume of a source. - * \param handle The handle of the source. - * \param volume The new maximum volume. - * \return Whether the action succeeded. - */ - virtual bool setVolumeMaximum(AUD_Handle* handle, float volume)=0; - - /** - * Retrieves the minimum volume of a source. - * \param handle The handle of the source. - * \return The minimum volume. - */ - virtual float getVolumeMinimum(AUD_Handle* handle)=0; - - /** - * Sets the minimum volume of a source. - * \param handle The handle of the source. - * \param volume The new minimum volume. - * \return Whether the action succeeded. - */ - virtual bool setVolumeMinimum(AUD_Handle* handle, float volume)=0; - - /** - * Retrieves the maximum distance of a source. - * If a source is further away from the reader than this distance, the - * volume will automatically be set to 0. - * \param handle The handle of the source. - * \return The maximum distance. - */ - virtual float getDistanceMaximum(AUD_Handle* handle)=0; - - /** - * Sets the maximum distance of a source. - * If a source is further away from the reader than this distance, the - * volume will automatically be set to 0. - * \param handle The handle of the source. - * \param distance The new maximum distance. - * \return Whether the action succeeded. - */ - virtual bool setDistanceMaximum(AUD_Handle* handle, float distance)=0; - - /** - * Retrieves the reference distance of a source. - * \param handle The handle of the source. - * \return The reference distance. - */ - virtual float getDistanceReference(AUD_Handle* handle)=0; - - /** - * Sets the reference distance of a source. - * \param handle The handle of the source. - * \param distance The new reference distance. - * \return Whether the action succeeded. - */ - virtual bool setDistanceReference(AUD_Handle* handle, float distance)=0; - - /** - * Retrieves the attenuation of a source. - * \param handle The handle of the source. - * \return The attenuation. - */ - virtual float getAttenuation(AUD_Handle* handle)=0; - - /** - * Sets the attenuation of a source. - * This value is used for distance calculation. - * \param handle The handle of the source. - * \param factor The new attenuation. - * \return Whether the action succeeded. - */ - virtual bool setAttenuation(AUD_Handle* handle, float factor)=0; - - /** - * Retrieves the outer angle of the cone of a source. - * \param handle The handle of the source. - * \return The outer angle of the cone. - */ - virtual float getConeAngleOuter(AUD_Handle* handle)=0; - - /** - * Sets the outer angle of the cone of a source. - * \param handle The handle of the source. - * \param angle The new outer angle of the cone. - * \return Whether the action succeeded. - */ - virtual bool setConeAngleOuter(AUD_Handle* handle, float angle)=0; - - /** - * Retrieves the inner angle of the cone of a source. - * \param handle The handle of the source. - * \return The inner angle of the cone. - */ - virtual float getConeAngleInner(AUD_Handle* handle)=0; - - /** - * Sets the inner angle of the cone of a source. - * \param handle The handle of the source. - * \param angle The new inner angle of the cone. - * \return Whether the action succeeded. - */ - virtual bool setConeAngleInner(AUD_Handle* handle, float angle)=0; - - /** - * Retrieves the outer volume of the cone of a source. - * The volume between inner and outer angle is interpolated between inner - * volume and this value. - * \param handle The handle of the source. - * \return The outer volume of the cone. - */ - virtual float getConeVolumeOuter(AUD_Handle* handle)=0; - - /** - * Sets the outer volume of the cone of a source. - * The volume between inner and outer angle is interpolated between inner - * volume and this value. - * \param handle The handle of the source. - * \param volume The new outer volume of the cone. - * \return Whether the action succeeded. - */ - virtual bool setConeVolumeOuter(AUD_Handle* handle, float volume)=0; }; #endif //AUD_I3DDEVICE diff --git a/intern/audaspace/intern/AUD_I3DHandle.h b/intern/audaspace/intern/AUD_I3DHandle.h new file mode 100644 index 00000000000..259c702bf86 --- /dev/null +++ b/intern/audaspace/intern/AUD_I3DHandle.h @@ -0,0 +1,213 @@ +/* + * $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_I3DHandle.h + * \ingroup audaspaceintern + */ + + +#ifndef AUD_I3DHANDLE +#define AUD_I3DHANDLE + +#include "AUD_Space.h" +#include "AUD_3DMath.h" + +/** + * This class represents an output device for 3D sound. + */ +class AUD_I3DHandle +{ +public: + /** + * Retrieves the location of a source. + * \return The location. + */ + virtual AUD_Vector3 getSourceLocation()=0; + + /** + * Sets the location of a source. + * \param location The new location. + * \return Whether the action succeeded. + */ + virtual bool setSourceLocation(const AUD_Vector3& location)=0; + + /** + * Retrieves the velocity of a source. + * \return The velocity. + */ + virtual AUD_Vector3 getSourceVelocity()=0; + + /** + * Sets the velocity of a source. + * \param velocity The new velocity. + * \return Whether the action succeeded. + */ + virtual bool setSourceVelocity(const AUD_Vector3& velocity)=0; + + /** + * Retrieves the orientation of a source. + * \return The orientation as quaternion. + */ + virtual AUD_Quaternion getSourceOrientation()=0; + + /** + * Sets the orientation of a source. + * \param orientation The new orientation as quaternion. + * \return Whether the action succeeded. + */ + virtual bool setSourceOrientation(const AUD_Quaternion& orientation)=0; + + + /** + * Checks whether the source location, velocity and orientation are relative + * to the listener. + * \return Whether the source is relative. + */ + virtual bool isRelative()=0; + + /** + * Sets whether the source location, velocity and orientation are relative + * to the listener. + * \param relative Whether the source is relative. + * \return Whether the action succeeded. + */ + virtual bool setRelative(bool relative)=0; + + /** + * Retrieves the maximum volume of a source. + * \return The maximum volume. + */ + virtual float getVolumeMaximum()=0; + + /** + * Sets the maximum volume of a source. + * \param volume The new maximum volume. + * \return Whether the action succeeded. + */ + virtual bool setVolumeMaximum(float volume)=0; + + /** + * Retrieves the minimum volume of a source. + * \return The minimum volume. + */ + virtual float getVolumeMinimum()=0; + + /** + * Sets the minimum volume of a source. + * \param volume The new minimum volume. + * \return Whether the action succeeded. + */ + virtual bool setVolumeMinimum(float volume)=0; + + /** + * Retrieves the maximum distance of a source. + * If a source is further away from the reader than this distance, the + * volume will automatically be set to 0. + * \return The maximum distance. + */ + virtual float getDistanceMaximum()=0; + + /** + * Sets the maximum distance of a source. + * If a source is further away from the reader than this distance, the + * volume will automatically be set to 0. + * \param distance The new maximum distance. + * \return Whether the action succeeded. + */ + virtual bool setDistanceMaximum(float distance)=0; + + /** + * Retrieves the reference distance of a source. + * \return The reference distance. + */ + virtual float getDistanceReference()=0; + + /** + * Sets the reference distance of a source. + * \param distance The new reference distance. + * \return Whether the action succeeded. + */ + virtual bool setDistanceReference(float distance)=0; + + /** + * Retrieves the attenuation of a source. + * \return The attenuation. + */ + virtual float getAttenuation()=0; + + /** + * Sets the attenuation of a source. + * This value is used for distance calculation. + * \param factor The new attenuation. + * \return Whether the action succeeded. + */ + virtual bool setAttenuation(float factor)=0; + + /** + * Retrieves the outer angle of the cone of a source. + * \return The outer angle of the cone. + */ + virtual float getConeAngleOuter()=0; + + /** + * Sets the outer angle of the cone of a source. + * \param angle The new outer angle of the cone. + * \return Whether the action succeeded. + */ + virtual bool setConeAngleOuter(float angle)=0; + + /** + * Retrieves the inner angle of the cone of a source. + * \return The inner angle of the cone. + */ + virtual float getConeAngleInner()=0; + + /** + * Sets the inner angle of the cone of a source. + * \param angle The new inner angle of the cone. + * \return Whether the action succeeded. + */ + virtual bool setConeAngleInner(float angle)=0; + + /** + * Retrieves the outer volume of the cone of a source. + * The volume between inner and outer angle is interpolated between inner + * volume and this value. + * \return The outer volume of the cone. + */ + virtual float getConeVolumeOuter()=0; + + /** + * Sets the outer volume of the cone of a source. + * The volume between inner and outer angle is interpolated between inner + * volume and this value. + * \param volume The new outer volume of the cone. + * \return Whether the action succeeded. + */ + virtual bool setConeVolumeOuter(float volume)=0; +}; + +#endif //AUD_I3DHANDLE diff --git a/intern/audaspace/intern/AUD_IDevice.h b/intern/audaspace/intern/AUD_IDevice.h index 4856b913b38..992e3347366 100644 --- a/intern/audaspace/intern/AUD_IDevice.h +++ b/intern/audaspace/intern/AUD_IDevice.h @@ -33,15 +33,10 @@ #define AUD_IDEVICE #include "AUD_Space.h" +#include "AUD_Reference.h" class AUD_IFactory; class AUD_IReader; - -/// Handle structure, for inherition. -struct AUD_Handle -{ -}; - -typedef void (*stopCallback)(void*); +class AUD_IHandle; /** * This class represents an output device for sound sources. @@ -74,7 +69,7 @@ public: * \exception AUD_Exception Thrown if there's an unexpected (from the * device side) error during creation of the reader. */ - virtual AUD_Handle* play(AUD_IReader* reader, bool keep = false)=0; + virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IReader> reader, bool keep = false)=0; /** * Plays a sound source. @@ -86,87 +81,7 @@ public: * \exception AUD_Exception Thrown if there's an unexpected (from the * device side) error during creation of the reader. */ - virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false)=0; - - /** - * Pauses a played back sound. - * \param handle The handle returned by the play function. - * \return - * - true if the sound has been paused. - * - false if the sound isn't playing back or the handle is invalid. - */ - virtual bool pause(AUD_Handle* handle)=0; - - /** - * Resumes a paused sound. - * \param handle The handle returned by the play function. - * \return - * - true if the sound has been resumed. - * - false if the sound isn't paused or the handle is invalid. - */ - virtual bool resume(AUD_Handle* handle)=0; - - /** - * Stops a played back or paused sound. The handle is definitely invalid - * afterwards. - * \param handle The handle returned by the play function. - * \return - * - true if the sound has been stopped. - * - false if the handle is invalid. - */ - virtual bool stop(AUD_Handle* handle)=0; - - /** - * Gets the behaviour of the device for a played back sound when the sound - * doesn't return any more samples. - * \param handle The handle returned by the play function. - * \return - * - true if the source will be paused when it's end is reached - * - false if the handle won't kept or is invalid. - */ - virtual bool getKeep(AUD_Handle* handle)=0; - - /** - * Sets the behaviour of the device for a played back sound when the sound - * doesn't return any more samples. - * \param handle The handle returned by the play function. - * \param keep True when the source should be paused and not deleted. - * \return - * - true if the behaviour has been changed. - * - false if the handle is invalid. - */ - virtual bool setKeep(AUD_Handle* handle, bool keep)=0; - - /** - * Seeks in a played back sound. - * \param handle The handle returned by the play function. - * \param position The new position from where to play back, in seconds. - * \return - * - true if the handle is valid. - * - false if the handle is invalid. - * \warning Whether the seek works or not depends on the sound source. - */ - virtual bool seek(AUD_Handle* handle, float position)=0; - - /** - * Retrieves the current playback position of a sound. - * \param handle The handle returned by the play function. - * \return The playback position in seconds, or 0.0 if the handle is - * invalid. - */ - virtual float getPosition(AUD_Handle* handle)=0; - - /** - * Returns the status of a played back sound. - * \param handle The handle returned by the play function. - * \return - * - AUD_STATUS_INVALID if the sound has stopped or the handle is - *. invalid - * - AUD_STATUS_PLAYING if the sound is currently played back. - * - AUD_STATUS_PAUSED if the sound is currently paused. - * \see AUD_Status - */ - virtual AUD_Status getStatus(AUD_Handle* handle)=0; + virtual AUD_Reference<AUD_IHandle> play(AUD_Reference<AUD_IFactory> factory, bool keep = false)=0; /** * Locks the device. @@ -195,69 +110,6 @@ public: * \param volume The overall device volume. */ virtual void setVolume(float volume)=0; - - /** - * Retrieves the volume of a playing sound. - * \param handle The sound handle. - * \return The volume. - */ - virtual float getVolume(AUD_Handle* handle)=0; - - /** - * Sets the volume of a playing sound. - * \param handle The sound handle. - * \param volume The volume. - * \return - * - true if the handle is valid. - * - false if the handle is invalid. - */ - virtual bool setVolume(AUD_Handle* handle, float volume)=0; - - /** - * Retrieves the pitch of a playing sound. - * \return The pitch. - */ - virtual float getPitch(AUD_Handle* handle)=0; - - /** - * Sets the pitch of a playing sound. - * \param handle The sound handle. - * \param pitch The pitch. - * \return - * - true if the handle is valid. - * - false if the handle is invalid. - */ - virtual bool setPitch(AUD_Handle* handle, float pitch)=0; - - /** - * Retrieves the loop count of a playing sound. - * A negative value indicates infinity. - * \return The remaining loop count. - */ - virtual int getLoopCount(AUD_Handle* handle)=0; - - /** - * Sets the loop count of a playing sound. - * A negative value indicates infinity. - * \param handle The sound handle. - * \param count The new loop count. - * \return - * - true if the handle is valid. - * - false if the handle is invalid. - */ - virtual bool setLoopCount(AUD_Handle* handle, int count)=0; - - /** - * Sets the callback function that's called when the end of a playing sound - * is reached. - * \param handle The sound handle. - * \param callback The callback function. - * \param data The data that should be passed to the callback function. - * \return - * - true if the handle is valid. - * - false if the handle is invalid. - */ - virtual bool setStopCallback(AUD_Handle* handle, stopCallback callback = 0, void* data = 0)=0; }; #endif //AUD_IDevice diff --git a/intern/audaspace/intern/AUD_IFactory.h b/intern/audaspace/intern/AUD_IFactory.h index 40a61279a55..c1a9de7f724 100644 --- a/intern/audaspace/intern/AUD_IFactory.h +++ b/intern/audaspace/intern/AUD_IFactory.h @@ -33,6 +33,7 @@ #define AUD_IFACTORY #include "AUD_Space.h" +#include "AUD_Reference.h" class AUD_IReader; /** @@ -55,7 +56,7 @@ public: * \exception AUD_Exception An exception may be thrown if there has been * a more unexpected error during reader creation. */ - virtual AUD_IReader* createReader() const=0; + virtual AUD_Reference<AUD_IReader> createReader()=0; }; #endif //AUD_IFACTORY diff --git a/intern/audaspace/intern/AUD_IHandle.h b/intern/audaspace/intern/AUD_IHandle.h new file mode 100644 index 00000000000..51d8e0ca2e5 --- /dev/null +++ b/intern/audaspace/intern/AUD_IHandle.h @@ -0,0 +1,181 @@ +/* + * $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_IHandle.h + * \ingroup audaspaceintern + */ + +#ifndef AUD_IHANDLE +#define AUD_IHANDLE + +//#include "AUD_Space.h" +//#include "AUD_Reference.h" + +typedef void (*stopCallback)(void*); + +/** + * This class represents a playback handles for specific devices. + */ +class AUD_IHandle +{ +public: + /** + * Destroys the device. + */ + virtual ~AUD_IHandle() {} + + /** + * Pauses a played back sound. + * \return + * - true if the sound has been paused. + * - false if the sound isn't playing back or the handle is invalid. + */ + virtual bool pause()=0; + + /** + * Resumes a paused sound. + * \return + * - true if the sound has been resumed. + * - false if the sound isn't paused or the handle is invalid. + */ + virtual bool resume()=0; + + /** + * Stops a played back or paused sound. The handle is definitely invalid + * afterwards. + * \return + * - true if the sound has been stopped. + * - false if the handle is invalid. + */ + virtual bool stop()=0; + + /** + * Gets the behaviour of the device for a played back sound when the sound + * doesn't return any more samples. + * \return + * - true if the source will be paused when it's end is reached + * - false if the handle won't kept or is invalid. + */ + virtual bool getKeep()=0; + + /** + * Sets the behaviour of the device for a played back sound when the sound + * doesn't return any more samples. + * \param keep True when the source should be paused and not deleted. + * \return + * - true if the behaviour has been changed. + * - false if the handle is invalid. + */ + virtual bool setKeep(bool keep)=0; + + /** + * Seeks in a played back sound. + * \param position The new position from where to play back, in seconds. + * \return + * - true if the handle is valid. + * - false if the handle is invalid. + * \warning Whether the seek works or not depends on the sound source. + */ + virtual bool seek(float position)=0; + + /** + * Retrieves the current playback position of a sound. + * \return The playback position in seconds, or 0.0 if the handle is + * invalid. + */ + virtual float getPosition()=0; + + /** + * Returns the status of a played back sound. + * \return + * - AUD_STATUS_INVALID if the sound has stopped or the handle is + *. invalid + * - AUD_STATUS_PLAYING if the sound is currently played back. + * - AUD_STATUS_PAUSED if the sound is currently paused. + * \see AUD_Status + */ + virtual AUD_Status getStatus()=0; + + /** + * Retrieves the volume of a playing sound. + * \return The volume. + */ + virtual float getVolume()=0; + + /** + * Sets the volume of a playing sound. + * \param volume The volume. + * \return + * - true if the handle is valid. + * - false if the handle is invalid. + */ + virtual bool setVolume(float volume)=0; + + /** + * Retrieves the pitch of a playing sound. + * \return The pitch. + */ + virtual float getPitch()=0; + + /** + * Sets the pitch of a playing sound. + * \param pitch The pitch. + * \return + * - true if the handle is valid. + * - false if the handle is invalid. + */ + virtual bool setPitch(float pitch)=0; + + /** + * Retrieves the loop count of a playing sound. + * A negative value indicates infinity. + * \return The remaining loop count. + */ + virtual int getLoopCount()=0; + + /** + * Sets the loop count of a playing sound. + * A negative value indicates infinity. + * \param count The new loop count. + * \return + * - true if the handle is valid. + * - false if the handle is invalid. + */ + virtual bool setLoopCount(int count)=0; + + /** + * Sets the callback function that's called when the end of a playing sound + * is reached. + * \param callback The callback function. + * \param data The data that should be passed to the callback function. + * \return + * - true if the handle is valid. + * - false if the handle is invalid. + */ + virtual bool setStopCallback(stopCallback callback = 0, void* data = 0)=0; +}; + +#endif //AUD_IHandle diff --git a/intern/audaspace/intern/AUD_IReader.h b/intern/audaspace/intern/AUD_IReader.h index 7c31c593964..b1a282c9d49 100644 --- a/intern/audaspace/intern/AUD_IReader.h +++ b/intern/audaspace/intern/AUD_IReader.h @@ -92,15 +92,15 @@ public: /** * Request to read the next length samples out of the source. - * The buffer for reading has to stay valid until the next call of this - * method or until the reader is deleted. + * The buffer supplied has the needed size. * \param[in,out] length The count of samples that should be read. Shall * contain the real count of samples after reading, in case * there were only fewer samples available. * A smaller value also indicates the end of the reader. - * \param[out] buffer The pointer to the buffer with the samples. + * \param[out] eos End of stream, whether the end is reached or not. + * \param[int] buffer The pointer to the buffer to read into. */ - virtual void read(int & length, sample_t* & buffer)=0; + virtual void read(int& length, bool& eos, sample_t* buffer)=0; }; #endif //AUD_IREADER diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.cpp b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp index a90dc5cb860..7bedd93b7d5 100644 --- a/intern/audaspace/intern/AUD_LinearResampleFactory.cpp +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.cpp @@ -32,18 +32,13 @@ #include "AUD_LinearResampleFactory.h" #include "AUD_LinearResampleReader.h" -AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_IFactory* factory, +AUD_LinearResampleFactory::AUD_LinearResampleFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs) : - AUD_ResampleFactory(factory, specs) + AUD_MixerFactory(factory, specs) { } -AUD_IReader* AUD_LinearResampleFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_LinearResampleFactory::createReader() { - AUD_IReader* reader = getReader(); - - if(reader->getSpecs().rate != m_specs.rate) - reader = new AUD_LinearResampleReader(reader, m_specs.specs); - - return reader; + return new AUD_LinearResampleReader(getReader(), m_specs.specs); } diff --git a/intern/audaspace/intern/AUD_LinearResampleFactory.h b/intern/audaspace/intern/AUD_LinearResampleFactory.h index 678aa0b80cb..de015610a73 100644 --- a/intern/audaspace/intern/AUD_LinearResampleFactory.h +++ b/intern/audaspace/intern/AUD_LinearResampleFactory.h @@ -32,12 +32,12 @@ #ifndef AUD_LINEARRESAMPLEFACTORY #define AUD_LINEARRESAMPLEFACTORY -#include "AUD_ResampleFactory.h" +#include "AUD_MixerFactory.h" /** * This factory creates a resampling reader that does simple linear resampling. */ -class AUD_LinearResampleFactory : public AUD_ResampleFactory +class AUD_LinearResampleFactory : public AUD_MixerFactory { private: // hide copy constructor and operator= @@ -45,9 +45,9 @@ private: AUD_LinearResampleFactory& operator=(const AUD_LinearResampleFactory&); public: - AUD_LinearResampleFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_LinearResampleFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader(); }; #endif //AUD_LINEARRESAMPLEFACTORY diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.cpp b/intern/audaspace/intern/AUD_LinearResampleReader.cpp index 05fb39b2cca..c33017e912a 100644 --- a/intern/audaspace/intern/AUD_LinearResampleReader.cpp +++ b/intern/audaspace/intern/AUD_LinearResampleReader.cpp @@ -34,95 +34,139 @@ #include <cmath> #include <cstring> -#define CC channels + channel +#define CC m_channels + channel -AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_IReader* reader, +AUD_LinearResampleReader::AUD_LinearResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs) : - AUD_EffectReader(reader), - m_sspecs(reader->getSpecs()), - m_factor(float(specs.rate) / float(m_sspecs.rate)), - m_tspecs(specs), + AUD_ResampleReader(reader, specs.rate), + m_channels(reader->getSpecs().channels), m_position(0), - m_sposition(0) + m_cache_pos(0), + m_cache_ok(false) { - m_tspecs.channels = m_sspecs.channels; - m_cache.resize(2 * AUD_SAMPLE_SIZE(m_tspecs)); + specs.channels = m_channels; + m_cache.resize(2 * AUD_SAMPLE_SIZE(specs)); } void AUD_LinearResampleReader::seek(int position) { - m_position = position; - m_sposition = floor(position / m_factor); - m_reader->seek(m_sposition); + position = floor(position * double(m_reader->getSpecs().rate) / double(m_rate)); + m_reader->seek(position); + m_cache_ok = false; + m_cache_pos = 0; } int AUD_LinearResampleReader::getLength() const { - return m_reader->getLength() * m_factor; + return floor(m_reader->getLength() * double(m_rate) / double(m_reader->getSpecs().rate)); } int AUD_LinearResampleReader::getPosition() const { - return m_position; + return floor((m_reader->getPosition() + (m_cache_ok ? m_cache_pos - 2 : 0)) + * m_rate / m_reader->getSpecs().rate); } AUD_Specs AUD_LinearResampleReader::getSpecs() const { - return m_tspecs; + AUD_Specs specs = m_reader->getSpecs(); + specs.rate = m_rate; + return specs; } -void AUD_LinearResampleReader::read(int & length, sample_t* & buffer) +void AUD_LinearResampleReader::read(int& length, bool& eos, sample_t* buffer) { - int samplesize = AUD_SAMPLE_SIZE(m_tspecs); - int size = length * samplesize; + AUD_Specs specs = m_reader->getSpecs(); - if(m_buffer.getSize() < size) - m_buffer.resize(size); + int samplesize = AUD_SAMPLE_SIZE(specs); + int size = length; + float factor = float(m_rate) / float(m_reader->getSpecs().rate); + float spos; + sample_t low, high; + eos = false; + + if(factor == 1 && (!m_cache_ok || m_cache_pos == 0)) + { + // can read directly! + m_reader->read(length, eos, buffer); + return; + } + + // check for channels changed + + if(specs.channels != m_channels) + { + m_cache.resize(2 * samplesize); + m_channels = specs.channels; + m_cache_ok = false; + } - int need = ceil((m_position + length) / m_factor) + 1 - m_sposition; - int len = need; + int len; sample_t* buf; - buffer = m_buffer.getBuffer(); - m_reader->read(len, buf); + if(m_cache_ok) + { + int need = ceil(length / factor - (1 - m_cache_pos)); - if(len < need) - length = floor((m_sposition + len - 1) * m_factor) - m_position; + len = need; - float spos; - sample_t low, high; - int channels = m_sspecs.channels; + m_buffer.assureSize((len + 3) * samplesize); + buf = m_buffer.getBuffer(); + + memcpy(buf, m_cache.getBuffer(), 2 * samplesize); + m_reader->read(len, eos, buf + 2 * m_channels); - for(int channel = 0; channel < channels; channel++) + if(len < need) + length = floor((len + (1 - m_cache_pos)) * factor); + } + else { - for(int i = 0; i < length; i++) - { - spos = (m_position + i) / m_factor - m_sposition; + int need = ceil(length / factor) + 1; + + len = need; - if(floor(spos) < 0) + m_buffer.assureSize((len + 1) * samplesize); + buf = m_buffer.getBuffer(); + + m_reader->read(len, eos, buf); + + if(len < need) + { + if(eos) { - low = m_cache.getBuffer()[(int)(floor(spos) + 2) * CC]; - if(ceil(spos) < 0) - high = m_cache.getBuffer()[(int)(ceil(spos) + 2) * CC]; - else - high = buf[(int)ceil(spos) * CC]; + length = floor(len * factor); + memset(buf + len * m_channels, 0, samplesize); } else - { - low = buf[(int)floor(spos) * CC]; - high = buf[(int)ceil(spos) * CC]; - } + length = ceil((len - 1) * factor); + } + m_cache_ok = true; + m_cache_pos = 0; + } + + for(int channel = 0; channel < m_channels; channel++) + { + for(int i = 0; i < length; i++) + { + spos = (i + 1) / factor + m_cache_pos; + + low = buf[(int)floor(spos) * CC]; + high = buf[(int)ceil(spos) * CC]; + buffer[i * CC] = low + (spos - floor(spos)) * (high - low); } } - if(len > 1) - memcpy(m_cache.getBuffer(), - buf + (len - 2) * channels, - 2 * samplesize); - else if(len == 1) - memcpy(m_cache.getBuffer() + 1 * channels, buf, samplesize); + if(floor(spos) == spos) + { + memcpy(m_cache.getBuffer(), buf + int(floor(spos - 1)) * m_channels, 2 * samplesize); + m_cache_pos = 1; + } + else + { + memcpy(m_cache.getBuffer(), buf + int(floor(spos)) * m_channels, 2 * samplesize); + m_cache_pos = spos - floor(spos); + } - m_sposition += len; - m_position += length; + eos &= length < size; } diff --git a/intern/audaspace/intern/AUD_LinearResampleReader.h b/intern/audaspace/intern/AUD_LinearResampleReader.h index 419c96be2fa..2d92d106697 100644 --- a/intern/audaspace/intern/AUD_LinearResampleReader.h +++ b/intern/audaspace/intern/AUD_LinearResampleReader.h @@ -32,29 +32,19 @@ #ifndef AUD_LINEARRESAMPLEREADER #define AUD_LINEARRESAMPLEREADER -#include "AUD_EffectReader.h" +#include "AUD_ResampleReader.h" #include "AUD_Buffer.h" /** * This resampling reader uses libsamplerate for resampling. */ -class AUD_LinearResampleReader : public AUD_EffectReader +class AUD_LinearResampleReader : public AUD_ResampleReader { private: /** - * The sample specification of the source. + * The reader channels. */ - const AUD_Specs m_sspecs; - - /** - * The resampling factor. - */ - const float m_factor; - - /** - * The target specification. - */ - AUD_Specs m_tspecs; + AUD_Channels m_channels; /** * The current position. @@ -62,9 +52,9 @@ private: int m_position; /** - * The current reading source position. + * The position in the cache. */ - int m_sposition; + float m_cache_pos; /** * The sound output buffer. @@ -76,6 +66,11 @@ private: */ AUD_Buffer m_cache; + /** + * Whether the cache contains valid data. + */ + bool m_cache_ok; + // hide copy constructor and operator= AUD_LinearResampleReader(const AUD_LinearResampleReader&); AUD_LinearResampleReader& operator=(const AUD_LinearResampleReader&); @@ -86,13 +81,13 @@ public: * \param reader The reader to mix. * \param specs The target specification. */ - AUD_LinearResampleReader(AUD_IReader* reader, AUD_Specs specs); + AUD_LinearResampleReader(AUD_Reference<AUD_IReader> reader, AUD_Specs specs); virtual void seek(int position); virtual int getLength() const; virtual int getPosition() const; virtual AUD_Specs getSpecs() const; - virtual void read(int & length, sample_t* & buffer); + virtual void read(int& length, bool& eos, sample_t* buffer); }; #endif //AUD_LINEARRESAMPLEREADER diff --git a/intern/audaspace/intern/AUD_Mixer.cpp b/intern/audaspace/intern/AUD_Mixer.cpp index 03488ac46b1..74ff180627a 100644 --- a/intern/audaspace/intern/AUD_Mixer.cpp +++ b/intern/audaspace/intern/AUD_Mixer.cpp @@ -73,43 +73,37 @@ AUD_DeviceSpecs AUD_Mixer::getSpecs() const return m_specs; } -void AUD_Mixer::add(sample_t* buffer, int start, int length, float volume) +void AUD_Mixer::setSpecs(AUD_Specs specs) { - AUD_MixerBuffer buf; - buf.buffer = buffer; - buf.start = start; - buf.length = length; - buf.volume = volume; - m_buffers.push_back(buf); + m_specs.specs = specs; } -void AUD_Mixer::superpose(data_t* buffer, int length, float volume) +void AUD_Mixer::clear(int length) { - AUD_MixerBuffer buf; + m_buffer.assureSize(length * m_specs.channels * AUD_SAMPLE_SIZE(m_specs)); - int channels = m_specs.channels; + m_length = length; - if(m_buffer.getSize() < length * channels * 4) - m_buffer.resize(length * channels * 4); + memset(m_buffer.getBuffer(), 0, length * m_specs.channels * AUD_SAMPLE_SIZE(m_specs)); +} +void AUD_Mixer::mix(sample_t* buffer, int start, int length, float volume) +{ sample_t* out = m_buffer.getBuffer(); - sample_t* in; - memset(out, 0, length * channels * 4); + length = (AUD_MIN(m_length, length + start) - start) * m_specs.channels; + start *= m_specs.channels; - int end; - - while(!m_buffers.empty()) - { - buf = m_buffers.front(); - m_buffers.pop_front(); + for(int i = 0; i < length; i++) + out[i + start] += buffer[i] * volume; +} - end = buf.length * channels; - in = buf.buffer; +void AUD_Mixer::read(data_t* buffer, float volume) +{ + sample_t* out = m_buffer.getBuffer(); - for(int i = 0; i < end; i++) - out[i + buf.start * channels] += in[i] * buf.volume * volume; - } + for(int i = 0; i < m_length * m_specs.channels; i++) + out[i] *= volume; - m_convert(buffer, (data_t*) out, length * channels); + m_convert(buffer, (data_t*) out, m_length * m_specs.channels); } diff --git a/intern/audaspace/intern/AUD_Mixer.h b/intern/audaspace/intern/AUD_Mixer.h index 277d5bfe2bd..5ca801b1690 100644 --- a/intern/audaspace/intern/AUD_Mixer.h +++ b/intern/audaspace/intern/AUD_Mixer.h @@ -34,16 +34,8 @@ #include "AUD_ConverterFunctions.h" #include "AUD_Buffer.h" +#include "AUD_Reference.h" class AUD_IReader; -#include <list> - -struct AUD_MixerBuffer -{ - sample_t* buffer; - int start; - int length; - float volume; -}; /** * This abstract class is able to mix audiosignals of different channel count @@ -53,17 +45,17 @@ class AUD_Mixer { protected: /** - * The list of buffers to superpose. + * The output specification. */ - std::list<AUD_MixerBuffer> m_buffers; + AUD_DeviceSpecs m_specs; /** - * The output specification. + * The length of the mixing buffer. */ - const AUD_DeviceSpecs m_specs; + int m_length; /** - * The temporary mixing buffer. + * The mixing buffer. */ AUD_Buffer m_buffer; @@ -90,28 +82,32 @@ public: AUD_DeviceSpecs getSpecs() const; /** - * This funuction prepares a reader for playback. - * \param reader The reader to prepare. - * \return The reader that should be used for playback. + * Sets the target specification for superposing. + * \param specs The target specification. */ - virtual AUD_IReader* prepare(AUD_IReader* reader)=0; + void setSpecs(AUD_Specs specs); /** - * Adds a buffer for superposition. + * Mixes a buffer. * \param buffer The buffer to superpose. * \param start The start sample of the buffer. * \param length The length of the buffer in samples. * \param volume The mixing volume. Must be a value between 0.0 and 1.0. */ - virtual void add(sample_t* buffer, int start, int length, float volume); + void mix(sample_t* buffer, int start, int length, float volume); /** - * Superposes all added buffers into an output buffer. + * Writes the mixing buffer into an output buffer. * \param buffer The target buffer for superposing. - * \param length The length of the buffer in samples. * \param volume The mixing volume. Must be a value between 0.0 and 1.0. */ - virtual void superpose(data_t* buffer, int length, float volume); + void read(data_t* buffer, float volume); + + /** + * Clears the mixing buffer. + * \param length The length of the buffer in samples. + */ + void clear(int length); }; #endif //AUD_MIXER diff --git a/intern/audaspace/intern/AUD_MixerFactory.cpp b/intern/audaspace/intern/AUD_MixerFactory.cpp index e65b149b94c..c3bf6b4fa99 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.cpp +++ b/intern/audaspace/intern/AUD_MixerFactory.cpp @@ -32,12 +32,12 @@ #include "AUD_MixerFactory.h" #include "AUD_IReader.h" -AUD_IReader* AUD_MixerFactory::getReader() const +AUD_Reference<AUD_IReader> AUD_MixerFactory::getReader() const { return m_factory->createReader(); } -AUD_MixerFactory::AUD_MixerFactory(AUD_IFactory* factory, +AUD_MixerFactory::AUD_MixerFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs) : m_specs(specs), m_factory(factory) { @@ -48,7 +48,7 @@ AUD_DeviceSpecs AUD_MixerFactory::getSpecs() const return m_specs; } -AUD_IFactory* AUD_MixerFactory::getFactory() const +AUD_Reference<AUD_IFactory> AUD_MixerFactory::getFactory() const { return m_factory; } diff --git a/intern/audaspace/intern/AUD_MixerFactory.h b/intern/audaspace/intern/AUD_MixerFactory.h index 2adabbd13ca..27c703b1898 100644 --- a/intern/audaspace/intern/AUD_MixerFactory.h +++ b/intern/audaspace/intern/AUD_MixerFactory.h @@ -48,7 +48,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. @@ -56,7 +56,7 @@ protected: * classes. * \return The reader to mix. */ - AUD_IReader* getReader() const; + AUD_Reference<AUD_IReader> getReader() const; public: /** @@ -64,7 +64,7 @@ public: * \param factory The factory to create the readers to mix out of. * \param specs The target specification. */ - AUD_MixerFactory(AUD_IFactory* factory, AUD_DeviceSpecs specs); + AUD_MixerFactory(AUD_Reference<AUD_IFactory> factory, AUD_DeviceSpecs specs); /** * Returns the target specification for resampling. @@ -75,7 +75,7 @@ public: * Returns the saved factory. * \return The factory. */ - AUD_IFactory* getFactory() const; + AUD_Reference<AUD_IFactory> getFactory() const; }; #endif //AUD_MIXERFACTORY diff --git a/intern/audaspace/intern/AUD_NULLDevice.cpp b/intern/audaspace/intern/AUD_NULLDevice.cpp index ab824799d88..6cb13111a43 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.cpp +++ b/intern/audaspace/intern/AUD_NULLDevice.cpp @@ -34,6 +34,7 @@ #include "AUD_NULLDevice.h" #include "AUD_IReader.h" #include "AUD_IFactory.h" +#include "AUD_IHandle.h" AUD_NULLDevice::AUD_NULLDevice() { @@ -48,56 +49,16 @@ AUD_DeviceSpecs AUD_NULLDevice::getSpecs() const return specs; } -AUD_Handle* AUD_NULLDevice::play(AUD_IReader* reader, bool keep) +AUD_Reference<AUD_IHandle> AUD_NULLDevice::play(AUD_Reference<AUD_IReader> reader, bool keep) { return 0; } -AUD_Handle* AUD_NULLDevice::play(AUD_IFactory* factory, bool keep) +AUD_Reference<AUD_IHandle> AUD_NULLDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep) { return 0; } -bool AUD_NULLDevice::pause(AUD_Handle* handle) -{ - return false; -} - -bool AUD_NULLDevice::resume(AUD_Handle* handle) -{ - return false; -} - -bool AUD_NULLDevice::stop(AUD_Handle* handle) -{ - return false; -} - -bool AUD_NULLDevice::getKeep(AUD_Handle* handle) -{ - return false; -} - -bool AUD_NULLDevice::setKeep(AUD_Handle* handle, bool keep) -{ - return false; -} - -bool AUD_NULLDevice::seek(AUD_Handle* handle, float position) -{ - return false; -} - -float AUD_NULLDevice::getPosition(AUD_Handle* handle) -{ - return std::numeric_limits<float>::quiet_NaN(); -} - -AUD_Status AUD_NULLDevice::getStatus(AUD_Handle* handle) -{ - return AUD_STATUS_INVALID; -} - void AUD_NULLDevice::lock() { } @@ -114,38 +75,3 @@ float AUD_NULLDevice::getVolume() const void AUD_NULLDevice::setVolume(float volume) { } - -float AUD_NULLDevice::getVolume(AUD_Handle* handle) -{ - return std::numeric_limits<float>::quiet_NaN(); -} - -bool AUD_NULLDevice::setVolume(AUD_Handle* handle, float volume) -{ - return false; -} - -float AUD_NULLDevice::getPitch(AUD_Handle* handle) -{ - return std::numeric_limits<float>::quiet_NaN(); -} - -bool AUD_NULLDevice::setPitch(AUD_Handle* handle, float pitch) -{ - return false; -} - -int AUD_NULLDevice::getLoopCount(AUD_Handle* handle) -{ - return 0; -} - -bool AUD_NULLDevice::setLoopCount(AUD_Handle* handle, int count) -{ - return false; -} - -bool AUD_NULLDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data) -{ - return false; -} diff --git a/intern/audaspace/intern/AUD_NULLDevice.h b/intern/audaspace/intern/AUD_NULLDevice.h index f700bea477b..69ca5b74f3b 100644 --- a/intern/audaspace/intern/AUD_NULLDevice.h +++ b/intern/audaspace/intern/AUD_NULLDevice.h @@ -32,6 +32,7 @@ #ifndef AUD_NULLDEVICE #define AUD_NULLDEVICE +#include "AUD_IReader.h" #include "AUD_IDevice.h" /** @@ -46,27 +47,12 @@ public: AUD_NULLDevice(); 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 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 = 0, void* data = 0); }; #endif //AUD_NULLDEVICE diff --git a/intern/audaspace/intern/AUD_ReadDevice.cpp b/intern/audaspace/intern/AUD_ReadDevice.cpp index eb5177330bb..5c1876aeb34 100644 --- a/intern/audaspace/intern/AUD_ReadDevice.cpp +++ b/intern/audaspace/intern/AUD_ReadDevice.cpp @@ -29,7 +29,6 @@ */ -#include "AUD_DefaultMixer.h" #include "AUD_ReadDevice.h" #include "AUD_IReader.h" diff --git a/intern/audaspace/intern/AUD_Reference.h b/intern/audaspace/intern/AUD_Reference.h index 3232ca3b609..3ddeab2eff1 100644 --- a/intern/audaspace/intern/AUD_Reference.h +++ b/intern/audaspace/intern/AUD_Reference.h @@ -28,10 +28,52 @@ * \ingroup audaspaceintern */ - #ifndef AUD_REFERENCE #define AUD_REFERENCE +#include <map> + +#ifdef MEM_DEBUG +#include <iostream> +#include <typeinfo> +#endif + +class AUD_ReferenceHandler +{ +private: + static std::map<void*, int> m_references; + +public: + static inline void incref(void* reference) + { + if(!reference) + return; + + std::map<void*, int>::iterator result = m_references.find(reference); + if(result != m_references.end()) + { + m_references[reference]++; + } + else + { + m_references[reference] = 1; + } + } + + static inline bool decref(void* reference) + { + if(!reference) + return false; + + if(!--m_references[reference]) + { + m_references.erase(reference); + return true; + } + return false; + } +}; + template <class T> /** * This class provides reference counting functionality. @@ -41,8 +83,7 @@ class AUD_Reference private: /// The reference. T* m_reference; - /// The reference counter. - int* m_refcount; + void* m_original; public: /** * Creates a new reference counter. @@ -50,9 +91,12 @@ public: */ AUD_Reference(T* reference = 0) { - m_reference = reference; - m_refcount = new int; - *m_refcount = 1; + m_original = m_reference = reference; + AUD_ReferenceHandler::incref(reference); +#ifdef MEM_DEBUG + if(m_reference != 0) + std::cerr << "+" << typeid(*m_reference).name() << std::endl; +#endif } /** @@ -61,9 +105,24 @@ public: */ AUD_Reference(const AUD_Reference& ref) { - m_reference = ref.m_reference; - m_refcount = ref.m_refcount; - (*m_refcount)++; + m_original = m_reference = ref.m_reference; + AUD_ReferenceHandler::incref(m_reference); +#ifdef MEM_DEBUG + if(m_reference != 0) + std::cerr << "+" << typeid(*m_reference).name() << std::endl; +#endif + } + + template <class U> + explicit AUD_Reference(const AUD_Reference<U>& ref) + { + m_original = ref.get(); + m_reference = dynamic_cast<T*>(ref.get()); + AUD_ReferenceHandler::incref(m_original); +#ifdef MEM_DEBUG + if(m_reference != 0) + std::cerr << "+" << typeid(*m_reference).name() << std::endl; +#endif } /** @@ -72,15 +131,12 @@ public: */ ~AUD_Reference() { - (*m_refcount)--; - if(*m_refcount == 0) - { - if(m_reference) - { - delete m_reference; - } - delete m_refcount; - } +#ifdef MEM_DEBUG + if(m_reference != 0) + std::cerr << "-" << typeid(*m_reference).name() << std::endl; +#endif + if(AUD_ReferenceHandler::decref(m_original)) + delete m_reference; } /** @@ -92,30 +148,72 @@ public: if(&ref == this) return *this; - (*m_refcount)--; - if(*m_refcount == 0) - { - if(m_reference) - { - delete m_reference; - } - delete m_refcount; - } +#ifdef MEM_DEBUG + if(m_reference != 0) + std::cerr << "-" << typeid(*m_reference).name() << std::endl; +#endif + if(AUD_ReferenceHandler::decref(m_original)) + delete m_reference; + m_original = ref.m_original; m_reference = ref.m_reference; - m_refcount = ref.m_refcount; - (*m_refcount)++; + AUD_ReferenceHandler::incref(m_original); +#ifdef MEM_DEBUG + if(m_reference != 0) + std::cerr << "+" << typeid(*m_reference).name() << std::endl; +#endif return *this; } /** + * Returns whether the reference is NULL. + */ + inline bool isNull() const + { + return m_reference == 0; + } + + /** * Returns the reference. */ - T* get() const + inline T* get() const + { + return m_reference; + } + + inline void* getOriginal() const + { + return m_original; + } + + /** + * Returns the reference. + */ + inline T& operator*() const + { + return *m_reference; + } + + /** + * Returns the reference. + */ + inline T* operator->() const { return m_reference; } }; +template<class T, class U> +inline bool operator==(const AUD_Reference<T>& a, const AUD_Reference<U>& b) +{ + return a.getOriginal() == b.getOriginal(); +} + +template<class T, class U> +inline bool operator!=(const AUD_Reference<T>& a, const AUD_Reference<U>& b) +{ + return a.getOriginal() != b.getOriginal(); +} + #endif // AUD_REFERENCE diff --git a/intern/audaspace/intern/AUD_ResampleFactory.h b/intern/audaspace/intern/AUD_ReferenceHandler.cpp index 634b82b3c96..cfc3c9441a8 100644 --- a/intern/audaspace/intern/AUD_ResampleFactory.h +++ b/intern/audaspace/intern/AUD_ReferenceHandler.cpp @@ -24,16 +24,10 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file audaspace/intern/AUD_ResampleFactory.h +/** \file audaspace/intern/AUD_Reference.cpp * \ingroup audaspaceintern */ +#include "AUD_Reference.h" -#ifndef AUD_RESAMPLEFACTORY -#define AUD_RESAMPLEFACTORY - -#include "AUD_MixerFactory.h" - -typedef AUD_MixerFactory AUD_ResampleFactory; - -#endif //AUD_RESAMPLEFACTORY +std::map<void*, int> AUD_ReferenceHandler::m_references; diff --git a/intern/audaspace/intern/AUD_ResampleReader.cpp b/intern/audaspace/intern/AUD_ResampleReader.cpp new file mode 100644 index 00000000000..e74d21eb743 --- /dev/null +++ b/intern/audaspace/intern/AUD_ResampleReader.cpp @@ -0,0 +1,47 @@ +/* + * $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_ResampleReader.cpp + * \ingroup audaspaceintern + */ + + +#include "AUD_ResampleReader.h" + +AUD_ResampleReader::AUD_ResampleReader(AUD_Reference<AUD_IReader> reader, AUD_SampleRate rate) : + AUD_EffectReader(reader), m_rate(rate) +{ +} + +void AUD_ResampleReader::setRate(AUD_SampleRate rate) +{ + m_rate = rate; +} + +AUD_SampleRate AUD_ResampleReader::getRate() +{ + return m_rate; +} diff --git a/intern/audaspace/intern/AUD_DefaultMixer.h b/intern/audaspace/intern/AUD_ResampleReader.h index a347141b5e0..4c1a1ece9d9 100644 --- a/intern/audaspace/intern/AUD_DefaultMixer.h +++ b/intern/audaspace/intern/AUD_ResampleReader.h @@ -24,36 +24,28 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file audaspace/intern/AUD_DefaultMixer.h +/** \file audaspace/intern/AUD_ResampleReader.h * \ingroup audaspaceintern */ +#ifndef AUD_RESAMPLEREADER +#define AUD_RESAMPLEREADER -#ifndef AUD_DEFAULTMIXER -#define AUD_DEFAULTMIXER +#include "AUD_EffectReader.h" -#include "AUD_Mixer.h" - -/** - * This class is able to mix audiosignals of different channel count and sample - * rate and convert it to a specific output format. - * It uses a default ChannelMapperFactory and a SRCResampleFactory for - * the perparation. - */ -class AUD_DefaultMixer : public AUD_Mixer +class AUD_ResampleReader : public AUD_EffectReader { -public: +protected: /** - * Creates the mixer. + * The target sampling rate. */ - AUD_DefaultMixer(AUD_DeviceSpecs specs); + AUD_SampleRate m_rate; - /** - * This funuction prepares a reader for playback. - * \param reader The reader to prepare. - * \return The reader that should be used for playback. - */ - virtual AUD_IReader* prepare(AUD_IReader* reader); + AUD_ResampleReader(AUD_Reference<AUD_IReader> reader, AUD_SampleRate rate); + +public: + virtual void setRate(AUD_SampleRate rate); + AUD_SampleRate getRate(); }; -#endif //AUD_DEFAULTMIXER +#endif // AUD_RESAMPLEREADER diff --git a/intern/audaspace/intern/AUD_SequencerFactory.cpp b/intern/audaspace/intern/AUD_SequencerFactory.cpp index f49dd94fe11..6907d7683c9 100644 --- a/intern/audaspace/intern/AUD_SequencerFactory.cpp +++ b/intern/audaspace/intern/AUD_SequencerFactory.cpp @@ -32,7 +32,7 @@ #include "AUD_SequencerFactory.h" #include "AUD_SequencerReader.h" -typedef std::list<AUD_SequencerReader*>::iterator AUD_ReaderIterator; +typedef std::list<AUD_Reference<AUD_SequencerReader> >::iterator AUD_ReaderIterator; AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, bool muted, void* data, @@ -46,22 +46,14 @@ AUD_SequencerFactory::AUD_SequencerFactory(AUD_Specs specs, bool muted, AUD_SequencerFactory::~AUD_SequencerFactory() { - AUD_SequencerReader* reader; - AUD_SequencerEntry* entry; - - while(!m_readers.empty()) - { - reader = m_readers.front(); - m_readers.pop_front(); - reader->destroy(); - } - - while(!m_entries.empty()) - { - entry = m_entries.front(); - m_entries.pop_front(); - delete entry; - } +} + +void AUD_SequencerFactory::setSpecs(AUD_Specs specs) +{ + m_specs = specs; + + for(AUD_ReaderIterator i = m_readers.begin(); i != m_readers.end(); i++) + (*i)->setSpecs(m_specs); } void AUD_SequencerFactory::mute(bool muted) @@ -74,19 +66,9 @@ bool AUD_SequencerFactory::getMute() const return m_muted; } -AUD_IReader* AUD_SequencerFactory::newReader() +AUD_Reference<AUD_SequencerEntry> AUD_SequencerFactory::add(AUD_Reference<AUD_IFactory>** sound, float begin, float end, float skip, void* data) { - AUD_SequencerReader* reader = new AUD_SequencerReader(this, m_entries, - m_specs, m_data, - m_volume); - m_readers.push_front(reader); - - return reader; -} - -AUD_SequencerEntry* AUD_SequencerFactory::add(AUD_IFactory** sound, float begin, float end, float skip, void* data) -{ - AUD_SequencerEntry* entry = new AUD_SequencerEntry; + AUD_Reference<AUD_SequencerEntry> entry = new AUD_SequencerEntry; entry->sound = sound; entry->begin = begin; entry->skip = skip; @@ -102,34 +84,37 @@ AUD_SequencerEntry* AUD_SequencerFactory::add(AUD_IFactory** sound, float begin, return entry; } -void AUD_SequencerFactory::remove(AUD_SequencerEntry* entry) +void AUD_SequencerFactory::remove(AUD_Reference<AUD_SequencerEntry> entry) { for(AUD_ReaderIterator i = m_readers.begin(); i != m_readers.end(); i++) (*i)->remove(entry); m_entries.remove(entry); - - delete entry; } -void AUD_SequencerFactory::move(AUD_SequencerEntry* entry, float begin, float end, float skip) +void AUD_SequencerFactory::move(AUD_Reference<AUD_SequencerEntry> entry, float begin, float end, float skip) { entry->begin = begin; entry->skip = skip; entry->end = end; } -void AUD_SequencerFactory::mute(AUD_SequencerEntry* entry, bool mute) +void AUD_SequencerFactory::mute(AUD_Reference<AUD_SequencerEntry> entry, bool mute) { entry->muted = mute; } -AUD_IReader* AUD_SequencerFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_SequencerFactory::createReader() { - return const_cast<AUD_SequencerFactory*>(this)->newReader(); + AUD_Reference<AUD_SequencerReader> reader = new AUD_SequencerReader(this, m_entries, + m_specs, m_data, + m_volume); + m_readers.push_front(reader); + + return AUD_Reference<AUD_IReader>(reader); } -void AUD_SequencerFactory::removeReader(AUD_SequencerReader* reader) +void AUD_SequencerFactory::removeReader(AUD_Reference<AUD_SequencerReader> reader) { m_readers.remove(reader); } diff --git a/intern/audaspace/intern/AUD_SequencerFactory.h b/intern/audaspace/intern/AUD_SequencerFactory.h index 8f3466f75ce..4e57a224c65 100644 --- a/intern/audaspace/intern/AUD_SequencerFactory.h +++ b/intern/audaspace/intern/AUD_SequencerFactory.h @@ -40,7 +40,7 @@ typedef float (*AUD_volumeFunction)(void*, void*, float); struct AUD_SequencerEntry { - AUD_IFactory** sound; + AUD_Reference<AUD_IFactory>** sound; float begin; float end; float skip; @@ -61,14 +61,12 @@ private: */ AUD_Specs m_specs; - std::list<AUD_SequencerEntry*> m_entries; - std::list<AUD_SequencerReader*> m_readers; + std::list<AUD_Reference<AUD_SequencerEntry> > m_entries; + std::list<AUD_Reference<AUD_SequencerReader> > m_readers; bool m_muted; void* m_data; AUD_volumeFunction m_volume; - AUD_IReader* newReader(); - // hide copy constructor and operator= AUD_SequencerFactory(const AUD_SequencerFactory&); AUD_SequencerFactory& operator=(const AUD_SequencerFactory&); @@ -77,16 +75,18 @@ public: AUD_SequencerFactory(AUD_Specs specs, bool muted, void* data, AUD_volumeFunction volume); ~AUD_SequencerFactory(); + void setSpecs(AUD_Specs specs); + void mute(bool muted); bool getMute() const; - AUD_SequencerEntry* add(AUD_IFactory** sound, float begin, float end, float skip, void* data); - void remove(AUD_SequencerEntry* entry); - void move(AUD_SequencerEntry* entry, float begin, float end, float skip); - void mute(AUD_SequencerEntry* entry, bool mute); + AUD_Reference<AUD_SequencerEntry> add(AUD_Reference<AUD_IFactory>** sound, float begin, float end, float skip, void* data); + void remove(AUD_Reference<AUD_SequencerEntry> entry); + void move(AUD_Reference<AUD_SequencerEntry> entry, float begin, float end, float skip); + void mute(AUD_Reference<AUD_SequencerEntry> entry, bool mute); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader(); - void removeReader(AUD_SequencerReader* reader); + void removeReader(AUD_Reference<AUD_SequencerReader> reader); }; #endif //AUD_SEQUENCERFACTORY diff --git a/intern/audaspace/intern/AUD_SequencerReader.cpp b/intern/audaspace/intern/AUD_SequencerReader.cpp index 95e0dca6323..a9309311d6a 100644 --- a/intern/audaspace/intern/AUD_SequencerReader.cpp +++ b/intern/audaspace/intern/AUD_SequencerReader.cpp @@ -30,27 +30,32 @@ #include "AUD_SequencerReader.h" -#include "AUD_DefaultMixer.h" +#include "AUD_Mixer.h" + +#ifdef WITH_SAMPLERATE +#include "AUD_SRCResampleReader.h" +#else +#include "AUD_LinearResampleReader.h" +#endif +#include "AUD_ChannelMapperReader.h" #include <math.h> -typedef std::list<AUD_SequencerStrip*>::iterator AUD_StripIterator; -typedef std::list<AUD_SequencerEntry*>::iterator AUD_EntryIterator; +typedef std::list<AUD_Reference<AUD_SequencerStrip> >::iterator AUD_StripIterator; +typedef std::list<AUD_Reference<AUD_SequencerEntry> >::iterator AUD_EntryIterator; -AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory, - std::list<AUD_SequencerEntry*> &entries, AUD_Specs specs, - void* data, AUD_volumeFunction volume) +AUD_SequencerReader::AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory, + std::list<AUD_Reference<AUD_SequencerEntry> > &entries, AUD_Specs specs, + void* data, AUD_volumeFunction volume) : + m_position(0), m_factory(factory), m_data(data), m_volume(volume) { AUD_DeviceSpecs dspecs; dspecs.specs = specs; dspecs.format = AUD_FORMAT_FLOAT32; - m_mixer = new AUD_DefaultMixer(dspecs); - m_factory = factory; - m_data = data; - m_volume = volume; + m_mixer = new AUD_Mixer(dspecs); - AUD_SequencerStrip* strip; + AUD_Reference<AUD_SequencerStrip> strip; for(AUD_EntryIterator i = entries.begin(); i != entries.end(); i++) { @@ -58,89 +63,54 @@ AUD_SequencerReader::AUD_SequencerReader(AUD_SequencerFactory* factory, strip->entry = *i; strip->old_sound = NULL; - if(strip->old_sound) - strip->reader = m_mixer->prepare(strip->old_sound->createReader()); - else - strip->reader = NULL; - m_strips.push_front(strip); } - - m_position = 0; } AUD_SequencerReader::~AUD_SequencerReader() { - if(m_factory != NULL) - m_factory->removeReader(this); - - AUD_SequencerStrip* strip; - - while(!m_strips.empty()) - { - strip = m_strips.front(); - m_strips.pop_front(); - if(strip->reader) - { - delete strip->reader; - } - delete strip; - } - - delete m_mixer; + m_factory->removeReader(this); } -void AUD_SequencerReader::destroy() +void AUD_SequencerReader::add(AUD_Reference<AUD_SequencerEntry> entry) { - m_factory = NULL; - AUD_SequencerStrip* strip; - - while(!m_strips.empty()) - { - strip = m_strips.front(); - m_strips.pop_front(); - delete strip; - } -} - -void AUD_SequencerReader::add(AUD_SequencerEntry* entry) -{ - AUD_SequencerStrip* strip = new AUD_SequencerStrip; + AUD_Reference<AUD_SequencerStrip> strip = new AUD_SequencerStrip; strip->entry = entry; - if(*strip->entry->sound) - { - strip->old_sound = *strip->entry->sound; - strip->reader = m_mixer->prepare(strip->old_sound->createReader()); - } - else - { - strip->reader = NULL; - strip->old_sound = NULL; - } m_strips.push_front(strip); } -void AUD_SequencerReader::remove(AUD_SequencerEntry* entry) +void AUD_SequencerReader::remove(AUD_Reference<AUD_SequencerEntry> entry) { - AUD_SequencerStrip* strip; + AUD_Reference<AUD_SequencerStrip> strip; for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++) { strip = *i; if(strip->entry == entry) { i++; - if(strip->reader) - { - delete strip->reader; - } m_strips.remove(strip); - delete strip; return; } } } +void AUD_SequencerReader::setSpecs(AUD_Specs specs) +{ + m_mixer->setSpecs(specs); + + AUD_Reference<AUD_SequencerStrip> strip; + for(AUD_StripIterator i = m_strips.begin(); i != m_strips.end(); i++) + { + strip = *i; + if(!strip->mapper.isNull()) + { + strip->mapper->setChannels(specs.channels); + strip->resampler->setRate(specs.rate); + } + } +} + bool AUD_SequencerReader::isSeekable() const { return true; @@ -166,21 +136,16 @@ AUD_Specs AUD_SequencerReader::getSpecs() const return m_mixer->getSpecs().specs; } -void AUD_SequencerReader::read(int & length, sample_t* & buffer) +void AUD_SequencerReader::read(int& length, bool& eos, sample_t* buffer) { AUD_DeviceSpecs specs = m_mixer->getSpecs(); - int samplesize = AUD_SAMPLE_SIZE(specs); int rate = specs.rate; - int size = length * samplesize; - int start, end, current, skip, len; - AUD_SequencerStrip* strip; - sample_t* buf; + AUD_Reference<AUD_SequencerStrip> strip; + m_buffer.assureSize(length * AUD_SAMPLE_SIZE(specs)); - if(m_buffer.getSize() < size) - m_buffer.resize(size); - buffer = m_buffer.getBuffer(); + m_mixer->clear(length); if(!m_factory->getMute()) { @@ -192,25 +157,38 @@ void AUD_SequencerReader::read(int & length, sample_t* & buffer) if(strip->old_sound != *strip->entry->sound) { strip->old_sound = *strip->entry->sound; - if(strip->reader) - delete strip->reader; if(strip->old_sound) { try { - strip->reader = m_mixer->prepare(strip->old_sound->createReader()); + strip->reader = (*strip->old_sound)->createReader(); + // resample + #ifdef WITH_SAMPLERATE + strip->resampler = new AUD_SRCResampleReader(strip->reader, m_mixer->getSpecs().specs); + #else + strip->resampler = new AUD_LinearResampleReader(strip->reader, m_mixer->getSpecs().specs); + #endif + + // rechannel + strip->mapper = new AUD_ChannelMapperReader(AUD_Reference<AUD_IReader>(strip->resampler), m_mixer->getSpecs().channels); } catch(AUD_Exception) { strip->reader = NULL; + strip->resampler = NULL; + strip->mapper = NULL; } } else + { strip->reader = NULL; + strip->resampler = NULL; + strip->mapper = NULL; + } } - if(strip->reader) + if(!strip->mapper.isNull()) { end = floor(strip->entry->end * rate); if(m_position < end) @@ -229,10 +207,10 @@ void AUD_SequencerReader::read(int & length, sample_t* & buffer) current += strip->entry->skip * rate; len = length > end - m_position ? end - m_position : length; len -= skip; - if(strip->reader->getPosition() != current) - strip->reader->seek(current); - strip->reader->read(len, buf); - m_mixer->add(buf, skip, len, m_volume(m_data, strip->entry->data, (float)m_position / (float)rate)); + if(strip->mapper->getPosition() != current) + strip->mapper->seek(current); + strip->mapper->read(len, eos, m_buffer.getBuffer()); + m_mixer->mix(m_buffer.getBuffer(), skip, len, m_volume(m_data, strip->entry->data, (float)m_position / (float)rate)); } } } @@ -240,7 +218,9 @@ void AUD_SequencerReader::read(int & length, sample_t* & buffer) } } - m_mixer->superpose((data_t*)buffer, length, 1.0f); + m_mixer->read((data_t*)buffer, 1.0f); m_position += length; + + eos = false; } diff --git a/intern/audaspace/intern/AUD_SequencerReader.h b/intern/audaspace/intern/AUD_SequencerReader.h index 53baf521acc..625bad3c3ae 100644 --- a/intern/audaspace/intern/AUD_SequencerReader.h +++ b/intern/audaspace/intern/AUD_SequencerReader.h @@ -35,13 +35,17 @@ #include "AUD_IReader.h" #include "AUD_SequencerFactory.h" #include "AUD_Buffer.h" -class AUD_Mixer; +#include "AUD_Mixer.h" +#include "AUD_ResampleReader.h" +#include "AUD_ChannelMapperReader.h" struct AUD_SequencerStrip { - AUD_IFactory* old_sound; - AUD_IReader* reader; - AUD_SequencerEntry* entry; + AUD_Reference<AUD_IReader> reader; + AUD_Reference<AUD_ResampleReader> resampler; + AUD_Reference<AUD_ChannelMapperReader> mapper; + AUD_Reference<AUD_SequencerEntry> entry; + AUD_Reference<AUD_IFactory>* old_sound; }; /** @@ -56,21 +60,21 @@ private: int m_position; /** - * The sound output buffer. + * The reading buffer. */ AUD_Buffer m_buffer; /** * The target specification. */ - AUD_Mixer* m_mixer; + AUD_Reference<AUD_Mixer> m_mixer; /** * Saves the SequencerFactory the reader belongs to. */ - AUD_SequencerFactory* m_factory; + AUD_Reference<AUD_SequencerFactory> m_factory; - std::list<AUD_SequencerStrip*> m_strips; + std::list<AUD_Reference<AUD_SequencerStrip> > m_strips; void* m_data; AUD_volumeFunction m_volume; @@ -85,24 +89,23 @@ public: * \param reader The reader to mix. * \param specs The target specification. */ - AUD_SequencerReader(AUD_SequencerFactory* factory, std::list<AUD_SequencerEntry*> &entries, const AUD_Specs specs, void* data, AUD_volumeFunction volume); + AUD_SequencerReader(AUD_Reference<AUD_SequencerFactory> factory, std::list<AUD_Reference<AUD_SequencerEntry> > &entries, const AUD_Specs specs, void* data, AUD_volumeFunction volume); /** * Destroys the reader. */ ~AUD_SequencerReader(); - void destroy(); - - void add(AUD_SequencerEntry* entry); - void remove(AUD_SequencerEntry* entry); + void add(AUD_Reference<AUD_SequencerEntry> entry); + void remove(AUD_Reference<AUD_SequencerEntry> entry); + void setSpecs(AUD_Specs specs); virtual bool isSeekable() const; virtual void seek(int position); virtual int getLength() const; virtual int getPosition() const; virtual AUD_Specs getSpecs() const; - virtual void read(int & length, sample_t* & buffer); + virtual void read(int& length, bool& eos, sample_t* buffer); }; #endif //AUD_SEQUENCERREADER diff --git a/intern/audaspace/intern/AUD_SilenceFactory.cpp b/intern/audaspace/intern/AUD_SilenceFactory.cpp index dc3f0626591..aefd561a584 100644 --- a/intern/audaspace/intern/AUD_SilenceFactory.cpp +++ b/intern/audaspace/intern/AUD_SilenceFactory.cpp @@ -37,7 +37,7 @@ AUD_SilenceFactory::AUD_SilenceFactory() { } -AUD_IReader* AUD_SilenceFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_SilenceFactory::createReader() { return new AUD_SilenceReader(); } diff --git a/intern/audaspace/intern/AUD_SilenceFactory.h b/intern/audaspace/intern/AUD_SilenceFactory.h index fb6afc34189..69b446408d7 100644 --- a/intern/audaspace/intern/AUD_SilenceFactory.h +++ b/intern/audaspace/intern/AUD_SilenceFactory.h @@ -50,7 +50,7 @@ public: */ AUD_SilenceFactory(); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader(); }; #endif //AUD_SILENCEFACTORY diff --git a/intern/audaspace/intern/AUD_SilenceReader.cpp b/intern/audaspace/intern/AUD_SilenceReader.cpp index bdff4fe75a6..d34fea72bb3 100644 --- a/intern/audaspace/intern/AUD_SilenceReader.cpp +++ b/intern/audaspace/intern/AUD_SilenceReader.cpp @@ -66,15 +66,9 @@ AUD_Specs AUD_SilenceReader::getSpecs() const return specs; } -void AUD_SilenceReader::read(int & length, sample_t* & buffer) +void AUD_SilenceReader::read(int& length, bool& eos, sample_t* buffer) { - // resize if necessary - if(m_buffer.getSize() < length * sizeof(sample_t)) - { - m_buffer.resize(length * sizeof(sample_t)); - memset(m_buffer.getBuffer(), 0, m_buffer.getSize()); - } - - buffer = m_buffer.getBuffer(); + memset(buffer, 0, length * sizeof(sample_t)); m_position += length; + eos = false; } diff --git a/intern/audaspace/intern/AUD_SilenceReader.h b/intern/audaspace/intern/AUD_SilenceReader.h index b35b4cfab42..29966aef0a7 100644 --- a/intern/audaspace/intern/AUD_SilenceReader.h +++ b/intern/audaspace/intern/AUD_SilenceReader.h @@ -51,11 +51,6 @@ private: */ int m_position; - /** - * The playback buffer. - */ - AUD_Buffer m_buffer; - // hide copy constructor and operator= AUD_SilenceReader(const AUD_SilenceReader&); AUD_SilenceReader& operator=(const AUD_SilenceReader&); @@ -71,7 +66,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_SILENCEREADER diff --git a/intern/audaspace/intern/AUD_SinusFactory.cpp b/intern/audaspace/intern/AUD_SinusFactory.cpp index 9ea7a031b16..b79f6bee6d7 100644 --- a/intern/audaspace/intern/AUD_SinusFactory.cpp +++ b/intern/audaspace/intern/AUD_SinusFactory.cpp @@ -44,7 +44,7 @@ float AUD_SinusFactory::getFrequency() const return m_frequency; } -AUD_IReader* AUD_SinusFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_SinusFactory::createReader() { return new AUD_SinusReader(m_frequency, m_sampleRate); } diff --git a/intern/audaspace/intern/AUD_SinusFactory.h b/intern/audaspace/intern/AUD_SinusFactory.h index 6d8b355784b..a6bc7f2110c 100644 --- a/intern/audaspace/intern/AUD_SinusFactory.h +++ b/intern/audaspace/intern/AUD_SinusFactory.h @@ -68,7 +68,7 @@ public: */ float getFrequency() const; - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader(); }; #endif //AUD_SINUSFACTORY diff --git a/intern/audaspace/intern/AUD_SinusReader.cpp b/intern/audaspace/intern/AUD_SinusReader.cpp index f32464f067a..bb5477ed5cf 100644 --- a/intern/audaspace/intern/AUD_SinusReader.cpp +++ b/intern/audaspace/intern/AUD_SinusReader.cpp @@ -72,19 +72,14 @@ AUD_Specs AUD_SinusReader::getSpecs() const return specs; } -void AUD_SinusReader::read(int & length, sample_t* & buffer) +void AUD_SinusReader::read(int& length, bool& eos, sample_t* buffer) { - // resize if necessary - if(m_buffer.getSize() < length * sizeof(sample_t)) - m_buffer.resize(length * sizeof(sample_t)); - // fill with sine data - buffer = m_buffer.getBuffer(); for(int i = 0; i < length; i++) { - buffer[i] = sin((m_position + i) * 2 * M_PI * m_frequency / - (float)m_sampleRate); + buffer[i] = sin((m_position + i) * 2 * M_PI * m_frequency / m_sampleRate); } m_position += length; + eos = false; } diff --git a/intern/audaspace/intern/AUD_SinusReader.h b/intern/audaspace/intern/AUD_SinusReader.h index e807f03226d..69e9a3ca576 100644 --- a/intern/audaspace/intern/AUD_SinusReader.h +++ b/intern/audaspace/intern/AUD_SinusReader.h @@ -57,11 +57,6 @@ private: int m_position; /** - * The playback buffer. - */ - AUD_Buffer m_buffer; - - /** * The sample rate for the output. */ const AUD_SampleRate m_sampleRate; @@ -83,7 +78,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_SINUSREADER diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp index b44b2f02d29..125b9d705dd 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp +++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp @@ -31,409 +31,780 @@ #include "AUD_SoftwareDevice.h" #include "AUD_IReader.h" -#include "AUD_DefaultMixer.h" +#include "AUD_Mixer.h" #include "AUD_IFactory.h" +#ifdef WITH_SAMPLERATE +#include "AUD_SRCResampleReader.h" +#else +#include "AUD_LinearResampleReader.h" +#endif #include <cstring> +#include <cmath> #include <limits> -/// Saves the data for playback. -struct AUD_SoftwareHandle : AUD_Handle +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +typedef enum +{ + AUD_RENDER_DISTANCE = 0x01, + AUD_RENDER_DOPPLER = 0x02, + AUD_RENDER_CONE = 0x04, + AUD_RENDER_VOLUME = 0x08 +} AUD_RenderFlags; + +#define AUD_PITCH_MAX 10 + +/******************************************************************************/ +/********************** AUD_SoftwareHandle Handle Code ************************/ +/******************************************************************************/ + +AUD_SoftwareDevice::AUD_SoftwareHandle::AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, AUD_Reference<AUD_ChannelMapperReader> mapper, bool keep) : + m_reader(reader), m_pitch(pitch), m_mapper(mapper), m_keep(keep), m_user_pitch(1.0f), m_user_volume(1.0f), m_volume(1.0f), m_loopcount(0), + m_relative(false), m_volume_max(1.0f), m_volume_min(0), m_distance_max(std::numeric_limits<float>::max()), + m_distance_reference(1.0f), m_attenuation(1.0f), m_cone_angle_outer(M_PI), m_cone_angle_inner(M_PI), m_cone_volume_outer(0), + m_flags(AUD_RENDER_CONE), m_stop(NULL), m_stop_data(NULL), m_status(AUD_STATUS_PLAYING), m_device(device) { - /// The reader source. - AUD_IReader* reader; +} - /// Whether to keep the source if end of it is reached. - bool keep; +void AUD_SoftwareDevice::AUD_SoftwareHandle::update() +{ + int flags = 0; - /// The volume of the source. - float volume; + AUD_Vector3 SL; + if(m_relative) + SL = m_location; + else + SL = m_device->m_location - m_location; + float distance = SL * SL; - /// The loop count of the source. - int loopcount; + if(distance > 0) + distance = sqrt(distance); + else + flags |= AUD_RENDER_DOPPLER | AUD_RENDER_DISTANCE; - /// The stop callback. - stopCallback stop; + if(m_pitch->getSpecs().channels != AUD_CHANNELS_MONO) + { + m_volume = m_user_volume; + m_pitch->setPitch(m_user_pitch); + return; + } - /// Stop callback data. - void* stop_data; -}; + flags = ~(flags | m_flags | m_device->m_flags); -typedef std::list<AUD_SoftwareHandle*>::iterator AUD_HandleIterator; + // Doppler and Pitch -void AUD_SoftwareDevice::create() -{ - m_playback = false; - m_volume = 1.0f; - m_mixer = new AUD_DefaultMixer(m_specs); + if(flags & AUD_RENDER_DOPPLER) + { + float vls; + if(m_relative) + vls = 0; + else + vls = SL * m_device->m_velocity / distance; + float vss = SL * m_velocity / distance; + float max = m_device->m_speed_of_sound / m_device->m_doppler_factor; + if(vss >= max) + { + m_pitch->setPitch(AUD_PITCH_MAX); + } + else + { + if(vls > max) + vls = max; - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + m_pitch->setPitch((m_device->m_speed_of_sound - m_device->m_doppler_factor * vls) / (m_device->m_speed_of_sound - m_device->m_doppler_factor * vss) * m_user_pitch); + } + } + else + m_pitch->setPitch(m_user_pitch); - pthread_mutex_init(&m_mutex, &attr); + if(flags & AUD_RENDER_VOLUME) + { + // Distance - pthread_mutexattr_destroy(&attr); -} + if(flags & AUD_RENDER_DISTANCE) + { + if(m_device->m_distance_model == AUD_DISTANCE_MODEL_INVERSE_CLAMPED || m_device->m_distance_model == AUD_DISTANCE_MODEL_LINEAR_CLAMPED || m_device->m_distance_model == AUD_DISTANCE_MODEL_EXPONENT_CLAMPED) + { + distance = AUD_MAX(AUD_MIN(m_distance_max, distance), m_distance_reference); + } -void AUD_SoftwareDevice::destroy() -{ - if(m_playback) - playing(m_playback = false); + switch(m_device->m_distance_model) + { + case AUD_DISTANCE_MODEL_INVERSE: + case AUD_DISTANCE_MODEL_INVERSE_CLAMPED: + m_volume = m_distance_reference / (m_distance_reference + m_attenuation * (distance - m_distance_reference)); + break; + case AUD_DISTANCE_MODEL_LINEAR: + case AUD_DISTANCE_MODEL_LINEAR_CLAMPED: + { + float temp = m_distance_max - m_distance_reference; + if(temp == 0) + { + if(distance > m_distance_reference) + m_volume = 0.0f; + else + m_volume = 1.0f; + } + else + m_volume = 1.0f - m_attenuation * (distance - m_distance_reference) / (m_distance_max - m_distance_reference); + break; + } + case AUD_DISTANCE_MODEL_EXPONENT: + case AUD_DISTANCE_MODEL_EXPONENT_CLAMPED: + if(m_distance_reference == 0) + m_volume = 0; + else + m_volume = pow(distance / m_distance_reference, -m_attenuation); + break; + default: + m_volume = 1.0f; + } + } + else + m_volume = 1.0f; - delete m_mixer; + // Cone - AUD_SoftwareHandle* handle; + if(flags & AUD_RENDER_CONE) + { + AUD_Vector3 SZ = m_orientation.getLookAt(); - // delete all playing sounds - while(!m_playingSounds.empty()) - { - handle = m_playingSounds.front(); - m_playingSounds.pop_front(); - delete handle->reader; - delete handle; + float phi = acos(float(SZ * SL / (SZ.length() * SL.length()))); + float t = (phi - m_cone_angle_inner)/(m_cone_angle_outer - m_cone_angle_inner); + + if(t > 0) + { + if(t > 1) + m_volume *= m_cone_volume_outer; + else + m_volume *= 1 + t * (m_cone_volume_outer - 1); + } + } + + // Volume + + m_volume *= m_user_volume; } - // delete all paused sounds - while(!m_pausedSounds.empty()) + // 3D Cue + + AUD_Quaternion orientation; + + if(!m_relative) + orientation = m_device->m_orientation; + + AUD_Vector3 Z = orientation.getLookAt(); + AUD_Vector3 N = orientation.getUp(); + AUD_Vector3 A = N * ((SL * N) / (N * N)) - SL; + + float Asquare = A * A; + + if(Asquare > 0) { - handle = m_pausedSounds.front(); - m_pausedSounds.pop_front(); - delete handle->reader; - delete handle; - } + float phi = acos(float(Z * A / (Z.length() * sqrt(Asquare)))); + if(N.cross(Z) * A > 0) + phi = -phi; - pthread_mutex_destroy(&m_mutex); + m_mapper->setMonoAngle(phi); + } + else + m_mapper->setMonoAngle(0); } -void AUD_SoftwareDevice::mix(data_t* buffer, int length) +bool AUD_SoftwareDevice::AUD_SoftwareHandle::pause() { - lock(); - + if(m_status) { - AUD_SoftwareHandle* sound; - int len; - int pos; - sample_t* buf; - std::list<AUD_SoftwareHandle*> stopSounds; - std::list<AUD_Buffer*> tempBufs; - AUD_Buffer* tempbuf; - int samplesize = AUD_SAMPLE_SIZE(m_specs); + m_device->lock(); - // for all sounds - AUD_HandleIterator it = m_playingSounds.begin(); - while(it != m_playingSounds.end()) + if(m_status == AUD_STATUS_PLAYING) { - sound = *it; - // increment the iterator to make sure it's valid, - // in case the sound gets deleted after stopping - ++it; + m_device->m_playingSounds.remove(this); + m_device->m_pausedSounds.push_back(this); - // get the buffer from the source - pos = 0; - len = length; - sound->reader->read(len, buf); + if(m_device->m_playingSounds.empty()) + m_device->playing(m_device->m_playback = false); + m_status = AUD_STATUS_PAUSED; + m_device->unlock(); - // in case of looping - while(pos + len < length && sound->loopcount) - { - tempbuf = new AUD_Buffer(len * samplesize); - memcpy(tempbuf->getBuffer(), buf, len * samplesize); - tempBufs.push_back(tempbuf); - m_mixer->add(tempbuf->getBuffer(), pos, len, sound->volume); + return true; + } - pos += len; + m_device->unlock(); + } - if(sound->loopcount > 0) - sound->loopcount--; + return false; +} - sound->reader->seek(0); +bool AUD_SoftwareDevice::AUD_SoftwareHandle::resume() +{ + if(m_status) + { + m_device->lock(); - len = length - pos; - sound->reader->read(len, buf); + if(m_status == AUD_STATUS_PAUSED) + { + m_device->m_pausedSounds.remove(this); + m_device->m_playingSounds.push_back(this); - // prevent endless loop - if(!len) - break; - } + if(!m_device->m_playback) + m_device->playing(m_device->m_playback = true); + m_status = AUD_STATUS_PLAYING; + m_device->unlock(); + return true; + } - m_mixer->add(buf, pos, len, sound->volume); - pos += len; + m_device->unlock(); + } - // in case the end of the sound is reached - if(pos < length) - { - if(sound->stop) - sound->stop(sound->stop_data); + return false; +} - if(sound->keep) - pause(sound); - else - stopSounds.push_back(sound); - } - } +bool AUD_SoftwareDevice::AUD_SoftwareHandle::stop() +{ + if(!m_status) + return false; - // superpose - m_mixer->superpose(buffer, length, m_volume); + m_device->lock(); - // cleanup - while(!stopSounds.empty()) - { - sound = stopSounds.front(); - stopSounds.pop_front(); - stop(sound); - } + // AUD_XXX Create a reference of our own object so that it doesn't get + // deleted before the end of this function + AUD_Reference<AUD_SoftwareHandle> This = this; - while(!tempBufs.empty()) - { - tempbuf = tempBufs.front(); - tempBufs.pop_front(); - delete tempbuf; - } + if(m_status == AUD_STATUS_PLAYING) + { + m_device->m_playingSounds.remove(This); + + if(m_device->m_playingSounds.empty()) + m_device->playing(m_device->m_playback = false); } + else + m_device->m_pausedSounds.remove(This); - unlock(); + m_device->unlock(); + m_status = AUD_STATUS_INVALID; + return true; } -bool AUD_SoftwareDevice::isValid(AUD_Handle* handle) +bool AUD_SoftwareDevice::AUD_SoftwareHandle::getKeep() { - for(AUD_HandleIterator i = m_playingSounds.begin(); - i != m_playingSounds.end(); i++) - if(*i == handle) - return true; - for(AUD_HandleIterator i = m_pausedSounds.begin(); - i != m_pausedSounds.end(); i++) - if(*i == handle) - return true; + if(m_status) + return m_keep; + return false; } -AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setKeep(bool keep) { - return m_specs; + if(!m_status) + return false; + + m_device->lock(); + + m_keep = keep; + + m_device->unlock(); + + return true; } -AUD_Handle* AUD_SoftwareDevice::play(AUD_IReader* reader, bool keep) +bool AUD_SoftwareDevice::AUD_SoftwareHandle::seek(float position) { - // prepare the reader - reader = m_mixer->prepare(reader); - if(reader == NULL) - return NULL; + if(!m_status) + return false; - // play sound - AUD_SoftwareHandle* sound = new AUD_SoftwareHandle; - sound->keep = keep; - sound->reader = reader; - sound->volume = 1.0f; - sound->loopcount = 0; - sound->stop = NULL; - sound->stop_data = NULL; + m_device->lock(); - lock(); - m_playingSounds.push_back(sound); + m_reader->seek((int)(position * m_reader->getSpecs().rate)); - if(!m_playback) - playing(m_playback = true); - unlock(); + m_device->unlock(); - return sound; + return true; } -AUD_Handle* AUD_SoftwareDevice::play(AUD_IFactory* factory, bool keep) +float AUD_SoftwareDevice::AUD_SoftwareHandle::getPosition() { - return play(factory->createReader(), keep); + if(!m_status) + return 0.0f; + + m_device->lock(); + + float position = m_reader->getPosition() / (float)m_device->m_specs.rate; + + m_device->unlock(); + + return position; } -bool AUD_SoftwareDevice::pause(AUD_Handle* handle) +AUD_Status AUD_SoftwareDevice::AUD_SoftwareHandle::getStatus() { - bool result = false; + return m_status; +} - lock(); +float AUD_SoftwareDevice::AUD_SoftwareHandle::getVolume() +{ + return m_user_volume; +} + +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolume(float volume) +{ + if(!m_status) + return false; + m_user_volume = volume; - // only songs that are played can be paused - for(AUD_HandleIterator i = m_playingSounds.begin(); - i != m_playingSounds.end(); i++) + if(volume == 0) { - if(*i == handle) - { - m_pausedSounds.push_back(*i); - m_playingSounds.erase(i); - if(m_playingSounds.empty()) - playing(m_playback = false); - result = true; - break; - } + m_volume = volume; + m_flags |= AUD_RENDER_VOLUME; } + else + m_flags &= ~AUD_RENDER_VOLUME; - unlock(); + return true; +} - return result; +float AUD_SoftwareDevice::AUD_SoftwareHandle::getPitch() +{ + return m_user_pitch; } -bool AUD_SoftwareDevice::resume(AUD_Handle* handle) +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setPitch(float pitch) { - bool result = false; + if(!m_status) + return false; + m_user_pitch = pitch; + return true; +} - lock(); +int AUD_SoftwareDevice::AUD_SoftwareHandle::getLoopCount() +{ + if(!m_status) + return 0; + return m_loopcount; +} - // only songs that are paused can be resumed - for(AUD_HandleIterator i = m_pausedSounds.begin(); - i != m_pausedSounds.end(); i++) - { - if(*i == handle) - { - m_playingSounds.push_back(*i); - m_pausedSounds.erase(i); - if(!m_playback) - playing(m_playback = true); - result = true; - break; - } - } +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setLoopCount(int count) +{ + if(!m_status) + return false; + m_loopcount = count; + return true; +} - unlock(); +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setStopCallback(stopCallback callback, void* data) +{ + if(!m_status) + return false; + + m_device->lock(); + + m_stop = callback; + m_stop_data = data; - return result; + m_device->unlock(); + + return true; } -bool AUD_SoftwareDevice::stop(AUD_Handle* handle) + + +/******************************************************************************/ +/******************** AUD_SoftwareHandle 3DHandle Code ************************/ +/******************************************************************************/ + +AUD_Vector3 AUD_SoftwareDevice::AUD_SoftwareHandle::getSourceLocation() { - bool result = false; + if(!m_status) + return AUD_Vector3(); - lock(); + return m_location; +} - for(AUD_HandleIterator i = m_playingSounds.begin(); - i != m_playingSounds.end(); i++) - { - if(*i == handle) - { - delete (*i)->reader; - delete *i; - m_playingSounds.erase(i); - if(m_playingSounds.empty()) - playing(m_playback = false); - result = true; - break; - } - } - if(!result) - { - for(AUD_HandleIterator i = m_pausedSounds.begin(); - i != m_pausedSounds.end(); i++) - { - if(*i == handle) - { - delete (*i)->reader; - delete *i; - m_pausedSounds.erase(i); - result = true; - break; - } - } - } +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setSourceLocation(const AUD_Vector3& location) +{ + if(!m_status) + return false; - unlock(); + m_location = location; - return result; + return true; } -bool AUD_SoftwareDevice::getKeep(AUD_Handle* handle) +AUD_Vector3 AUD_SoftwareDevice::AUD_SoftwareHandle::getSourceVelocity() { - bool result = false; + if(!m_status) + return AUD_Vector3(); - lock(); + return m_velocity; +} - if(isValid(handle)) - result = ((AUD_SoftwareHandle*)handle)->keep; +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setSourceVelocity(const AUD_Vector3& velocity) +{ + if(!m_status) + return false; - unlock(); + m_velocity = velocity; - return result; + return true; } -bool AUD_SoftwareDevice::setKeep(AUD_Handle* handle, bool keep) +AUD_Quaternion AUD_SoftwareDevice::AUD_SoftwareHandle::getSourceOrientation() { - bool result = false; + if(!m_status) + return AUD_Quaternion(); - lock(); + return m_orientation; +} - if(isValid(handle)) - { - ((AUD_SoftwareHandle*)handle)->keep = keep; - result = true; - } +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setSourceOrientation(const AUD_Quaternion& orientation) +{ + if(!m_status) + return false; - unlock(); + m_orientation = orientation; - return result; + return true; } -bool AUD_SoftwareDevice::seek(AUD_Handle* handle, float position) +bool AUD_SoftwareDevice::AUD_SoftwareHandle::isRelative() { - lock(); + if(!m_status) + return false; - bool result = false; + return m_relative; +} - if(isValid(handle)) - { - AUD_IReader* reader = ((AUD_SoftwareHandle*)handle)->reader; - reader->seek((int)(position * reader->getSpecs().rate)); - result = true; - } +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setRelative(bool relative) +{ + if(!m_status) + return false; - unlock(); + m_relative = relative; - return result; + return true; } -float AUD_SoftwareDevice::getPosition(AUD_Handle* handle) +float AUD_SoftwareDevice::AUD_SoftwareHandle::getVolumeMaximum() { - lock(); + if(!m_status) + return std::numeric_limits<float>::quiet_NaN(); - float position = 0.0f; + return m_volume_max; +} - if(isValid(handle)) - { - AUD_SoftwareHandle* h = (AUD_SoftwareHandle*)handle; - position = h->reader->getPosition() / (float)m_specs.rate; - } +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolumeMaximum(float volume) +{ + if(!m_status) + return false; - unlock(); + m_volume_max = volume; - return position; + return true; +} + +float AUD_SoftwareDevice::AUD_SoftwareHandle::getVolumeMinimum() +{ + if(!m_status) + return std::numeric_limits<float>::quiet_NaN();; + + return m_volume_min; +} + +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setVolumeMinimum(float volume) +{ + if(!m_status) + return false; + + m_volume_min = volume; + + return true; +} + +float AUD_SoftwareDevice::AUD_SoftwareHandle::getDistanceMaximum() +{ + if(!m_status) + return std::numeric_limits<float>::quiet_NaN(); + + return m_distance_max; +} + +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setDistanceMaximum(float distance) +{ + if(!m_status) + return false; + + m_distance_max = distance; + + return true; } -AUD_Status AUD_SoftwareDevice::getStatus(AUD_Handle* handle) +float AUD_SoftwareDevice::AUD_SoftwareHandle::getDistanceReference() { - AUD_Status status = AUD_STATUS_INVALID; + if(!m_status) + return std::numeric_limits<float>::quiet_NaN(); + + return m_distance_reference; +} + +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setDistanceReference(float distance) +{ + if(!m_status) + return false; + + m_distance_reference = distance; + + return true; +} + +float AUD_SoftwareDevice::AUD_SoftwareHandle::getAttenuation() +{ + if(!m_status) + return std::numeric_limits<float>::quiet_NaN(); + + return m_attenuation; +} + +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setAttenuation(float factor) +{ + if(!m_status) + return false; + + m_attenuation = factor; + + if(factor == 0) + m_flags |= AUD_RENDER_DISTANCE; + else + m_flags &= ~AUD_RENDER_DISTANCE; + + return true; +} + +float AUD_SoftwareDevice::AUD_SoftwareHandle::getConeAngleOuter() +{ + if(!m_status) + return std::numeric_limits<float>::quiet_NaN(); + + return m_cone_angle_outer * 360.0f / M_PI; +} + +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setConeAngleOuter(float angle) +{ + if(!m_status) + return false; + + m_cone_angle_outer = angle * M_PI / 360.0f; + + return true; +} + +float AUD_SoftwareDevice::AUD_SoftwareHandle::getConeAngleInner() +{ + if(!m_status) + return std::numeric_limits<float>::quiet_NaN(); + + return m_cone_angle_inner * 360.0f / M_PI; +} + +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setConeAngleInner(float angle) +{ + if(!m_status) + return false; + + if(angle >= 360) + m_flags |= AUD_RENDER_CONE; + else + m_flags &= ~AUD_RENDER_CONE; + + m_cone_angle_inner = angle * M_PI / 360.0f; + + return true; +} + +float AUD_SoftwareDevice::AUD_SoftwareHandle::getConeVolumeOuter() +{ + if(!m_status) + return std::numeric_limits<float>::quiet_NaN();; + + return m_cone_volume_outer; +} + +bool AUD_SoftwareDevice::AUD_SoftwareHandle::setConeVolumeOuter(float volume) +{ + if(!m_status) + return false; + + m_cone_volume_outer = volume; + + return true; +} + +/******************************************************************************/ +/**************************** IDevice Code ************************************/ +/******************************************************************************/ + +void AUD_SoftwareDevice::create() +{ + m_playback = false; + m_volume = 1.0f; + m_mixer = new AUD_Mixer(m_specs); + m_speed_of_sound = 343.0f; + m_doppler_factor = 1.0f; + m_distance_model = AUD_DISTANCE_MODEL_INVERSE_CLAMPED; + m_flags = 0; + + 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); +} + +void AUD_SoftwareDevice::destroy() +{ + if(m_playback) + playing(m_playback = false); + + while(!m_playingSounds.empty()) + m_playingSounds.front()->stop(); + + while(!m_pausedSounds.empty()) + m_pausedSounds.front()->stop(); + + pthread_mutex_destroy(&m_mutex); +} + +void AUD_SoftwareDevice::mix(data_t* buffer, int length) +{ + m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_specs)); lock(); - for(AUD_HandleIterator i = m_playingSounds.begin(); - i != m_playingSounds.end(); i++) { - if(*i == handle) - { - status = AUD_STATUS_PLAYING; - break; - } - } - if(status == AUD_STATUS_INVALID) - { - for(AUD_HandleIterator i = m_pausedSounds.begin(); - i != m_pausedSounds.end(); i++) + AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> sound; + int len; + int pos; + bool eos; + std::list<AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> > stopSounds; + sample_t* buf = m_buffer.getBuffer(); + + m_mixer->clear(length); + + // for all sounds + AUD_HandleIterator it = m_playingSounds.begin(); + while(it != m_playingSounds.end()) { - if(*i == handle) + sound = *it; + // increment the iterator to make sure it's valid, + // in case the sound gets deleted after stopping + ++it; + + // get the buffer from the source + pos = 0; + len = length; + + // update 3D Info + sound->update(); + + sound->m_reader->read(len, eos, buf); + + // in case of looping + while(pos + len < length && sound->m_loopcount && eos) { - status = AUD_STATUS_PAUSED; - break; + m_mixer->mix(buf, pos, len, sound->m_volume); + + pos += len; + + if(sound->m_loopcount > 0) + sound->m_loopcount--; + + sound->m_reader->seek(0); + + len = length - pos; + sound->m_reader->read(len, eos, buf); + + // prevent endless loop + if(!len) + break; + } + + m_mixer->mix(buf, pos, len, sound->m_volume); + + // in case the end of the sound is reached + if(eos && !sound->m_loopcount) + { + if(sound->m_stop) + sound->m_stop(sound->m_stop_data); + + if(sound->m_keep) + sound->pause(); + else + stopSounds.push_back(sound); } } + + // superpose + m_mixer->read(buffer, m_volume); + + // cleanup + while(!stopSounds.empty()) + { + sound = stopSounds.front(); + stopSounds.pop_front(); + sound->stop(); + } } unlock(); +} - return status; +AUD_DeviceSpecs AUD_SoftwareDevice::getSpecs() const +{ + return m_specs; +} + +AUD_Reference<AUD_IHandle> AUD_SoftwareDevice::play(AUD_Reference<AUD_IReader> reader, bool keep) +{ + // prepare the reader + // pitch + + AUD_Reference<AUD_PitchReader> pitch = new AUD_PitchReader(reader, 1); + reader = AUD_Reference<AUD_IReader>(pitch); + + // resample + #ifdef WITH_SAMPLERATE + reader = new AUD_SRCResampleReader(reader, m_specs.specs); + #else + reader = new AUD_LinearResampleReader(reader, m_specs.specs); + #endif + + // rechannel + AUD_Reference<AUD_ChannelMapperReader> mapper = new AUD_ChannelMapperReader(reader, m_specs.channels); + reader = AUD_Reference<AUD_IReader>(mapper); + + if(reader.isNull()) + return NULL; + + // play sound + AUD_Reference<AUD_SoftwareDevice::AUD_SoftwareHandle> sound = new AUD_SoftwareDevice::AUD_SoftwareHandle(this, reader, pitch, mapper, keep); + + lock(); + m_playingSounds.push_back(sound); + + if(!m_playback) + playing(m_playback = true); + unlock(); + + return AUD_Reference<AUD_IHandle>(sound); +} + +AUD_Reference<AUD_IHandle> AUD_SoftwareDevice::play(AUD_Reference<AUD_IFactory> factory, bool keep) +{ + return play(factory->createReader(), keep); } void AUD_SoftwareDevice::lock() @@ -456,66 +827,74 @@ void AUD_SoftwareDevice::setVolume(float volume) m_volume = volume; } -float AUD_SoftwareDevice::getVolume(AUD_Handle* handle) +/******************************************************************************/ +/**************************** 3D Device Code **********************************/ +/******************************************************************************/ + +AUD_Vector3 AUD_SoftwareDevice::getListenerLocation() const { - lock(); - float result = std::numeric_limits<float>::quiet_NaN(); - if(isValid(handle)) - result = ((AUD_SoftwareHandle*)handle)->volume; - unlock(); - return result; + return m_location; } -bool AUD_SoftwareDevice::setVolume(AUD_Handle* handle, float volume) +void AUD_SoftwareDevice::setListenerLocation(const AUD_Vector3& location) { - lock(); - bool result = isValid(handle); - if(result) - ((AUD_SoftwareHandle*)handle)->volume = volume; - unlock(); - return result; + m_location = location; } -float AUD_SoftwareDevice::getPitch(AUD_Handle* handle) +AUD_Vector3 AUD_SoftwareDevice::getListenerVelocity() const { - return std::numeric_limits<float>::quiet_NaN(); + return m_velocity; } -bool AUD_SoftwareDevice::setPitch(AUD_Handle* handle, float pitch) +void AUD_SoftwareDevice::setListenerVelocity(const AUD_Vector3& velocity) { - return false; + m_velocity = velocity; } -int AUD_SoftwareDevice::getLoopCount(AUD_Handle* handle) +AUD_Quaternion AUD_SoftwareDevice::getListenerOrientation() const { - lock(); - int result = 0; - if(isValid(handle)) - result = ((AUD_SoftwareHandle*)handle)->loopcount; - unlock(); - return result; + return m_orientation; } -bool AUD_SoftwareDevice::setLoopCount(AUD_Handle* handle, int count) +void AUD_SoftwareDevice::setListenerOrientation(const AUD_Quaternion& orientation) { - lock(); - bool result = isValid(handle); - if(result) - ((AUD_SoftwareHandle*)handle)->loopcount = count; - unlock(); - return result; + m_orientation = orientation; } -bool AUD_SoftwareDevice::setStopCallback(AUD_Handle* handle, stopCallback callback, void* data) +float AUD_SoftwareDevice::getSpeedOfSound() const { - lock(); - bool result = isValid(handle); - if(result) - { - AUD_SoftwareHandle* h = (AUD_SoftwareHandle*)handle; - h->stop = callback; - h->stop_data = data; - } - unlock(); - return result; + return m_speed_of_sound; +} + +void AUD_SoftwareDevice::setSpeedOfSound(float speed) +{ + m_speed_of_sound = speed; +} + +float AUD_SoftwareDevice::getDopplerFactor() const +{ + return m_doppler_factor; +} + +void AUD_SoftwareDevice::setDopplerFactor(float factor) +{ + m_doppler_factor = factor; + if(factor == 0) + m_flags |= AUD_RENDER_DOPPLER; + else + m_flags &= ~AUD_RENDER_DOPPLER; +} + +AUD_DistanceModel AUD_SoftwareDevice::getDistanceModel() const +{ + return m_distance_model; +} + +void AUD_SoftwareDevice::setDistanceModel(AUD_DistanceModel model) +{ + m_distance_model = model; + if(model == AUD_DISTANCE_MODEL_INVALID) + m_flags |= AUD_RENDER_DISTANCE; + else + m_flags &= ~AUD_RENDER_DISTANCE; } diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h index 1f6a5ead6e0..c7dbf1d41eb 100644 --- a/intern/audaspace/intern/AUD_SoftwareDevice.h +++ b/intern/audaspace/intern/AUD_SoftwareDevice.h @@ -33,9 +33,13 @@ #define AUD_SOFTWAREDEVICE #include "AUD_IDevice.h" -struct AUD_SoftwareHandle; -class AUD_Mixer; -class AUD_Buffer; +#include "AUD_IHandle.h" +#include "AUD_I3DDevice.h" +#include "AUD_I3DHandle.h" +#include "AUD_Mixer.h" +#include "AUD_Buffer.h" +#include "AUD_PitchReader.h" +#include "AUD_ChannelMapperReader.h" #include <list> #include <pthread.h> @@ -48,9 +52,139 @@ class AUD_Buffer; * - Call the create and destroy functions. * - Call the mix function to retrieve their audio data. */ -class AUD_SoftwareDevice : public AUD_IDevice +class AUD_SoftwareDevice : public AUD_IDevice, public AUD_I3DDevice { protected: + /// Saves the data for playback. + class AUD_SoftwareHandle : public AUD_IHandle, public AUD_I3DHandle + { + public: + /// The reader source. + AUD_Reference<AUD_IReader> m_reader; + + /// The pitch reader in between. + AUD_Reference<AUD_PitchReader> m_pitch; + + /// The channel mapper reader in between. + AUD_Reference<AUD_ChannelMapperReader> m_mapper; + + /// Whether to keep the source if end of it is reached. + bool m_keep; + + /// The user set pitch of the source. + float m_user_pitch; + + /// The user set volume of the source. + float m_user_volume; + + /// The calculated final volume of the source. + float m_volume; + + /// The loop count of the source. + int m_loopcount; + + /// Location in 3D Space. + AUD_Vector3 m_location; + + /// Velocity in 3D Space. + AUD_Vector3 m_velocity; + + /// Orientation in 3D Space. + AUD_Quaternion m_orientation; + + /// Whether the position to the listener is relative or absolute + bool m_relative; + + /// Maximum volume. + float m_volume_max; + + /// Minimum volume. + float m_volume_min; + + /// Maximum distance. + float m_distance_max; + + /// Reference distance; + float m_distance_reference; + + /// Attenuation + float m_attenuation; + + /// Cone outer angle. + float m_cone_angle_outer; + + /// Cone inner angle. + float m_cone_angle_inner; + + /// Cone outer volume. + float m_cone_volume_outer; + + /// Rendering flags + int m_flags; + + /// The stop callback. + stopCallback m_stop; + + /// Stop callback data. + void* m_stop_data; + + /// Current status of the handle + AUD_Status m_status; + + /// Own device. + AUD_SoftwareDevice* m_device; + + public: + + AUD_SoftwareHandle(AUD_SoftwareDevice* device, AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_PitchReader> pitch, AUD_Reference<AUD_ChannelMapperReader> mapper, bool keep); + + void update(); + + virtual ~AUD_SoftwareHandle() {} + 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_SoftwareHandle> >::iterator AUD_HandleIterator; + /** * The specification of the device. */ @@ -59,7 +193,7 @@ protected: /** * The mixer. */ - AUD_Mixer* m_mixer; + AUD_Reference<AUD_Mixer> m_mixer; /** * Initializes member variables. @@ -86,14 +220,19 @@ protected: private: /** + * The reading buffer. + */ + AUD_Buffer m_buffer; + + /** * The list of sounds that are currently playing. */ - std::list<AUD_SoftwareHandle*> m_playingSounds; + std::list<AUD_Reference<AUD_SoftwareHandle> > m_playingSounds; /** * The list of sounds that are currently paused. */ - std::list<AUD_SoftwareHandle*> m_pausedSounds; + std::list<AUD_Reference<AUD_SoftwareHandle> > m_pausedSounds; /** * Whether there is currently playback. @@ -110,36 +249,48 @@ private: */ float m_volume; - /** - * Checks if a handle is valid. - * \param handle The handle to check. - * \return Whether the handle is valid. - */ - bool isValid(AUD_Handle* handle); + /// Listener location. + AUD_Vector3 m_location; + + /// Listener velocity. + AUD_Vector3 m_velocity; + + /// Listener orientation. + AUD_Quaternion m_orientation; + + /// Speed of Sound. + float m_speed_of_sound; + + /// Doppler factor. + float m_doppler_factor; + + /// Distance model. + AUD_DistanceModel m_distance_model; + + /// Rendering flags + int m_flags; public: 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 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); + virtual AUD_Vector3 getListenerVelocity() const; + virtual void setListenerVelocity(const AUD_Vector3& velocity); + virtual AUD_Quaternion getListenerOrientation() const; + virtual void setListenerOrientation(const AUD_Quaternion& orientation); + virtual float getSpeedOfSound() const; + virtual void setSpeedOfSound(float speed); + virtual float getDopplerFactor() const; + virtual void setDopplerFactor(float factor); + virtual AUD_DistanceModel getDistanceModel() const; + virtual void setDistanceModel(AUD_DistanceModel model); }; #endif //AUD_SOFTWAREDEVICE diff --git a/intern/audaspace/intern/AUD_Space.h b/intern/audaspace/intern/AUD_Space.h index ee28a05b80d..308e032ff7f 100644 --- a/intern/audaspace/intern/AUD_Space.h +++ b/intern/audaspace/intern/AUD_Space.h @@ -41,6 +41,9 @@ /// Throws a AUD_Exception with the provided error code. #define AUD_THROW(exception, errorstr) { AUD_Exception e; e.error = exception; e.str = errorstr; throw e; } +/// Returns the bit for a channel mask. +#define AUD_CHANNEL_BIT(channel) (0x01 << channel) + /// Returns the smaller of the two values. #define AUD_MIN(a, b) (((a) < (b)) ? (a) : (b)) /// Returns the bigger of the two values. @@ -79,10 +82,24 @@ typedef enum AUD_CHANNELS_SURROUND5 = 5, /// 5 channel surround sound. AUD_CHANNELS_SURROUND51 = 6, /// 5.1 surround sound. AUD_CHANNELS_SURROUND61 = 7, /// 6.1 surround sound. - AUD_CHANNELS_SURROUND71 = 8, /// 7.1 surround sound. - AUD_CHANNELS_SURROUND72 = 9 /// 7.2 surround sound. + AUD_CHANNELS_SURROUND71 = 8 /// 7.1 surround sound. } AUD_Channels; +/// The channel names. +typedef enum +{ + AUD_CHANNEL_FRONT_LEFT = 0, + AUD_CHANNEL_FRONT_RIGHT, + AUD_CHANNEL_FRONT_CENTER, + AUD_CHANNEL_LFE, + AUD_CHANNEL_REAR_LEFT, + AUD_CHANNEL_REAR_RIGHT, + AUD_CHANNEL_REAR_CENTER, + AUD_CHANNEL_SIDE_LEFT, + AUD_CHANNEL_SIDE_RIGHT, + AUD_CHANNEL_MAX +} AUD_Channel; + /** * The sample rate tells how many samples are played back within one second. * Some exotic formats may use other sample rates than provided here. @@ -100,7 +117,7 @@ typedef enum AUD_RATE_88200 = 88200, /// 88200 Hz. AUD_RATE_96000 = 96000, /// 96000 Hz. AUD_RATE_192000 = 192000 /// 192000 Hz. -} AUD_SampleRate; +} AUD_DefaultSampleRate; /// Status of a playback handle. typedef enum @@ -149,6 +166,9 @@ typedef float sample_t; /// Sample data type (format samples) typedef unsigned char data_t; +/// Sample rate type. +typedef double AUD_SampleRate; + /// Specification of a sound source. typedef struct { diff --git a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp index c25442b6f26..ff966c86025 100644 --- a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp +++ b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp @@ -35,17 +35,17 @@ #include <cstring> -AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory) : +AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_Reference<AUD_IFactory> factory) : m_buffer(new AUD_Buffer()) { - AUD_IReader* reader = factory->createReader(); + AUD_Reference<AUD_IReader> reader = factory->createReader(); m_specs = reader->getSpecs(); int sample_size = AUD_SAMPLE_SIZE(m_specs); int length; int index = 0; - sample_t* buffer; + bool eos = false; // get an approximated size if possible int size = reader->getLength(); @@ -55,27 +55,24 @@ AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory) : else size += m_specs.rate; - // as long as we fill our buffer to the end - while(index == m_buffer.get()->getSize() / sample_size) + // as long as the end of the stream is not reached + while(!eos) { // increase - m_buffer.get()->resize(size*sample_size, true); + m_buffer->resize(size*sample_size, true); // read more length = size-index; - reader->read(length, buffer); - memcpy(m_buffer.get()->getBuffer() + index * m_specs.channels, - buffer, - length * sample_size); - size += AUD_BUFFER_RESIZE_BYTES / sample_size; + reader->read(length, eos, m_buffer->getBuffer() + index * m_specs.channels); + if(index == m_buffer->getSize() / sample_size) + size += AUD_BUFFER_RESIZE_BYTES / sample_size; index += length; } - m_buffer.get()->resize(index * sample_size, true); - delete reader; + m_buffer->resize(index * sample_size, true); } -AUD_IReader* AUD_StreamBufferFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_StreamBufferFactory::createReader() { return new AUD_BufferReader(m_buffer, m_specs); } diff --git a/intern/audaspace/intern/AUD_StreamBufferFactory.h b/intern/audaspace/intern/AUD_StreamBufferFactory.h index b6a44d95744..2783889ff6c 100644 --- a/intern/audaspace/intern/AUD_StreamBufferFactory.h +++ b/intern/audaspace/intern/AUD_StreamBufferFactory.h @@ -64,9 +64,9 @@ public: * \param factory The factory that creates the reader for buffering. * \exception AUD_Exception Thrown if the reader cannot be created. */ - AUD_StreamBufferFactory(AUD_IFactory* factory); + AUD_StreamBufferFactory(AUD_Reference<AUD_IFactory> factory); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader(); }; #endif //AUD_STREAMBUFFERFACTORY diff --git a/intern/audaspace/jack/AUD_JackDevice.cpp b/intern/audaspace/jack/AUD_JackDevice.cpp index 03a740f5fbf..a8b2625b848 100644 --- a/intern/audaspace/jack/AUD_JackDevice.cpp +++ b/intern/audaspace/jack/AUD_JackDevice.cpp @@ -28,8 +28,6 @@ * \ingroup audjack */ - -#include "AUD_Mixer.h" #include "AUD_JackDevice.h" #include "AUD_IReader.h" diff --git a/intern/audaspace/sndfile/AUD_SndFileFactory.cpp b/intern/audaspace/sndfile/AUD_SndFileFactory.cpp index 2d1d29e50f5..5a0280cdf84 100644 --- a/intern/audaspace/sndfile/AUD_SndFileFactory.cpp +++ b/intern/audaspace/sndfile/AUD_SndFileFactory.cpp @@ -43,13 +43,13 @@ AUD_SndFileFactory::AUD_SndFileFactory(std::string filename) : AUD_SndFileFactory::AUD_SndFileFactory(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_SndFileFactory::createReader() const +AUD_Reference<AUD_IReader> AUD_SndFileFactory::createReader() { - if(m_buffer.get()) - return new AUD_SndFileReader(m_buffer); - else + if(m_buffer.isNull()) return new AUD_SndFileReader(m_filename); + else + return new AUD_SndFileReader(m_buffer); } diff --git a/intern/audaspace/sndfile/AUD_SndFileFactory.h b/intern/audaspace/sndfile/AUD_SndFileFactory.h index 9c747e1df01..a46dc165264 100644 --- a/intern/audaspace/sndfile/AUD_SndFileFactory.h +++ b/intern/audaspace/sndfile/AUD_SndFileFactory.h @@ -72,7 +72,7 @@ public: */ AUD_SndFileFactory(const data_t* buffer, int size); - virtual AUD_IReader* createReader() const; + virtual AUD_Reference<AUD_IReader> createReader(); }; #endif //AUD_SNDFILEFACTORY diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.cpp b/intern/audaspace/sndfile/AUD_SndFileReader.cpp index f226d2eee4d..16c90b6f0f1 100644 --- a/intern/audaspace/sndfile/AUD_SndFileReader.cpp +++ b/intern/audaspace/sndfile/AUD_SndFileReader.cpp @@ -36,7 +36,7 @@ sf_count_t AUD_SndFileReader::vio_get_filelen(void *user_data) { AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; - return reader->m_membuffer.get()->getSize(); + return reader->m_membuffer->getSize(); } sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence, @@ -53,7 +53,7 @@ sf_count_t AUD_SndFileReader::vio_seek(sf_count_t offset, int whence, reader->m_memoffset = reader->m_memoffset + offset; break; case SEEK_END: - reader->m_memoffset = reader->m_membuffer.get()->getSize() + offset; + reader->m_memoffset = reader->m_membuffer->getSize() + offset; break; } @@ -65,10 +65,10 @@ sf_count_t AUD_SndFileReader::vio_read(void *ptr, sf_count_t count, { AUD_SndFileReader* reader = (AUD_SndFileReader*)user_data; - if(reader->m_memoffset + count > reader->m_membuffer.get()->getSize()) - count = reader->m_membuffer.get()->getSize() - reader->m_memoffset; + if(reader->m_memoffset + count > reader->m_membuffer->getSize()) + count = reader->m_membuffer->getSize() - reader->m_memoffset; - memcpy(ptr, ((data_t*)reader->m_membuffer.get()->getBuffer()) + + memcpy(ptr, ((data_t*)reader->m_membuffer->getBuffer()) + reader->m_memoffset, count); reader->m_memoffset += count; @@ -161,17 +161,13 @@ AUD_Specs AUD_SndFileReader::getSpecs() const return m_specs; } -void AUD_SndFileReader::read(int & length, sample_t* & buffer) +void AUD_SndFileReader::read(int& length, bool& eos, sample_t* buffer) { - int sample_size = AUD_SAMPLE_SIZE(m_specs); - - // resize output buffer if necessary - if(m_buffer.getSize() < length*sample_size) - m_buffer.resize(length*sample_size); - - buffer = m_buffer.getBuffer(); + int olen = length; length = sf_readf_float(m_sndfile, buffer, length); m_position += length; + + eos = length < olen; } diff --git a/intern/audaspace/sndfile/AUD_SndFileReader.h b/intern/audaspace/sndfile/AUD_SndFileReader.h index af095819c0e..e7f9e9bf6d6 100644 --- a/intern/audaspace/sndfile/AUD_SndFileReader.h +++ b/intern/audaspace/sndfile/AUD_SndFileReader.h @@ -68,11 +68,6 @@ private: AUD_Specs m_specs; /** - * The playback buffer. - */ - AUD_Buffer m_buffer; - - /** * The sndfile. */ SNDFILE* m_sndfile; @@ -129,7 +124,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_SNDFILEREADER |