Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorJoerg Mueller <nexyon@gmail.com>2009-07-20 16:05:18 +0400
committerJoerg Mueller <nexyon@gmail.com>2009-07-20 16:05:18 +0400
commit94ff22d9e18363010e663583df8d89cbe00a774e (patch)
tree38ff2c01d083630a035474393ad6b190d3f16a7d /intern
parent456672efd0ee7c7fe27866347da56f6dd2480769 (diff)
audaspace update including build system adoptions for linux, all other OSs are not expected to work yet due to missing libsamplerate aka SRC
Diffstat (limited to 'intern')
-rw-r--r--intern/audaspace/AUD_C-API.h17
-rw-r--r--intern/audaspace/CMakeLists.txt31
-rw-r--r--intern/audaspace/FX/AUD_DelayFactory.cpp58
-rw-r--r--intern/audaspace/FX/AUD_DelayFactory.h70
-rw-r--r--intern/audaspace/FX/AUD_DelayReader.cpp111
-rw-r--r--intern/audaspace/FX/AUD_DelayReader.h73
-rw-r--r--intern/audaspace/FX/AUD_DoubleReader.cpp158
-rw-r--r--intern/audaspace/FX/AUD_DoubleReader.h83
-rw-r--r--intern/audaspace/FX/AUD_EffectFactory.cpp50
-rw-r--r--intern/audaspace/FX/AUD_EffectFactory.h76
-rw-r--r--intern/audaspace/FX/AUD_EffectReader.cpp78
-rw-r--r--intern/audaspace/FX/AUD_EffectReader.h66
-rw-r--r--intern/audaspace/FX/AUD_FaderFactory.cpp84
-rw-r--r--intern/audaspace/FX/AUD_FaderFactory.h111
-rw-r--r--intern/audaspace/FX/AUD_FaderReader.cpp133
-rw-r--r--intern/audaspace/FX/AUD_FaderReader.h86
-rw-r--r--intern/audaspace/FX/AUD_LimiterFactory.cpp67
-rw-r--r--intern/audaspace/FX/AUD_LimiterFactory.h84
-rw-r--r--intern/audaspace/FX/AUD_LimiterReader.cpp95
-rw-r--r--intern/audaspace/FX/AUD_LimiterReader.h64
-rw-r--r--intern/audaspace/FX/AUD_LoopFactory.cpp57
-rw-r--r--intern/audaspace/FX/AUD_LoopFactory.h74
-rw-r--r--intern/audaspace/FX/AUD_LoopReader.cpp107
-rw-r--r--intern/audaspace/FX/AUD_LoopReader.h69
-rw-r--r--intern/audaspace/FX/AUD_PingPongFactory.cpp67
-rw-r--r--intern/audaspace/FX/AUD_PingPongFactory.h (renamed from intern/audaspace/intern/AUD_ISuperposer.h)28
-rw-r--r--intern/audaspace/FX/AUD_PitchFactory.cpp52
-rw-r--r--intern/audaspace/FX/AUD_PitchFactory.h70
-rw-r--r--intern/audaspace/FX/AUD_PitchReader.cpp (renamed from intern/audaspace/SDL/AUD_SDLSuperposer.cpp)19
-rw-r--r--intern/audaspace/FX/AUD_PitchReader.h54
-rw-r--r--intern/audaspace/FX/AUD_ReverseFactory.cpp43
-rw-r--r--intern/audaspace/FX/AUD_ReverseFactory.h50
-rw-r--r--intern/audaspace/FX/AUD_ReverseReader.cpp111
-rw-r--r--intern/audaspace/FX/AUD_ReverseReader.h74
-rw-r--r--intern/audaspace/FX/AUD_VolumeFactory.cpp57
-rw-r--r--intern/audaspace/FX/AUD_VolumeFactory.h72
-rw-r--r--intern/audaspace/FX/AUD_VolumeReader.cpp97
-rw-r--r--intern/audaspace/FX/AUD_VolumeReader.h72
-rw-r--r--intern/audaspace/OpenAL/AUD_OpenALDevice.cpp1286
-rw-r--r--intern/audaspace/OpenAL/AUD_OpenALDevice.h170
-rw-r--r--intern/audaspace/SConscript19
-rw-r--r--intern/audaspace/SDL/AUD_SDLDevice.cpp46
-rw-r--r--intern/audaspace/SDL/AUD_SDLDevice.h17
-rw-r--r--intern/audaspace/SDL/AUD_SDLMixer.cpp83
-rw-r--r--intern/audaspace/SDL/AUD_SDLMixer.h76
-rw-r--r--intern/audaspace/SDL/AUD_SDLMixerFactory.cpp32
-rw-r--r--intern/audaspace/SDL/AUD_SDLMixerFactory.h9
-rw-r--r--intern/audaspace/SDL/AUD_SDLMixerReader.cpp20
-rw-r--r--intern/audaspace/SDL/AUD_SDLMixerReader.h1
-rw-r--r--intern/audaspace/SRC/AUD_SRCResampleFactory.cpp53
-rw-r--r--intern/audaspace/SRC/AUD_SRCResampleFactory.h46
-rw-r--r--intern/audaspace/SRC/AUD_SRCResampleReader.cpp119
-rw-r--r--intern/audaspace/SRC/AUD_SRCResampleReader.h102
-rw-r--r--intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp19
-rw-r--r--intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp58
-rw-r--r--intern/audaspace/ffmpeg/AUD_FFMPEGReader.h7
-rw-r--r--intern/audaspace/intern/AUD_Buffer.cpp10
-rw-r--r--intern/audaspace/intern/AUD_Buffer.h10
-rw-r--r--intern/audaspace/intern/AUD_BufferReader.cpp9
-rw-r--r--intern/audaspace/intern/AUD_BufferReader.h1
-rw-r--r--intern/audaspace/intern/AUD_C-API.cpp18
-rw-r--r--intern/audaspace/intern/AUD_ChannelMapperFactory.cpp125
-rw-r--r--intern/audaspace/intern/AUD_ChannelMapperFactory.h65
-rw-r--r--intern/audaspace/intern/AUD_ChannelMapperReader.cpp108
-rw-r--r--intern/audaspace/intern/AUD_ChannelMapperReader.h76
-rw-r--r--intern/audaspace/intern/AUD_ConverterFactory.cpp54
-rw-r--r--intern/audaspace/intern/AUD_ConverterFactory.h (renamed from intern/audaspace/SDL/AUD_SDLSuperposer.h)24
-rw-r--r--intern/audaspace/intern/AUD_ConverterFunctions.cpp502
-rw-r--r--intern/audaspace/intern/AUD_ConverterFunctions.h156
-rw-r--r--intern/audaspace/intern/AUD_ConverterReader.cpp244
-rw-r--r--intern/audaspace/intern/AUD_ConverterReader.h71
-rw-r--r--intern/audaspace/intern/AUD_FloatMixer.cpp170
-rw-r--r--intern/audaspace/intern/AUD_FloatMixer.h100
-rw-r--r--intern/audaspace/intern/AUD_I3DDevice.h150
-rw-r--r--intern/audaspace/intern/AUD_IDevice.h63
-rw-r--r--intern/audaspace/intern/AUD_IMixer.h77
-rw-r--r--intern/audaspace/intern/AUD_IReader.h16
-rw-r--r--intern/audaspace/intern/AUD_MixerFactory.cpp8
-rw-r--r--intern/audaspace/intern/AUD_MixerFactory.h2
-rw-r--r--intern/audaspace/intern/AUD_NULLDevice.cpp103
-rw-r--r--intern/audaspace/intern/AUD_NULLDevice.h64
-rw-r--r--intern/audaspace/intern/AUD_ReadDevice.cpp64
-rw-r--r--intern/audaspace/intern/AUD_ReadDevice.h68
-rw-r--r--intern/audaspace/intern/AUD_Reference.h14
-rw-r--r--intern/audaspace/intern/AUD_ResampleFactory.h33
-rw-r--r--intern/audaspace/intern/AUD_SinusReader.cpp11
-rw-r--r--intern/audaspace/intern/AUD_SinusReader.h1
-rw-r--r--intern/audaspace/intern/AUD_SoftwareDevice.cpp363
-rw-r--r--intern/audaspace/intern/AUD_SoftwareDevice.h45
-rw-r--r--intern/audaspace/intern/AUD_SourceCaps.h41
-rw-r--r--intern/audaspace/intern/AUD_Space.h104
-rw-r--r--intern/audaspace/intern/AUD_StreamBufferFactory.cpp8
92 files changed, 7507 insertions, 402 deletions
diff --git a/intern/audaspace/AUD_C-API.h b/intern/audaspace/AUD_C-API.h
index 9243c8756ec..e89e53a88cc 100644
--- a/intern/audaspace/AUD_C-API.h
+++ b/intern/audaspace/AUD_C-API.h
@@ -72,16 +72,11 @@ extern void AUD_unload(AUD_Sound* sound);
/**
* Plays back a sound file.
* \param sound The handle of the sound file.
- * \param endBehaviour The behaviour after the end of the sound file has been
- * reached.
- * \param seekTo From where the sound file should be played back in seconds.
- * A negative value indicates the seconds that should be waited
- * before playback starts.
+ * \param keep When keep is true the sound source will not be deleted but set to
+ * paused when its end has been reached.
* \return A handle to the played back sound.
*/
-extern AUD_Handle* AUD_play(AUD_Sound* sound,
- AUD_EndBehaviour endBehaviour,
- double seekTo);
+extern AUD_Handle* AUD_play(AUD_Sound* sound, int keep);
/**
* Pauses a played back sound.
@@ -107,11 +102,11 @@ extern int AUD_stop(AUD_Handle* handle);
/**
* Sets the end behaviour of a playing or paused sound.
* \param handle The handle to the sound.
- * \param endBehaviour The behaviour after the end of the file has been reached.
+ * \param keep When keep is true the sound source will not be deleted but set to
+ * paused when its end has been reached.
* \return Whether the handle has been valid or not.
*/
-extern int AUD_setEndBehaviour(AUD_Handle* handle,
- AUD_EndBehaviour endBehaviour);
+extern int AUD_setKeep(AUD_Handle* handle, int keep);
/**
* Seeks a playing or paused sound.
diff --git a/intern/audaspace/CMakeLists.txt b/intern/audaspace/CMakeLists.txt
index 3eed151732a..c0716e2057c 100644
--- a/intern/audaspace/CMakeLists.txt
+++ b/intern/audaspace/CMakeLists.txt
@@ -20,14 +20,33 @@
#
# ***** END LGPL LICENSE BLOCK *****
-SET(INC . intern SDL ffmpeg)
+SET(INC . intern FX SRC ${PTHREADS_INC} ${LIBSAMPLERATE_INC})
+
+FILE(GLOB SRC intern/*.cpp intern/*.h FX/*.cpp SRC/*.cpp)
IF(WITH_FFMPEG)
- FILE(GLOB SRC ffmpeg/*.cpp SDL/*.cpp intern/*.cpp intern/*.h)
- INCLUDE_DIRECTORIES(${SDL_INC} ${FFMPEG_INC} ${PTHREADS_INC})
-ELSE(WITH_FFMPEG)
- FILE(GLOB SRC SDL/*.cpp intern/*.cpp intern/*.h)
- INCLUDE_DIRECTORIES(${SDL_INC} ${PTHREADS_INC})
+ SET(INC ${INC} ffmpeg ${FFMPEG_INC})
+ FILE(GLOB FFMPEGSRC ffmpeg/*.cpp)
+ ADD_DEFINITIONS(-DWITH_FFMPEG)
ENDIF(WITH_FFMPEG)
+IF(WITH_SDL)
+ SET(INC ${INC} SDL ${SDL_INC})
+ FILE(GLOB SDLSRC SDL/*.cpp)
+ ADD_DEFINITIONS(-DWITH_SDL)
+ENDIF(WITH_SDL)
+
+IF(WITH_OPENAL)
+ SET(INC ${INC} OpenAL ${OPENAL_INC})
+ FILE(GLOB OPENALSRC OpenAL/*.cpp)
+ ADD_DEFINITIONS(-DWITH_OPENAL)
+
+ STRING(REGEX MATCH ".*ramework.*" FRAMEWORK ${OPENAL_INC})
+ IF(FRAMEWORK)
+ ADD_DEFINITIONS(-DAPPLE_FRAMEWORK_FIX)
+ ENDIF(FRAMEWORK)
+ENDIF(WITH_OPENAL)
+
+SET(SRC ${SRC} ${FFMPEGSRC} ${SDLSRC} ${OPENALSRC})
+
BLENDERLIB(bf_audaspace "${SRC}" "${INC}")
diff --git a/intern/audaspace/FX/AUD_DelayFactory.cpp b/intern/audaspace/FX/AUD_DelayFactory.cpp
new file mode 100644
index 00000000000..25ce4faed4c
--- /dev/null
+++ b/intern/audaspace/FX/AUD_DelayFactory.cpp
@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_DelayFactory.h"
+#include "AUD_DelayReader.h"
+#include "AUD_Space.h"
+
+AUD_DelayFactory::AUD_DelayFactory(AUD_IFactory* factory, float delay) :
+ AUD_EffectFactory(factory),
+ m_delay(delay) {}
+
+AUD_DelayFactory::AUD_DelayFactory(float delay) :
+ AUD_EffectFactory(0),
+ m_delay(delay) {}
+
+float AUD_DelayFactory::getDelay()
+{
+ return m_delay;
+}
+
+void AUD_DelayFactory::setDelay(float delay)
+{
+ m_delay = delay;
+}
+
+AUD_IReader* AUD_DelayFactory::createReader()
+{
+ AUD_IReader* reader = getReader();
+
+ if(reader != 0)
+ {
+ reader = new AUD_DelayReader(reader, m_delay); AUD_NEW("reader")
+ }
+
+ return reader;
+}
diff --git a/intern/audaspace/FX/AUD_DelayFactory.h b/intern/audaspace/FX/AUD_DelayFactory.h
new file mode 100644
index 00000000000..5ad4b9ab996
--- /dev/null
+++ b/intern/audaspace/FX/AUD_DelayFactory.h
@@ -0,0 +1,70 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_DELAYFACTORY
+#define AUD_DELAYFACTORY
+
+#include "AUD_EffectFactory.h"
+
+/**
+ * This factory plays another factory delayed.
+ */
+class AUD_DelayFactory : public AUD_EffectFactory
+{
+private:
+ /**
+ * The delay in samples.
+ */
+ float m_delay;
+
+public:
+ /**
+ * Creates a new delay factory.
+ * \param factory The input factory.
+ * \param delay The desired delay in seconds.
+ */
+ AUD_DelayFactory(AUD_IFactory* factory = 0, float delay = 0);
+
+ /**
+ * Creates a new delay factory.
+ * \param delay The desired delay in seconds.
+ */
+ AUD_DelayFactory(float delay);
+
+ /**
+ * Returns the delay in seconds.
+ */
+ float getDelay();
+
+ /**
+ * Sets the delay.
+ * \param delay The new delay value in seconds.
+ */
+ void setDelay(float delay);
+
+ virtual AUD_IReader* createReader();
+};
+
+#endif //AUD_DELAYFACTORY
diff --git a/intern/audaspace/FX/AUD_DelayReader.cpp b/intern/audaspace/FX/AUD_DelayReader.cpp
new file mode 100644
index 00000000000..38d3b893b5c
--- /dev/null
+++ b/intern/audaspace/FX/AUD_DelayReader.cpp
@@ -0,0 +1,111 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_DelayReader.h"
+#include "AUD_Buffer.h"
+
+#include <cstring>
+
+AUD_DelayReader::AUD_DelayReader(AUD_IReader* reader, float delay) :
+ AUD_EffectReader(reader)
+{
+ m_delay = (int)(delay * reader->getSpecs().rate);
+ m_remdelay = m_delay;
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+}
+
+AUD_DelayReader::~AUD_DelayReader()
+{
+ delete m_buffer; AUD_DELETE("buffer")
+}
+
+void AUD_DelayReader::seek(int position)
+{
+ if(position < 0)
+ return;
+
+ if(position < m_delay)
+ {
+ m_remdelay = m_delay - position;
+ m_reader->seek(0);
+ }
+ else
+ {
+ m_remdelay = 0;
+ m_reader->seek(position - m_delay);
+ }
+}
+
+int AUD_DelayReader::getLength()
+{
+ int len = m_reader->getLength();
+ if(len < 0)
+ return len;
+ return len+m_delay;
+}
+
+int AUD_DelayReader::getPosition()
+{
+ if(m_remdelay > 0)
+ return m_delay-m_remdelay;
+ return m_reader->getPosition() + m_delay;
+}
+
+void AUD_DelayReader::read(int & length, sample_t* & buffer)
+{
+ if(m_remdelay > 0)
+ {
+ int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs());
+
+ if(m_buffer->getSize() < length*samplesize)
+ m_buffer->resize(length*samplesize);
+
+ if(length > m_remdelay)
+ {
+ if(getSpecs().format == AUD_FORMAT_U8)
+ memset(m_buffer->getBuffer(), 0x80, m_remdelay*samplesize);
+ else
+ memset(m_buffer->getBuffer(), 0, m_remdelay*samplesize);
+ int len = length - m_remdelay;
+ m_reader->read(len, buffer);
+ memcpy(m_buffer->getBuffer()+m_remdelay*samplesize,
+ buffer, len*samplesize);
+ if(len < length-m_remdelay)
+ length = m_remdelay + len;
+ m_remdelay = 0;
+ }
+ else
+ {
+ if(getSpecs().format == AUD_FORMAT_U8)
+ memset(m_buffer->getBuffer(), 0x80, length*samplesize);
+ else
+ memset(m_buffer->getBuffer(), 0, length*samplesize);
+ m_remdelay -= length;
+ }
+ buffer = m_buffer->getBuffer();
+ }
+ else
+ m_reader->read(length, buffer);
+}
diff --git a/intern/audaspace/FX/AUD_DelayReader.h b/intern/audaspace/FX/AUD_DelayReader.h
new file mode 100644
index 00000000000..4662b455dfc
--- /dev/null
+++ b/intern/audaspace/FX/AUD_DelayReader.h
@@ -0,0 +1,73 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_DELAYREADER
+#define AUD_DELAYREADER
+
+#include "AUD_EffectReader.h"
+class AUD_Buffer;
+
+/**
+ * This class reads another reader and changes it's delay.
+ */
+class AUD_DelayReader : public AUD_EffectReader
+{
+private:
+ /**
+ * The playback buffer.
+ */
+ AUD_Buffer *m_buffer;
+
+ /**
+ * The delay level.
+ */
+ int m_delay;
+
+ /**
+ * The remaining delay for playback.
+ */
+ int m_remdelay;
+
+public:
+ /**
+ * Creates a new delay reader.
+ * \param reader The reader to read from.
+ * \param delay The delay in seconds.
+ * \exception AUD_Exception Thrown if the reader specified is NULL.
+ */
+ AUD_DelayReader(AUD_IReader* reader, float delay);
+
+ /**
+ * Destroys the reader.
+ */
+ virtual ~AUD_DelayReader();
+
+ virtual void seek(int position);
+ virtual int getLength();
+ virtual int getPosition();
+ virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_DELAYREADER
diff --git a/intern/audaspace/FX/AUD_DoubleReader.cpp b/intern/audaspace/FX/AUD_DoubleReader.cpp
new file mode 100644
index 00000000000..181e394da98
--- /dev/null
+++ b/intern/audaspace/FX/AUD_DoubleReader.cpp
@@ -0,0 +1,158 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_DoubleReader.h"
+#include "AUD_Buffer.h"
+
+#include <cstring>
+
+AUD_DoubleReader::AUD_DoubleReader(AUD_IReader* reader1,
+ AUD_IReader* reader2) :
+ m_reader1(reader1), m_reader2(reader2)
+{
+ try
+ {
+ if(!reader1)
+ AUD_THROW(AUD_ERROR_READER);
+
+ if(!reader2)
+ AUD_THROW(AUD_ERROR_READER);
+
+ AUD_Specs s1, s2;
+ s1 = reader1->getSpecs();
+ s2 = reader2->getSpecs();
+ if(memcmp(&s1, &s2, sizeof(AUD_Specs)) != 0)
+ AUD_THROW(AUD_ERROR_READER);
+ }
+
+ catch(AUD_Exception e)
+ {
+ if(reader1)
+ {
+ delete reader1; AUD_DELETE("reader")
+ }
+ if(reader2)
+ {
+ delete reader2; AUD_DELETE("reader")
+ }
+
+ throw;
+ }
+
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+ m_finished1 = false;
+}
+
+AUD_DoubleReader::~AUD_DoubleReader()
+{
+ delete m_reader1; AUD_DELETE("reader")
+ delete m_reader2; AUD_DELETE("reader")
+ delete m_buffer; AUD_DELETE("buffer")
+}
+
+bool AUD_DoubleReader::isSeekable()
+{
+ return false;
+}
+
+void AUD_DoubleReader::seek(int position)
+{
+ int length1 = m_reader1->getLength();
+
+ if(position < 0)
+ position = 0;
+
+ if(position < length1)
+ {
+ m_reader1->seek(position);
+ m_reader2->seek(0);
+ m_finished1 = false;
+ }
+ else
+ {
+ m_reader2->seek(position-length1);
+ m_finished1 = true;
+ }
+}
+
+int AUD_DoubleReader::getLength()
+{
+ int len1 = m_reader1->getLength();
+ int len2 = m_reader2->getLength();
+ if(len1 < 0 || len2 < 0)
+ return -1;
+ return len1 + len2;
+}
+
+int AUD_DoubleReader::getPosition()
+{
+ return m_reader1->getPosition() + m_reader2->getPosition();
+}
+
+AUD_Specs AUD_DoubleReader::getSpecs()
+{
+ return m_reader1->getSpecs();
+}
+
+AUD_ReaderType AUD_DoubleReader::getType()
+{
+ if(m_reader1->getType() == AUD_TYPE_BUFFER &&
+ m_reader2->getType() == AUD_TYPE_BUFFER)
+ return AUD_TYPE_BUFFER;
+ return AUD_TYPE_STREAM;
+}
+
+bool AUD_DoubleReader::notify(AUD_Message &message)
+{
+ return m_reader1->notify(message) | m_reader2->notify(message);
+}
+
+void AUD_DoubleReader::read(int & length, sample_t* & buffer)
+{
+ if(!m_finished1)
+ {
+ int len = length;
+ m_reader1->read(len, buffer);
+ if(len < length)
+ {
+ int samplesize = AUD_SAMPLE_SIZE(m_reader1->getSpecs());
+ if(m_buffer->getSize() < length * samplesize)
+ m_buffer->resize(length * samplesize);
+ memcpy(m_buffer->getBuffer(), buffer, len*samplesize);
+ len = length - len;
+ length -= len;
+ m_reader2->read(len, buffer);
+ memcpy(m_buffer->getBuffer() + length*samplesize,
+ buffer, len*samplesize);
+ length += len;
+ buffer = m_buffer->getBuffer();
+ m_finished1 = true;
+ }
+ }
+ else
+ {
+ m_reader2->read(length, buffer);
+ }
+}
diff --git a/intern/audaspace/FX/AUD_DoubleReader.h b/intern/audaspace/FX/AUD_DoubleReader.h
new file mode 100644
index 00000000000..d82b81ec0ba
--- /dev/null
+++ b/intern/audaspace/FX/AUD_DoubleReader.h
@@ -0,0 +1,83 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_DOUBLEREADER
+#define AUD_DOUBLEREADER
+
+#include "AUD_IReader.h"
+class AUD_Buffer;
+
+/**
+ * This reader plays two readers with the same specs sequently.
+ */
+class AUD_DoubleReader : public AUD_IReader
+{
+private:
+ /**
+ * The first reader.
+ */
+ AUD_IReader* m_reader1;
+
+ /**
+ * The second reader.
+ */
+ AUD_IReader* m_reader2;
+
+ /**
+ * Whether we've reached the end of the first reader.
+ */
+ bool m_finished1;
+
+ /**
+ * The playback buffer for the intersecting part.
+ */
+ AUD_Buffer* m_buffer;
+
+public:
+ /**
+ * Creates a new ping pong reader.
+ * \param reader1 The first reader to read from.
+ * \param reader2 The second reader to read from.
+ * \exception AUD_Exception Thrown if one of the reader specified is NULL
+ * or the specs from the readers differ.
+ */
+ AUD_DoubleReader(AUD_IReader* reader1, AUD_IReader* reader2);
+
+ /**
+ * Destroys the reader.
+ */
+ virtual ~AUD_DoubleReader();
+
+ virtual bool isSeekable();
+ virtual void seek(int position);
+ virtual int getLength();
+ virtual int getPosition();
+ virtual AUD_Specs getSpecs();
+ virtual AUD_ReaderType getType();
+ virtual bool notify(AUD_Message &message);
+ virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_DOUBLEREADER
diff --git a/intern/audaspace/FX/AUD_EffectFactory.cpp b/intern/audaspace/FX/AUD_EffectFactory.cpp
new file mode 100644
index 00000000000..882499416b7
--- /dev/null
+++ b/intern/audaspace/FX/AUD_EffectFactory.cpp
@@ -0,0 +1,50 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_EffectFactory.h"
+#include "AUD_IReader.h"
+
+AUD_IReader* AUD_EffectFactory::getReader()
+{
+ if(m_factory != 0)
+ return m_factory->createReader();
+
+ return 0;
+}
+
+AUD_EffectFactory::AUD_EffectFactory(AUD_IFactory* factory)
+{
+ m_factory = factory;
+}
+
+void AUD_EffectFactory::setFactory(AUD_IFactory* factory)
+{
+ m_factory = factory;
+}
+
+AUD_IFactory* AUD_EffectFactory::getFactory()
+{
+ return m_factory;
+}
diff --git a/intern/audaspace/FX/AUD_EffectFactory.h b/intern/audaspace/FX/AUD_EffectFactory.h
new file mode 100644
index 00000000000..67259b9e6c3
--- /dev/null
+++ b/intern/audaspace/FX/AUD_EffectFactory.h
@@ -0,0 +1,76 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_EFFECTFACTORY
+#define AUD_EFFECTFACTORY
+
+#include "AUD_IFactory.h"
+
+/**
+ * This factory is a base class for all effect factories that take one other
+ * factory as input.
+ */
+class AUD_EffectFactory : public AUD_IFactory
+{
+protected:
+ /**
+ * If there is no reader it is created out of this factory.
+ */
+ AUD_IFactory* m_factory;
+
+ /**
+ * Returns the reader created out of the factory.
+ * This method can be used for the createReader function of the implementing
+ * classes.
+ * \return The reader created out of the factory or NULL if there is none.
+ */
+ AUD_IReader* getReader();
+
+public:
+ /**
+ * Creates a new factory.
+ * \param factory The input factory.
+ */
+ AUD_EffectFactory(AUD_IFactory* factory);
+
+ /**
+ * Destroys the factory.
+ */
+ virtual ~AUD_EffectFactory() {}
+
+ /**
+ * Sets the input factory.
+ * \param factory The input factory.
+ */
+ void setFactory(AUD_IFactory* factory);
+
+ /**
+ * Returns the saved factory.
+ * \return The factory or NULL if there has no factory been saved.
+ */
+ AUD_IFactory* getFactory();
+};
+
+#endif //AUD_EFFECTFACTORY
diff --git a/intern/audaspace/FX/AUD_EffectReader.cpp b/intern/audaspace/FX/AUD_EffectReader.cpp
new file mode 100644
index 00000000000..47026b88440
--- /dev/null
+++ b/intern/audaspace/FX/AUD_EffectReader.cpp
@@ -0,0 +1,78 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_EffectReader.h"
+
+AUD_EffectReader::AUD_EffectReader(AUD_IReader* reader)
+{
+ if(!reader)
+ AUD_THROW(AUD_ERROR_READER);
+ m_reader = reader;
+}
+
+AUD_EffectReader::~AUD_EffectReader()
+{
+ delete m_reader; AUD_DELETE("reader")
+}
+
+bool AUD_EffectReader::isSeekable()
+{
+ return m_reader->isSeekable();
+}
+
+void AUD_EffectReader::seek(int position)
+{
+ m_reader->seek(position);
+}
+
+int AUD_EffectReader::getLength()
+{
+ return m_reader->getLength();
+}
+
+int AUD_EffectReader::getPosition()
+{
+ return m_reader->getPosition();
+}
+
+AUD_Specs AUD_EffectReader::getSpecs()
+{
+ return m_reader->getSpecs();
+}
+
+AUD_ReaderType AUD_EffectReader::getType()
+{
+ return m_reader->getType();
+}
+
+bool AUD_EffectReader::notify(AUD_Message &message)
+{
+ return m_reader->notify(message);
+}
+
+void AUD_EffectReader::read(int & length, sample_t* & buffer)
+{
+ m_reader->read(length, buffer);
+}
diff --git a/intern/audaspace/FX/AUD_EffectReader.h b/intern/audaspace/FX/AUD_EffectReader.h
new file mode 100644
index 00000000000..f64bf34077d
--- /dev/null
+++ b/intern/audaspace/FX/AUD_EffectReader.h
@@ -0,0 +1,66 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_EFFECTREADER
+#define AUD_EFFECTREADER
+
+#include "AUD_IReader.h"
+
+/**
+ * This reader is a base class for all effect readers that take one other reader
+ * as input.
+ */
+class AUD_EffectReader : public AUD_IReader
+{
+protected:
+ /**
+ * The reader to read from.
+ */
+ AUD_IReader* m_reader;
+
+public:
+ /**
+ * Creates a new effect reader.
+ * \param reader The reader to read from.
+ * \exception AUD_Exception Thrown if the reader specified is NULL.
+ */
+ AUD_EffectReader(AUD_IReader* reader);
+
+ /**
+ * Destroys the reader.
+ */
+ virtual ~AUD_EffectReader();
+
+ virtual bool isSeekable();
+ virtual void seek(int position);
+ virtual int getLength();
+ virtual int getPosition();
+ virtual AUD_Specs getSpecs();
+ virtual AUD_ReaderType getType();
+ virtual bool notify(AUD_Message &message);
+ virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_EFFECTREADER
diff --git a/intern/audaspace/FX/AUD_FaderFactory.cpp b/intern/audaspace/FX/AUD_FaderFactory.cpp
new file mode 100644
index 00000000000..4357e11bd43
--- /dev/null
+++ b/intern/audaspace/FX/AUD_FaderFactory.cpp
@@ -0,0 +1,84 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_FaderFactory.h"
+#include "AUD_FaderReader.h"
+
+AUD_FaderFactory::AUD_FaderFactory(AUD_IFactory* factory, AUD_FadeType type,
+ float start, float length) :
+ AUD_EffectFactory(factory),
+ m_type(type),
+ m_start(start),
+ m_length(length) {}
+
+AUD_FaderFactory::AUD_FaderFactory(AUD_FadeType type,
+ float start, float length) :
+ AUD_EffectFactory(0),
+ m_type(type),
+ m_start(start),
+ m_length(length) {}
+
+AUD_FadeType AUD_FaderFactory::getType()
+{
+ return m_type;
+}
+
+void AUD_FaderFactory::setType(AUD_FadeType type)
+{
+ m_type = type;
+}
+
+float AUD_FaderFactory::getStart()
+{
+ return m_start;
+}
+
+void AUD_FaderFactory::setStart(float start)
+{
+ m_start = start;
+}
+
+float AUD_FaderFactory::getLength()
+{
+ return m_length;
+}
+
+void AUD_FaderFactory::setLength(float length)
+{
+ m_length = length;
+}
+
+AUD_IReader* AUD_FaderFactory::createReader()
+{
+ AUD_IReader* reader = getReader();
+
+ if(reader != 0)
+ {
+ reader = new AUD_FaderReader(reader, m_type, m_start, m_length);
+ AUD_NEW("reader")
+ }
+
+ return reader;
+}
diff --git a/intern/audaspace/FX/AUD_FaderFactory.h b/intern/audaspace/FX/AUD_FaderFactory.h
new file mode 100644
index 00000000000..4999ccac8f1
--- /dev/null
+++ b/intern/audaspace/FX/AUD_FaderFactory.h
@@ -0,0 +1,111 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_FADERFACTORY
+#define AUD_FADERFACTORY
+
+#include "AUD_EffectFactory.h"
+
+/**
+ * This factory fades another factory.
+ * If the fading type is AUD_FADE_IN, everything before the fading start will be
+ * silenced, for AUD_FADE_OUT that's true for everything after fading ends.
+ */
+class AUD_FaderFactory : public AUD_EffectFactory
+{
+private:
+ /**
+ * The fading type.
+ */
+ AUD_FadeType m_type;
+
+ /**
+ * The fading start.
+ */
+ float m_start;
+
+ /**
+ * The fading length.
+ */
+ float m_length;
+
+public:
+ /**
+ * Creates a new fader factory.
+ * \param factory The input factory.
+ * \param type The fading type.
+ * \param start The time where fading should start in seconds.
+ * \param length How long fading should last in seconds.
+ */
+ AUD_FaderFactory(AUD_IFactory* factory = 0,
+ AUD_FadeType type = AUD_FADE_IN,
+ float start = 0.0f, float length = 1.0f);
+
+ /**
+ * Creates a new fader factory.
+ * \param type The fading type.
+ * \param start The time where fading should start in seconds.
+ * \param length How long fading should last in seconds.
+ */
+ AUD_FaderFactory(AUD_FadeType type = AUD_FADE_IN,
+ float start = 0.0f, float length = 1.0f);
+
+ /**
+ * Returns the fading type.
+ */
+ AUD_FadeType getType();
+
+ /**
+ * Sets the fading type.
+ * \param type The new fading type: AUD_FADE_IN or AUD_FADE_OUT.
+ */
+ void setType(AUD_FadeType type);
+
+ /**
+ * Returns the fading start.
+ */
+ float getStart();
+
+ /**
+ * Sets the fading start.
+ * \param start The new fading start.
+ */
+ void setStart(float start);
+
+ /**
+ * Returns the fading length.
+ */
+ float getLength();
+
+ /**
+ * Sets the fading length.
+ * \param start The new fading length.
+ */
+ void setLength(float length);
+
+ virtual AUD_IReader* createReader();
+};
+
+#endif //AUD_FADERFACTORY
diff --git a/intern/audaspace/FX/AUD_FaderReader.cpp b/intern/audaspace/FX/AUD_FaderReader.cpp
new file mode 100644
index 00000000000..d5096e7fae1
--- /dev/null
+++ b/intern/audaspace/FX/AUD_FaderReader.cpp
@@ -0,0 +1,133 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_FaderReader.h"
+#include "AUD_Buffer.h"
+
+#include <cstring>
+
+AUD_FaderReader::AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type,
+ float start,float length) :
+ AUD_EffectReader(reader),
+ m_type(type),
+ m_start(start),
+ m_length(length)
+{
+ int bigendian = 1;
+ bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
+
+ switch(m_reader->getSpecs().format)
+ {
+ case AUD_FORMAT_S16:
+ m_adjust = AUD_volume_adjust<int16_t>;
+ break;
+ case AUD_FORMAT_S32:
+ m_adjust = AUD_volume_adjust<int32_t>;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ m_adjust = AUD_volume_adjust<float>;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ m_adjust = AUD_volume_adjust<double>;
+ break;
+ case AUD_FORMAT_U8:
+ m_adjust = AUD_volume_adjust_u8;
+ break;
+ case AUD_FORMAT_S24:
+ m_adjust = bigendian ? AUD_volume_adjust_s24_be :
+ AUD_volume_adjust_s24_le;
+ break;
+ default:
+ delete m_reader;
+ AUD_THROW(AUD_ERROR_READER);
+ }
+
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+}
+
+AUD_FaderReader::~AUD_FaderReader()
+{
+ delete m_buffer; AUD_DELETE("buffer")
+}
+
+bool AUD_FaderReader::notify(AUD_Message &message)
+{
+ return m_reader->notify(message);
+}
+
+void AUD_FaderReader::read(int & length, sample_t* & buffer)
+{
+ int position = m_reader->getPosition();
+ AUD_Specs specs = m_reader->getSpecs();
+ int samplesize = AUD_SAMPLE_SIZE(specs);
+
+ m_reader->read(length, buffer);
+
+ if(m_buffer->getSize() < length * samplesize)
+ m_buffer->resize(length * samplesize);
+
+ if((position + length) / (float)specs.rate <= m_start)
+ {
+ if(m_type != AUD_FADE_OUT)
+ {
+ buffer = m_buffer->getBuffer();
+ memset(buffer,
+ specs.format == AUD_FORMAT_U8 ? 0x80 : 0,
+ length * samplesize);
+ }
+ }
+ else if(position / (float)specs.rate >= m_start+m_length)
+ {
+ if(m_type == AUD_FADE_OUT)
+ {
+ buffer = m_buffer->getBuffer();
+ memset(buffer,
+ specs.format == AUD_FORMAT_U8 ? 0x80 : 0,
+ length * samplesize);
+ }
+ }
+ else
+ {
+ sample_t* buf = m_buffer->getBuffer();
+ float volume;
+
+ for(int i = 0; i < length; i++)
+ {
+ volume = (((position+i)/(float)specs.rate)-m_start) / m_length;
+ if(volume > 1.0f)
+ volume = 1.0f;
+ else if(volume < 0.0f)
+ volume = 0.0f;
+
+ if(m_type == AUD_FADE_OUT)
+ volume = 1.0f - volume;
+
+ m_adjust(buf + i * samplesize, buffer + i * samplesize,
+ specs.channels, volume);
+ }
+
+ buffer = buf;
+ }
+}
diff --git a/intern/audaspace/FX/AUD_FaderReader.h b/intern/audaspace/FX/AUD_FaderReader.h
new file mode 100644
index 00000000000..773643b2f5d
--- /dev/null
+++ b/intern/audaspace/FX/AUD_FaderReader.h
@@ -0,0 +1,86 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_FADERREADER
+#define AUD_FADERREADER
+
+#include "AUD_EffectReader.h"
+#include "AUD_ConverterFunctions.h"
+class AUD_Buffer;
+
+/**
+ * This class fades another reader.
+ * If the fading type is AUD_FADE_IN, everything before the fading start will be
+ * silenced, for AUD_FADE_OUT that's true for everything after fading ends.
+ */
+class AUD_FaderReader : public AUD_EffectReader
+{
+private:
+ /**
+ * The playback buffer.
+ */
+ AUD_Buffer *m_buffer;
+
+ /**
+ * The fading type.
+ */
+ AUD_FadeType m_type;
+
+ /**
+ * The fading start.
+ */
+ float m_start;
+
+ /**
+ * The fading length.
+ */
+ float m_length;
+
+ /**
+ * Volume adjustment function.
+ */
+ AUD_volume_adjust_f m_adjust;
+
+public:
+ /**
+ * Creates a new fader reader.
+ * \param type The fading type.
+ * \param start The time where fading should start in seconds.
+ * \param length How long fading should last in seconds.
+ * \exception AUD_Exception Thrown if the reader specified is NULL.
+ */
+ AUD_FaderReader(AUD_IReader* reader, AUD_FadeType type,
+ float start,float length);
+
+ /**
+ * Destroys the reader.
+ */
+ virtual ~AUD_FaderReader();
+
+ virtual bool notify(AUD_Message &message);
+ virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_FADERREADER
diff --git a/intern/audaspace/FX/AUD_LimiterFactory.cpp b/intern/audaspace/FX/AUD_LimiterFactory.cpp
new file mode 100644
index 00000000000..6f19575240a
--- /dev/null
+++ b/intern/audaspace/FX/AUD_LimiterFactory.cpp
@@ -0,0 +1,67 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_LimiterFactory.h"
+#include "AUD_LimiterReader.h"
+#include "AUD_Space.h"
+
+AUD_LimiterFactory::AUD_LimiterFactory(AUD_IFactory* factory,
+ float start, float end) :
+ AUD_EffectFactory(factory),
+ m_start(start),
+ m_end(end) {}
+
+float AUD_LimiterFactory::getStart()
+{
+ return m_start;
+}
+
+void AUD_LimiterFactory::setStart(float start)
+{
+ m_start = start;
+}
+
+float AUD_LimiterFactory::getEnd()
+{
+ return m_end;
+}
+
+void AUD_LimiterFactory::setEnd(float end)
+{
+ m_end = end;
+}
+
+AUD_IReader* AUD_LimiterFactory::createReader()
+{
+ AUD_IReader* reader = getReader();
+
+ if(reader != 0)
+ {
+ reader = new AUD_LimiterReader(reader, m_start, m_end);
+ AUD_NEW("reader")
+ }
+
+ return reader;
+}
diff --git a/intern/audaspace/FX/AUD_LimiterFactory.h b/intern/audaspace/FX/AUD_LimiterFactory.h
new file mode 100644
index 00000000000..588fea6eb4b
--- /dev/null
+++ b/intern/audaspace/FX/AUD_LimiterFactory.h
@@ -0,0 +1,84 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_LIMITERFACTORY
+#define AUD_LIMITERFACTORY
+
+#include "AUD_EffectFactory.h"
+
+/**
+ * This factory limits another factory in start and end time.
+ */
+class AUD_LimiterFactory : public AUD_EffectFactory
+{
+private:
+ /**
+ * The start time.
+ */
+ float m_start;
+
+ /**
+ * The end time.
+ */
+ float m_end;
+
+public:
+ /**
+ * Creates a new limiter factory.
+ * \param factory The input factory.
+ * \param start The desired start time.
+ * \param end The desired end time, a negative value signals that it should
+ * play to the end.
+ */
+ AUD_LimiterFactory(AUD_IFactory* factory = 0,
+ float start = 0, float end = -1);
+
+ /**
+ * Returns the start time.
+ */
+ float getStart();
+
+ /**
+ * Sets the start time.
+ * \param start The new start time.
+ */
+ void setStart(float start);
+
+ /**
+ * Returns the end time.
+ */
+ float getEnd();
+
+ /**
+ * Sets the end time.
+ * \param end The new end time, a negative value signals that it should play
+ * to the end.
+ */
+ void setEnd(float end);
+
+ virtual AUD_IReader* createReader();
+};
+
+#endif //AUD_LIMITERFACTORY
diff --git a/intern/audaspace/FX/AUD_LimiterReader.cpp b/intern/audaspace/FX/AUD_LimiterReader.cpp
new file mode 100644
index 00000000000..05882369001
--- /dev/null
+++ b/intern/audaspace/FX/AUD_LimiterReader.cpp
@@ -0,0 +1,95 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_LimiterReader.h"
+#include "AUD_Buffer.h"
+
+#include <iostream>
+
+AUD_LimiterReader::AUD_LimiterReader(AUD_IReader* reader,
+ float start, float end) :
+ AUD_EffectReader(reader)
+{
+ m_end = (int)(end * reader->getSpecs().rate);
+
+ if(start <= 0)
+ m_start = 0;
+ else
+ {
+ m_start = (int)(start * reader->getSpecs().rate);
+ if(m_reader->isSeekable())
+ m_reader->seek(m_start);
+ else
+ {
+ // skip first m_start samples by reading them
+ int length;
+ sample_t* buffer;
+ for(int i = m_start;
+ i >= AUD_DEFAULT_BUFFER_SIZE;
+ i -= AUD_DEFAULT_BUFFER_SIZE)
+ {
+ length = AUD_DEFAULT_BUFFER_SIZE;
+ m_reader->read(length, buffer);
+ length = i;
+ }
+ m_reader->read(length, buffer);
+ }
+ }
+}
+
+void AUD_LimiterReader::seek(int position)
+{
+ m_reader->seek(position + m_start);
+}
+
+int AUD_LimiterReader::getLength()
+{
+ int len = m_reader->getLength();
+ if(m_reader->getType() != AUD_TYPE_BUFFER || len < 0 ||
+ (len > m_end && m_end >= 0))
+ len = m_end;
+ return len - m_start;
+}
+
+int AUD_LimiterReader::getPosition()
+{
+ return m_reader->getPosition() - m_start;
+}
+
+void AUD_LimiterReader::read(int & length, sample_t* & buffer)
+{
+ if(m_end >= 0)
+ {
+ int position = m_reader->getPosition();
+ if(position+length > m_end)
+ length = m_end - position;
+ if(length < 0)
+ {
+ length = 0;
+ return;
+ }
+ }
+ m_reader->read(length, buffer);
+}
diff --git a/intern/audaspace/FX/AUD_LimiterReader.h b/intern/audaspace/FX/AUD_LimiterReader.h
new file mode 100644
index 00000000000..9921f5ee1b0
--- /dev/null
+++ b/intern/audaspace/FX/AUD_LimiterReader.h
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_LIMITERREADER
+#define AUD_LIMITERREADER
+
+#include "AUD_EffectReader.h"
+
+/**
+ * This reader limits another reader in start and end sample.
+ */
+class AUD_LimiterReader : public AUD_EffectReader
+{
+private:
+ /**
+ * The start sample: inclusive.
+ */
+ int m_start;
+
+ /**
+ * The end sample: exlusive.
+ */
+ int m_end;
+
+public:
+ /**
+ * Creates a new limiter reader.
+ * \param reader The reader to read from.
+ * \param start The desired start sample (inclusive).
+ * \param end The desired end sample (exklusive), a negative value signals
+ * that it should play to the end.
+ * \exception AUD_Exception Thrown if the reader specified is NULL.
+ */
+ AUD_LimiterReader(AUD_IReader* reader, float start = 0, float end = -1);
+
+ virtual void seek(int position);
+ virtual int getLength();
+ virtual int getPosition();
+ virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_LIMITERREADER
diff --git a/intern/audaspace/FX/AUD_LoopFactory.cpp b/intern/audaspace/FX/AUD_LoopFactory.cpp
new file mode 100644
index 00000000000..90186f623ff
--- /dev/null
+++ b/intern/audaspace/FX/AUD_LoopFactory.cpp
@@ -0,0 +1,57 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_LoopFactory.h"
+#include "AUD_LoopReader.h"
+
+AUD_LoopFactory::AUD_LoopFactory(AUD_IFactory* factory, int loop) :
+ AUD_EffectFactory(factory),
+ m_loop(loop) {}
+
+AUD_LoopFactory::AUD_LoopFactory(int loop) :
+ AUD_EffectFactory(0),
+ m_loop(loop) {}
+
+int AUD_LoopFactory::getLoop()
+{
+ return m_loop;
+}
+
+void AUD_LoopFactory::setLoop(int loop)
+{
+ m_loop = loop;
+}
+
+AUD_IReader* AUD_LoopFactory::createReader()
+{
+ AUD_IReader* reader = getReader();
+
+ if(reader != 0)
+ {
+ reader = new AUD_LoopReader(reader, m_loop); AUD_NEW("reader")
+ }
+
+ return reader;
+}
diff --git a/intern/audaspace/FX/AUD_LoopFactory.h b/intern/audaspace/FX/AUD_LoopFactory.h
new file mode 100644
index 00000000000..461d8c9ab69
--- /dev/null
+++ b/intern/audaspace/FX/AUD_LoopFactory.h
@@ -0,0 +1,74 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_LOOPFACTORY
+#define AUD_LOOPFACTORY
+
+#include "AUD_EffectFactory.h"
+
+/**
+ * This factory loops another factory.
+ * \note The reader has to be seekable.
+ */
+class AUD_LoopFactory : public AUD_EffectFactory
+{
+private:
+ /**
+ * The loop count.
+ */
+ float m_loop;
+
+public:
+ /**
+ * Creates a new loop factory.
+ * \param factory The input factory.
+ * \param loop The desired loop count, negative values result in endless
+ * looping.
+ */
+ AUD_LoopFactory(AUD_IFactory* factory = 0, int loop = -1);
+
+ /**
+ * Creates a new loop factory.
+ * \param loop The desired loop count, negative values result in endless
+ * looping.
+ */
+ AUD_LoopFactory(int loop);
+
+ /**
+ * Returns the loop count.
+ */
+ int getLoop();
+
+ /**
+ * Sets the loop count.
+ * \param loop The desired loop count, negative values result in endless
+ * looping.
+ */
+ void setLoop(int loop);
+
+ virtual AUD_IReader* createReader();
+};
+
+#endif //AUD_LOOPFACTORY
diff --git a/intern/audaspace/FX/AUD_LoopReader.cpp b/intern/audaspace/FX/AUD_LoopReader.cpp
new file mode 100644
index 00000000000..9e270321013
--- /dev/null
+++ b/intern/audaspace/FX/AUD_LoopReader.cpp
@@ -0,0 +1,107 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_LoopReader.h"
+#include "AUD_Buffer.h"
+
+#include <cstring>
+#include <stdio.h>
+
+AUD_LoopReader::AUD_LoopReader(AUD_IReader* reader, int loop) :
+ AUD_EffectReader(reader), m_loop(loop)
+{
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+}
+
+AUD_LoopReader::~AUD_LoopReader()
+{
+ delete m_buffer; AUD_DELETE("buffer")
+}
+
+AUD_ReaderType AUD_LoopReader::getType()
+{
+ if(m_loop < 0)
+ return AUD_TYPE_STREAM;
+ return m_reader->getType();
+}
+
+bool AUD_LoopReader::notify(AUD_Message &message)
+{
+ if(message.type == AUD_MSG_LOOP)
+ {
+ m_loop = message.loopcount;
+
+ m_reader->notify(message);
+
+ return true;
+ }
+ return m_reader->notify(message);
+}
+
+void AUD_LoopReader::read(int & length, sample_t* & buffer)
+{
+ int samplesize = AUD_SAMPLE_SIZE(m_reader->getSpecs());
+
+ int len = length;
+
+ m_reader->read(len, buffer);
+
+ if(len < length && m_loop != 0)
+ {
+ int pos = 0;
+
+ if(m_buffer->getSize() < length*samplesize)
+ m_buffer->resize(length*samplesize);
+
+ memcpy(m_buffer->getBuffer() + pos * samplesize,
+ buffer, len * samplesize);
+
+ pos += len;
+
+ while(pos < length && m_loop != 0)
+ {
+ if(m_loop > 0)
+ m_loop--;
+
+ m_reader->seek(0);
+
+ len = length - pos;
+ m_reader->read(len, buffer);
+ // prevent endless loop
+ if(!len)
+ break;
+
+ memcpy(m_buffer->getBuffer() + pos * samplesize,
+ buffer, len * samplesize);
+
+ pos += len;
+ }
+
+ length = pos;
+ buffer = m_buffer->getBuffer();
+ }
+ else
+ length = len;
+}
diff --git a/intern/audaspace/FX/AUD_LoopReader.h b/intern/audaspace/FX/AUD_LoopReader.h
new file mode 100644
index 00000000000..621ee3493ab
--- /dev/null
+++ b/intern/audaspace/FX/AUD_LoopReader.h
@@ -0,0 +1,69 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_LOOPREADER
+#define AUD_LOOPREADER
+
+#include "AUD_EffectReader.h"
+class AUD_Buffer;
+
+/**
+ * This class reads another reader and loops it.
+ * \note The other reader must be seekable.
+ */
+class AUD_LoopReader : public AUD_EffectReader
+{
+private:
+ /**
+ * The playback buffer.
+ */
+ AUD_Buffer *m_buffer;
+
+ /**
+ * The left loop count.
+ */
+ int m_loop;
+
+public:
+ /**
+ * Creates a new loop reader.
+ * \param reader The reader to read from.
+ * \param loop The desired loop count, negative values result in endless
+ * looping.
+ * \exception AUD_Exception Thrown if the reader specified is NULL.
+ */
+ AUD_LoopReader(AUD_IReader* reader, int loop);
+
+ /**
+ * Destroys the reader.
+ */
+ virtual ~AUD_LoopReader();
+
+ virtual AUD_ReaderType getType();
+ virtual bool notify(AUD_Message &message);
+ virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_LOOPREADER
diff --git a/intern/audaspace/FX/AUD_PingPongFactory.cpp b/intern/audaspace/FX/AUD_PingPongFactory.cpp
new file mode 100644
index 00000000000..a030d581b1a
--- /dev/null
+++ b/intern/audaspace/FX/AUD_PingPongFactory.cpp
@@ -0,0 +1,67 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_PingPongFactory.h"
+#include "AUD_DoubleReader.h"
+#include "AUD_ReverseFactory.h"
+
+AUD_PingPongFactory::AUD_PingPongFactory(AUD_IFactory* factory) :
+ AUD_EffectFactory(factory) {}
+
+AUD_IReader* AUD_PingPongFactory::createReader()
+{
+ if(m_factory == 0)
+ return 0;
+
+ AUD_IReader* reader = m_factory->createReader();
+
+ if(reader != 0)
+ {
+ AUD_IReader* reader2;
+ AUD_ReverseFactory factory(m_factory);
+
+ try
+ {
+ reader2 = factory.createReader();
+ }
+ catch(AUD_Exception e)
+ {
+ reader2 = 0;
+ }
+
+ if(reader2 != 0)
+ {
+ reader = new AUD_DoubleReader(reader, reader2);
+ AUD_NEW("reader")
+ }
+ else
+ {
+ delete reader; AUD_DELETE("reader")
+ reader = 0;
+ }
+ }
+
+ return reader;
+}
diff --git a/intern/audaspace/intern/AUD_ISuperposer.h b/intern/audaspace/FX/AUD_PingPongFactory.h
index ffaf6d88829..b8854da550a 100644
--- a/intern/audaspace/intern/AUD_ISuperposer.h
+++ b/intern/audaspace/FX/AUD_PingPongFactory.h
@@ -23,31 +23,29 @@
* ***** END LGPL LICENSE BLOCK *****
*/
-#ifndef AUD_ISUPERPOSER
-#define AUD_ISUPERPOSER
+#ifndef AUD_PINGPONGFACTORY
+#define AUD_PINGPONGFACTORY
-#include "AUD_Space.h"
+#include "AUD_EffectFactory.h"
/**
- * This class is able to superpose two audiosignals.
+ * This factory plays another factory first normal, then reversed.
+ * \note Readers from the underlying factory must be from the buffer type.
*/
-class AUD_ISuperposer
+class AUD_PingPongFactory : public AUD_EffectFactory
{
public:
/**
- * Destroys the superposer.
+ * Creates a new ping pong factory.
+ * \param factory The input factory.
*/
- virtual ~AUD_ISuperposer(){}
+ AUD_PingPongFactory(AUD_IFactory* factory = 0);
/**
- * Creates a reader for playback of the sound source.
- * \param target The target buffer for superposing.
- * \param source The source buffer for superposing.
- * \param length The count of bytes to superpose.
+ * Destroys the factory.
*/
- virtual void superpose(sample_t* destination,
- sample_t* source,
- int length)=0;
+
+ virtual AUD_IReader* createReader();
};
-#endif //AUD_ISUPERPOSER
+#endif //AUD_PINGPONGFACTORY
diff --git a/intern/audaspace/FX/AUD_PitchFactory.cpp b/intern/audaspace/FX/AUD_PitchFactory.cpp
new file mode 100644
index 00000000000..9aaa241beca
--- /dev/null
+++ b/intern/audaspace/FX/AUD_PitchFactory.cpp
@@ -0,0 +1,52 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_PitchFactory.h"
+#include "AUD_PitchReader.h"
+#include "AUD_Space.h"
+
+extern "C" {
+#include <libavformat/avformat.h>
+}
+
+AUD_PitchFactory::AUD_PitchFactory(AUD_IFactory* factory, float pitch) :
+ AUD_EffectFactory(factory),
+ m_pitch(pitch) {}
+
+AUD_PitchFactory::AUD_PitchFactory(float pitch) :
+ AUD_EffectFactory(0),
+ m_pitch(pitch) {}
+
+AUD_IReader* AUD_PitchFactory::createReader()
+{
+ AUD_IReader* reader = getReader();
+
+ if(reader != 0)
+ {
+ reader = new AUD_PitchReader(reader, m_pitch); AUD_NEW("reader")
+ }
+
+ return reader;
+}
diff --git a/intern/audaspace/FX/AUD_PitchFactory.h b/intern/audaspace/FX/AUD_PitchFactory.h
new file mode 100644
index 00000000000..3209aa46983
--- /dev/null
+++ b/intern/audaspace/FX/AUD_PitchFactory.h
@@ -0,0 +1,70 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_PITCHFACTORY
+#define AUD_PITCHFACTORY
+
+#include "AUD_EffectFactory.h"
+
+/**
+ * This factory changes the pitch of another factory.
+ */
+class AUD_PitchFactory : public AUD_EffectFactory
+{
+private:
+ /**
+ * The pitch.
+ */
+ float m_pitch;
+
+public:
+ /**
+ * Creates a new pitch factory.
+ * \param factory The input factory.
+ * \param pitch The desired pitch.
+ */
+ AUD_PitchFactory(AUD_IFactory* factory = 0, float pitch = 1.0);
+
+ /**
+ * Creates a new pitch factory.
+ * \param pitch The desired pitch.
+ */
+ AUD_PitchFactory(float pitch);
+
+ /**
+ * Returns the pitch.
+ */
+ float getPitch();
+
+ /**
+ * Sets the pitch.
+ * \param pitch The new pitch value. Should be between 0.0 and 1.0.
+ */
+ void setPitch(float pitch);
+
+ virtual AUD_IReader* createReader();
+};
+
+#endif //AUD_PITCHFACTORY
diff --git a/intern/audaspace/SDL/AUD_SDLSuperposer.cpp b/intern/audaspace/FX/AUD_PitchReader.cpp
index 6ce88d2fedf..d840f32fc10 100644
--- a/intern/audaspace/SDL/AUD_SDLSuperposer.cpp
+++ b/intern/audaspace/FX/AUD_PitchReader.cpp
@@ -23,20 +23,17 @@
* ***** END LGPL LICENSE BLOCK *****
*/
-#include "AUD_SDLSuperposer.h"
+#include "AUD_PitchReader.h"
-#include <SDL.h>
-
-AUD_SDLSuperposer::AUD_SDLSuperposer()
+AUD_PitchReader::AUD_PitchReader(AUD_IReader* reader, float pitch) :
+ AUD_EffectReader(reader)
{
+ m_pitch = pitch;
}
-void AUD_SDLSuperposer::superpose(sample_t* destination,
- sample_t* source,
- int length)
+AUD_Specs AUD_PitchReader::getSpecs()
{
- SDL_MixAudio((Uint8*)destination,
- (Uint8*)source,
- length,
- SDL_MIX_MAXVOLUME);
+ AUD_Specs specs = m_reader->getSpecs();
+ specs.rate = (AUD_SampleRate)(specs.rate * m_pitch);
+ return specs;
}
diff --git a/intern/audaspace/FX/AUD_PitchReader.h b/intern/audaspace/FX/AUD_PitchReader.h
new file mode 100644
index 00000000000..440e9cc843c
--- /dev/null
+++ b/intern/audaspace/FX/AUD_PitchReader.h
@@ -0,0 +1,54 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_PITCHREADER
+#define AUD_PITCHREADER
+
+#include "AUD_EffectReader.h"
+
+/**
+ * This class reads another reader and changes it's pitch.
+ */
+class AUD_PitchReader : public AUD_EffectReader
+{
+private:
+ /**
+ * The pitch level.
+ */
+ float m_pitch;
+
+public:
+ /**
+ * Creates a new pitch reader.
+ * \param reader The reader to read from.
+ * \param pitch The size of the buffer.
+ * \exception AUD_Exception Thrown if the reader specified is NULL.
+ */
+ AUD_PitchReader(AUD_IReader* reader, float pitch);
+
+ virtual AUD_Specs getSpecs();
+};
+
+#endif //AUD_PITCHREADER
diff --git a/intern/audaspace/FX/AUD_ReverseFactory.cpp b/intern/audaspace/FX/AUD_ReverseFactory.cpp
new file mode 100644
index 00000000000..1242641c350
--- /dev/null
+++ b/intern/audaspace/FX/AUD_ReverseFactory.cpp
@@ -0,0 +1,43 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_ReverseFactory.h"
+#include "AUD_ReverseReader.h"
+#include "AUD_Space.h"
+
+AUD_ReverseFactory::AUD_ReverseFactory(AUD_IFactory* factory) :
+ AUD_EffectFactory(factory) {}
+
+AUD_IReader* AUD_ReverseFactory::createReader()
+{
+ AUD_IReader* reader = getReader();
+
+ if(reader != 0)
+ {
+ reader = new AUD_ReverseReader(reader); AUD_NEW("reader")
+ }
+
+ return reader;
+}
diff --git a/intern/audaspace/FX/AUD_ReverseFactory.h b/intern/audaspace/FX/AUD_ReverseFactory.h
new file mode 100644
index 00000000000..4b664c47281
--- /dev/null
+++ b/intern/audaspace/FX/AUD_ReverseFactory.h
@@ -0,0 +1,50 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_REVERSEFACTORY
+#define AUD_REVERSEFACTORY
+
+#include "AUD_EffectFactory.h"
+
+/**
+ * This factory reads another factory reverted.
+ * \note Readers from the underlying factory must be from the buffer type.
+ */
+class AUD_ReverseFactory : public AUD_EffectFactory
+{
+public:
+ /**
+ * Creates a new reverse factory.
+ * \param factory The input factory.
+ */
+ AUD_ReverseFactory(AUD_IFactory* factory = 0);
+
+ /**
+ * Destroys the factory.
+ */
+ virtual AUD_IReader* createReader();
+};
+
+#endif //AUD_REVERSEFACTORY
diff --git a/intern/audaspace/FX/AUD_ReverseReader.cpp b/intern/audaspace/FX/AUD_ReverseReader.cpp
new file mode 100644
index 00000000000..043480b91b9
--- /dev/null
+++ b/intern/audaspace/FX/AUD_ReverseReader.cpp
@@ -0,0 +1,111 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_ReverseReader.h"
+#include "AUD_Buffer.h"
+
+#include <cstring>
+
+AUD_ReverseReader::AUD_ReverseReader(AUD_IReader* reader) :
+ AUD_EffectReader(reader)
+{
+ if(reader->getType() != AUD_TYPE_BUFFER)
+ AUD_THROW(AUD_ERROR_READER);
+
+ m_length = reader->getLength();
+ if(m_length < 0)
+ AUD_THROW(AUD_ERROR_READER);
+
+ m_position = 0;
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+}
+
+AUD_ReverseReader::~AUD_ReverseReader()
+{
+ delete m_buffer; AUD_DELETE("buffer")
+}
+
+void AUD_ReverseReader::seek(int position)
+{
+ m_position = position;
+}
+
+int AUD_ReverseReader::getLength()
+{
+ return m_length;
+}
+
+int AUD_ReverseReader::getPosition()
+{
+ return m_position;
+}
+
+void AUD_ReverseReader::read(int & length, sample_t* & buffer)
+{
+ // first correct the length
+ if(m_position+length > m_length)
+ length = m_length-m_position;
+
+ if(length <= 0)
+ {
+ length = 0;
+ return;
+ }
+
+ int samplesize = AUD_SAMPLE_SIZE(getSpecs());
+
+ // resize buffer if needed
+ if(m_buffer->getSize() < length * samplesize)
+ m_buffer->resize(length * samplesize);
+
+ 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);
+
+ // set null if reader didn't give enough data
+ if(len < length)
+ {
+ if(getSpecs().format == AUD_FORMAT_U8)
+ memset(buffer, 0x80, (length-len)*samplesize);
+ else
+ memset(buffer, 0, (length-len)*samplesize);
+ buffer += length-len;
+ }
+
+ // copy the samples reverted
+ for(int i = 0; i < len; i++)
+ memcpy(buffer + i * samplesize,
+ buf + (len - 1 - i) * samplesize,
+ samplesize);
+
+ m_position += length;
+
+ buffer = m_buffer->getBuffer();
+}
diff --git a/intern/audaspace/FX/AUD_ReverseReader.h b/intern/audaspace/FX/AUD_ReverseReader.h
new file mode 100644
index 00000000000..045d2ac5a8e
--- /dev/null
+++ b/intern/audaspace/FX/AUD_ReverseReader.h
@@ -0,0 +1,74 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_REVERSEREADER
+#define AUD_REVERSEREADER
+
+#include "AUD_EffectReader.h"
+class AUD_Buffer;
+
+/**
+ * This class reads another reader from back to front.
+ * \note The underlying reader must be a buffer.
+ */
+class AUD_ReverseReader : public AUD_EffectReader
+{
+private:
+ /**
+ * The current position.
+ */
+ int m_position;
+
+ /**
+ * The sample count.
+ */
+ int m_length;
+
+ /**
+ * The playback buffer.
+ */
+ AUD_Buffer* m_buffer;
+
+public:
+ /**
+ * Creates a new reverse reader.
+ * \param reader The reader to read from.
+ * \exception AUD_Exception Thrown if the reader specified is NULL or not
+ * a buffer.
+ */
+ AUD_ReverseReader(AUD_IReader* reader);
+
+ /**
+ * Destroys the reader.
+ */
+ virtual ~AUD_ReverseReader();
+
+ virtual void seek(int position);
+ virtual int getLength();
+ virtual int getPosition();
+ virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_REVERSEREADER
diff --git a/intern/audaspace/FX/AUD_VolumeFactory.cpp b/intern/audaspace/FX/AUD_VolumeFactory.cpp
new file mode 100644
index 00000000000..fbde608aa12
--- /dev/null
+++ b/intern/audaspace/FX/AUD_VolumeFactory.cpp
@@ -0,0 +1,57 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_VolumeFactory.h"
+#include "AUD_VolumeReader.h"
+
+AUD_VolumeFactory::AUD_VolumeFactory(AUD_IFactory* factory, float volume) :
+ AUD_EffectFactory(factory),
+ m_volume(volume) {}
+
+AUD_VolumeFactory::AUD_VolumeFactory(float volume) :
+ AUD_EffectFactory(0),
+ m_volume(volume) {}
+
+float AUD_VolumeFactory::getVolume()
+{
+ return m_volume;
+}
+
+void AUD_VolumeFactory::setVolume(float volume)
+{
+ m_volume = volume;
+}
+
+AUD_IReader* AUD_VolumeFactory::createReader()
+{
+ AUD_IReader* reader = getReader();
+
+ if(reader != 0)
+ {
+ reader = new AUD_VolumeReader(reader, m_volume); AUD_NEW("reader")
+ }
+
+ return reader;
+}
diff --git a/intern/audaspace/FX/AUD_VolumeFactory.h b/intern/audaspace/FX/AUD_VolumeFactory.h
new file mode 100644
index 00000000000..d2812536d83
--- /dev/null
+++ b/intern/audaspace/FX/AUD_VolumeFactory.h
@@ -0,0 +1,72 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_VOLUMEFACTORY
+#define AUD_VOLUMEFACTORY
+
+#include "AUD_EffectFactory.h"
+
+/**
+ * This factory changes the volume of another factory.
+ * The set volume should be a value between 0.0 and 1.0, higher values at your
+ * own risk!
+ */
+class AUD_VolumeFactory : public AUD_EffectFactory
+{
+private:
+ /**
+ * The volume.
+ */
+ float m_volume;
+
+public:
+ /**
+ * Creates a new volume factory.
+ * \param factory The input factory.
+ * \param volume The desired volume.
+ */
+ AUD_VolumeFactory(AUD_IFactory* factory = 0, float volume = 1.0);
+
+ /**
+ * Creates a new volume factory.
+ * \param volume The desired volume.
+ */
+ AUD_VolumeFactory(float volume);
+
+ /**
+ * Returns the volume.
+ */
+ float getVolume();
+
+ /**
+ * Sets the volume.
+ * \param volume The new volume value. Should be between 0.0 and 1.0.
+ */
+ void setVolume(float volume);
+
+ virtual AUD_IReader* createReader();
+};
+
+#endif //AUD_VOLUMEFACTORY
diff --git a/intern/audaspace/FX/AUD_VolumeReader.cpp b/intern/audaspace/FX/AUD_VolumeReader.cpp
new file mode 100644
index 00000000000..fc3f20152a6
--- /dev/null
+++ b/intern/audaspace/FX/AUD_VolumeReader.cpp
@@ -0,0 +1,97 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_VolumeReader.h"
+#include "AUD_Buffer.h"
+
+#include <cstring>
+
+AUD_VolumeReader::AUD_VolumeReader(AUD_IReader* reader, float volume) :
+ AUD_EffectReader(reader),
+ m_volume(volume)
+{
+ int bigendian = 1;
+ bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
+
+ switch(m_reader->getSpecs().format)
+ {
+ case AUD_FORMAT_S16:
+ m_adjust = AUD_volume_adjust<int16_t>;
+ break;
+ case AUD_FORMAT_S32:
+ m_adjust = AUD_volume_adjust<int32_t>;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ m_adjust = AUD_volume_adjust<float>;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ m_adjust = AUD_volume_adjust<double>;
+ break;
+ case AUD_FORMAT_U8:
+ m_adjust = AUD_volume_adjust_u8;
+ break;
+ case AUD_FORMAT_S24:
+ m_adjust = bigendian ? AUD_volume_adjust_s24_be :
+ AUD_volume_adjust_s24_le;
+ break;
+ default:
+ delete m_reader;
+ AUD_THROW(AUD_ERROR_READER);
+ }
+
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+}
+
+AUD_VolumeReader::~AUD_VolumeReader()
+{
+ delete m_buffer; AUD_DELETE("buffer")
+}
+
+bool AUD_VolumeReader::notify(AUD_Message &message)
+{
+ if(message.type == AUD_MSG_VOLUME)
+ {
+ m_volume = message.volume;
+
+ m_reader->notify(message);
+
+ return true;
+ }
+ return m_reader->notify(message);
+}
+
+void AUD_VolumeReader::read(int & length, sample_t* & buffer)
+{
+ sample_t* buf;
+ AUD_Specs specs = m_reader->getSpecs();
+
+ m_reader->read(length, buf);
+ if(m_buffer->getSize() < length*AUD_SAMPLE_SIZE(specs))
+ m_buffer->resize(length*AUD_SAMPLE_SIZE(specs));
+
+ buffer = m_buffer->getBuffer();
+
+ m_adjust(buffer, buf, length * specs.channels, m_volume);
+}
diff --git a/intern/audaspace/FX/AUD_VolumeReader.h b/intern/audaspace/FX/AUD_VolumeReader.h
new file mode 100644
index 00000000000..f38ae4d265c
--- /dev/null
+++ b/intern/audaspace/FX/AUD_VolumeReader.h
@@ -0,0 +1,72 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_VOLUMEREADER
+#define AUD_VOLUMEREADER
+
+#include "AUD_EffectReader.h"
+#include "AUD_ConverterFunctions.h"
+class AUD_Buffer;
+
+/**
+ * This class reads another reader and changes it's volume.
+ */
+class AUD_VolumeReader : public AUD_EffectReader
+{
+private:
+ /**
+ * The playback buffer.
+ */
+ AUD_Buffer *m_buffer;
+
+ /**
+ * The volume level.
+ */
+ float m_volume;
+
+ /**
+ * Volume adjustment function.
+ */
+ AUD_volume_adjust_f m_adjust;
+
+public:
+ /**
+ * Creates a new volume reader.
+ * \param reader The reader to read from.
+ * \param volume The size of the buffer.
+ * \exception AUD_Exception Thrown if the reader specified is NULL.
+ */
+ AUD_VolumeReader(AUD_IReader* reader, float volume);
+
+ /**
+ * Destroys the reader.
+ */
+ virtual ~AUD_VolumeReader();
+
+ virtual bool notify(AUD_Message &message);
+ virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_VOLUMEREADER
diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
new file mode 100644
index 00000000000..28b00e01a5d
--- /dev/null
+++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp
@@ -0,0 +1,1286 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_OpenALDevice.h"
+#include "AUD_IReader.h"
+#include "AUD_IMixer.h"
+#include "AUD_ConverterFactory.h"
+#include "AUD_SourceCaps.h"
+
+#include <cstring>
+#include <limits>
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+/// Saves the data for playback.
+struct AUD_OpenALHandle : AUD_Handle
+{
+ /// Whether it's a buffered or a streamed source.
+ bool isBuffered;
+
+ /// The reader source.
+ AUD_IReader* reader;
+
+ /// Whether to keep the source if end of it is reached.
+ bool keep;
+
+ /// OpenAL sample format.
+ ALenum format;
+
+ /// OpenAL source.
+ ALuint source;
+
+ /// OpenAL buffers.
+ ALuint buffers[3];
+
+ /// The first buffer to be read next.
+ int current;
+};
+
+struct AUD_OpenALBufferedFactory
+{
+ /// The factory.
+ AUD_IFactory* factory;
+
+ /// The OpenAL buffer.
+ ALuint buffer;
+};
+
+typedef std::list<AUD_OpenALHandle*>::iterator AUD_HandleIterator;
+typedef std::list<AUD_OpenALBufferedFactory*>::iterator AUD_BFIterator;
+
+/******************************************************************************/
+/**************************** Threading Code **********************************/
+/******************************************************************************/
+
+void* AUD_openalRunThread(void* device)
+{
+ AUD_OpenALDevice* dev = (AUD_OpenALDevice*)device;
+ dev->updateStreams();
+ return NULL;
+}
+
+void AUD_OpenALDevice::start()
+{
+ lock();
+
+ if(!m_playing)
+ {
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+ pthread_create(&m_thread, &attr, AUD_openalRunThread, this);
+
+ pthread_attr_destroy(&attr);
+
+ m_playing = true;
+ }
+
+ unlock();
+}
+
+void AUD_OpenALDevice::updateStreams()
+{
+ AUD_OpenALHandle* sound;
+
+ int length;
+ sample_t* buffer;
+
+ ALint info;
+ AUD_Specs specs;
+
+ while(1)
+ {
+ lock();
+
+ alcSuspendContext(m_context);
+
+ // for all sounds
+ AUD_HandleIterator it = m_playingSounds->begin();
+ while(it != m_playingSounds->end())
+ {
+ sound = *it;
+ // increment the iterator to make sure it's valid,
+ // in case the sound gets deleted after stopping
+ ++it;
+
+ // is it a streamed sound?
+ if(!sound->isBuffered)
+ {
+ // check for buffer refilling
+ alGetSourcei(sound->source, AL_BUFFERS_PROCESSED, &info);
+
+ if(info)
+ {
+ specs = sound->reader->getSpecs();
+
+ // for all empty buffers
+ while(info--)
+ {
+ // if there's still data to play back
+ if(sound->current >= 0)
+ {
+ // read data
+ length = m_buffersize;
+ sound->reader->read(length, buffer);
+
+ // read nothing?
+ if(length == 0)
+ {
+ sound->current = -1;
+ break;
+ }
+
+ // unqueue buffer
+ alSourceUnqueueBuffers(sound->source, 1,
+ &sound->buffers[sound->current]);
+ ALenum err;
+ if((err = alGetError()) != AL_NO_ERROR)
+ {
+ sound->current = -1;
+ break;
+ }
+
+ // fill with new data
+ alBufferData(sound->buffers[sound->current],
+ sound->format,
+ buffer,
+ length * AUD_SAMPLE_SIZE(specs),
+ specs.rate);
+
+ if(alGetError() != AL_NO_ERROR)
+ {
+ sound->current = -1;
+ break;
+ }
+
+ // and queue again
+ alSourceQueueBuffers(sound->source, 1,
+ &sound->buffers[sound->current]);
+ if(alGetError() != AL_NO_ERROR)
+ {
+ sound->current = -1;
+ break;
+ }
+
+ sound->current = (sound->current+1) % 3;
+ }
+ else
+ break;
+ }
+ }
+ }
+
+ // check if the sound has been stopped
+ alGetSourcei(sound->source, AL_SOURCE_STATE, &info);
+
+ if(info == AL_STOPPED)
+ {
+ // if it really stopped
+ if(sound->current < 0)
+ {
+ // pause or
+ if(sound->keep)
+ {
+ alSourceRewind(sound->source);
+ pause(sound);
+ }
+ // stop
+ else
+ stop(sound);
+ }
+ // continue playing
+ else
+ alSourcePlay(sound->source);
+ }
+ }
+
+ alcProcessContext(m_context);
+
+ // stop thread
+ if(m_playingSounds->empty())
+ {
+ unlock();
+ m_playing = false;
+ pthread_exit(NULL);
+ }
+
+ unlock();
+
+#ifdef WIN32
+ Sleep(20);
+#else
+ usleep(20000);
+#endif
+ }
+}
+
+/******************************************************************************/
+/**************************** 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;
+}
+
+AUD_OpenALDevice::AUD_OpenALDevice(AUD_Specs specs, int buffersize)
+{
+ // cannot determine how many channels or which format OpenAL uses, but
+ // it at least is able to play 16 bit stereo audio
+ specs.channels = AUD_CHANNELS_STEREO;
+ specs.format = AUD_FORMAT_S16;
+
+ m_device = alcOpenDevice(NULL);
+
+ if(!m_device)
+ AUD_THROW(AUD_ERROR_OPENAL);
+
+ // at least try to set the frequency
+ ALCint attribs[] = { ALC_FREQUENCY, specs.rate, 0 };
+ ALCint* attributes = attribs;
+ if(specs.rate == AUD_RATE_INVALID)
+ attributes = NULL;
+
+ m_context = alcCreateContext(m_device, attributes);
+ alcMakeContextCurrent(m_context);
+
+ alcGetIntegerv(m_device, ALC_FREQUENCY, 1, (ALCint*)&specs.rate);
+
+ // check for specific formats and channel counts to be played back
+ if(alIsExtensionPresent("AL_EXT_FLOAT32") == AL_TRUE)
+ specs.format = AUD_FORMAT_FLOAT32;
+
+ m_useMC = alIsExtensionPresent("AL_EXT_MCFORMATS") == AL_TRUE;
+
+ alGetError();
+
+ m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory")
+
+ m_specs = specs;
+ m_buffersize = buffersize;
+ m_playing = false;
+
+ m_playingSounds = new std::list<AUD_OpenALHandle*>(); AUD_NEW("list")
+ m_pausedSounds = new std::list<AUD_OpenALHandle*>(); AUD_NEW("list")
+ m_bufferedFactories = new std::list<AUD_OpenALBufferedFactory*>();
+ AUD_NEW("list")
+
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+
+ pthread_mutex_init(&m_mutex, &attr);
+
+ pthread_mutexattr_destroy(&attr);
+}
+
+AUD_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; AUD_DELETE("reader")
+ alDeleteBuffers(3, sound->buffers);
+ }
+ delete sound; AUD_DELETE("handle")
+ m_playingSounds->erase(m_playingSounds->begin());
+ }
+ delete m_playingSounds; AUD_DELETE("list")
+
+ // delete all paused sounds
+ while(!m_pausedSounds->empty())
+ {
+ sound = *(m_pausedSounds->begin());
+ alDeleteSources(1, &sound->source);
+ if(!sound->isBuffered)
+ {
+ delete sound->reader; AUD_DELETE("reader")
+ alDeleteBuffers(3, sound->buffers);
+ }
+ delete sound; AUD_DELETE("handle")
+ m_pausedSounds->erase(m_pausedSounds->begin());
+ }
+ delete m_pausedSounds; AUD_DELETE("list")
+
+ // delete all buffered factories
+ while(!m_bufferedFactories->empty())
+ {
+ alDeleteBuffers(1, &(*(m_bufferedFactories->begin()))->buffer);
+ delete *m_bufferedFactories->begin(); AUD_DELETE("bufferedfactory");
+ m_bufferedFactories->erase(m_bufferedFactories->begin());
+ }
+ delete m_bufferedFactories; AUD_DELETE("list")
+
+ alcProcessContext(m_context);
+ unlock();
+
+ // wait for the thread to stop
+ pthread_join(m_thread, NULL);
+
+ // quit OpenAL
+ alcMakeContextCurrent(NULL);
+ alcDestroyContext(m_context);
+ alcCloseDevice(m_device);
+
+ delete m_converter; AUD_DELETE("factory")
+
+ pthread_mutex_destroy(&m_mutex);
+}
+
+AUD_Specs AUD_OpenALDevice::getSpecs()
+{
+ return m_specs;
+}
+
+bool AUD_OpenALDevice::getFormat(ALenum &format, AUD_Specs specs)
+{
+ bool valid = true;
+ format = 0;
+
+ switch(specs.format)
+ {
+ case AUD_FORMAT_U8:
+ switch(specs.channels)
+ {
+ case AUD_CHANNELS_MONO:
+ format = AL_FORMAT_MONO8;
+ break;
+ case AUD_CHANNELS_STEREO:
+ format = AL_FORMAT_STEREO8;
+ break;
+ case AUD_CHANNELS_SURROUND4:
+ if(m_useMC)
+ {
+ format = alGetEnumValue("AL_FORMAT_QUAD8");
+ break;
+ }
+ case AUD_CHANNELS_SURROUND51:
+ if(m_useMC)
+ {
+ format = alGetEnumValue("AL_FORMAT_51CHN8");
+ break;
+ }
+ case AUD_CHANNELS_SURROUND61:
+ if(m_useMC)
+ {
+ format = alGetEnumValue("AL_FORMAT_61CHN8");
+ break;
+ }
+ case AUD_CHANNELS_SURROUND71:
+ if(m_useMC)
+ {
+ format = alGetEnumValue("AL_FORMAT_71CHN8");
+ break;
+ }
+ default:
+ valid = false;
+ }
+ break;
+ case AUD_FORMAT_S16:
+ switch(specs.channels)
+ {
+ case AUD_CHANNELS_MONO:
+ format = AL_FORMAT_MONO16;
+ break;
+ case AUD_CHANNELS_STEREO:
+ format = AL_FORMAT_STEREO16;
+ break;
+ case AUD_CHANNELS_SURROUND4:
+ if(m_useMC)
+ {
+ format = alGetEnumValue("AL_FORMAT_QUAD16");
+ break;
+ }
+ case AUD_CHANNELS_SURROUND51:
+ if(m_useMC)
+ {
+ format = alGetEnumValue("AL_FORMAT_51CHN16");
+ break;
+ }
+ case AUD_CHANNELS_SURROUND61:
+ if(m_useMC)
+ {
+ format = alGetEnumValue("AL_FORMAT_61CHN16");
+ break;
+ }
+ case AUD_CHANNELS_SURROUND71:
+ if(m_useMC)
+ {
+ format = alGetEnumValue("AL_FORMAT_71CHN16");
+ break;
+ }
+ default:
+ valid = false;
+ }
+ break;
+ case AUD_FORMAT_FLOAT32:
+ switch(specs.channels)
+ {
+ case AUD_CHANNELS_MONO:
+ format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
+ break;
+ case AUD_CHANNELS_STEREO:
+ format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
+ break;
+ case AUD_CHANNELS_SURROUND4:
+ if(m_useMC)
+ {
+ format = alGetEnumValue("AL_FORMAT_QUAD32");
+ break;
+ }
+ case AUD_CHANNELS_SURROUND51:
+ if(m_useMC)
+ {
+ format = alGetEnumValue("AL_FORMAT_51CHN32");
+ break;
+ }
+ case AUD_CHANNELS_SURROUND61:
+ if(m_useMC)
+ {
+ format = alGetEnumValue("AL_FORMAT_61CHN32");
+ break;
+ }
+ case AUD_CHANNELS_SURROUND71:
+ if(m_useMC)
+ {
+ format = alGetEnumValue("AL_FORMAT_71CHN32");
+ break;
+ }
+ default:
+ valid = false;
+ }
+ break;
+ default:
+ valid = false;
+ }
+
+ if(!format)
+ valid = false;
+
+ return valid;
+}
+
+AUD_Handle* AUD_OpenALDevice::play(AUD_IFactory* factory, bool keep)
+{
+ // check if it is a buffered factory
+ for(AUD_BFIterator i = m_bufferedFactories->begin();
+ i != m_bufferedFactories->end(); i++)
+ {
+ if((*i)->factory == factory)
+ {
+ // create the handle
+ AUD_OpenALHandle* sound = new AUD_OpenALHandle; AUD_NEW("handle")
+ sound->keep = keep;
+ sound->current = -1;
+ sound->isBuffered = true;
+
+ alcSuspendContext(m_context);
+
+ // OpenAL playback code
+ try
+ {
+ alGenSources(1, &sound->source);
+ if(alGetError() != AL_NO_ERROR)
+ AUD_THROW(AUD_ERROR_OPENAL);
+
+ try
+ {
+ alSourcei(sound->source, AL_BUFFER, (*i)->buffer);
+ if(alGetError() != AL_NO_ERROR)
+ AUD_THROW(AUD_ERROR_OPENAL);
+
+ alSourcePlay(sound->source);
+
+ if(alGetError() != AL_NO_ERROR)
+ AUD_THROW(AUD_ERROR_OPENAL);
+ }
+ catch(AUD_Exception e)
+ {
+ alDeleteSources(1, &sound->source);
+ throw;
+ }
+ }
+ catch(AUD_Exception e)
+ {
+ delete sound; AUD_DELETE("handle")
+ alcProcessContext(m_context);
+ unlock();
+ throw;
+ }
+
+ // play sound
+ m_playingSounds->push_back(sound);
+
+ start();
+
+ alcProcessContext(m_context);
+ unlock();
+
+ return sound;
+ }
+ }
+
+ AUD_IReader* reader = factory->createReader();
+
+ if(reader == NULL)
+ AUD_THROW(AUD_ERROR_READER);
+
+ AUD_Specs specs;
+
+ specs = reader->getSpecs();
+
+ // check format
+ bool valid = true;
+
+ if(specs.format == AUD_FORMAT_INVALID)
+ valid = false;
+ else if(specs.format == AUD_FORMAT_S24 ||
+ specs.format == AUD_FORMAT_S32 ||
+ specs.format == AUD_FORMAT_FLOAT32 ||
+ specs.format == AUD_FORMAT_FLOAT64)
+ {
+ m_converter->setReader(reader);
+ reader = m_converter->createReader();
+ specs = reader->getSpecs();
+ }
+
+ // create the handle
+ AUD_OpenALHandle* sound = new AUD_OpenALHandle; AUD_NEW("handle")
+ sound->keep = keep;
+ sound->reader = reader;
+ sound->current = 0;
+ sound->isBuffered = false;
+
+ valid &= getFormat(sound->format, specs);
+
+ if(!valid)
+ {
+ delete sound; AUD_DELETE("handle")
+ delete reader; AUD_DELETE("reader")
+ return NULL;
+ }
+
+ lock();
+ alcSuspendContext(m_context);
+
+ // OpenAL playback code
+ try
+ {
+ alGenBuffers(3, sound->buffers);
+ if(alGetError() != AL_NO_ERROR)
+ AUD_THROW(AUD_ERROR_OPENAL);
+
+ try
+ {
+ sample_t* buf;
+ int length;
+
+ for(int i=0; i<3; i++)
+ {
+ length = m_buffersize;
+ reader->read(length, buf);
+ alBufferData(sound->buffers[i], sound->format, buf,
+ length * AUD_SAMPLE_SIZE(specs), specs.rate);
+ if(alGetError() != AL_NO_ERROR)
+ AUD_THROW(AUD_ERROR_OPENAL);
+ }
+
+ alGenSources(1, &sound->source);
+ if(alGetError() != AL_NO_ERROR)
+ AUD_THROW(AUD_ERROR_OPENAL);
+
+ try
+ {
+ alSourceQueueBuffers(sound->source, 3, sound->buffers);
+ if(alGetError() != AL_NO_ERROR)
+ AUD_THROW(AUD_ERROR_OPENAL);
+
+ alSourcePlay(sound->source);
+
+ if(alGetError() != AL_NO_ERROR)
+ AUD_THROW(AUD_ERROR_OPENAL);
+ }
+ catch(AUD_Exception e)
+ {
+ alDeleteSources(1, &sound->source);
+ throw;
+ }
+ }
+ catch(AUD_Exception e)
+ {
+ alDeleteBuffers(3, sound->buffers);
+ throw;
+ }
+ }
+ catch(AUD_Exception e)
+ {
+ delete sound; AUD_DELETE("handle")
+ delete reader; AUD_DELETE("reader")
+ alcProcessContext(m_context);
+ unlock();
+ throw;
+ }
+
+ // play sound
+ m_playingSounds->push_back(sound);
+
+ start();
+
+ alcProcessContext(m_context);
+ unlock();
+
+ return sound;
+}
+
+bool AUD_OpenALDevice::pause(AUD_Handle* handle)
+{
+ // only songs that are played can be paused
+ lock();
+ 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);
+ unlock();
+ return true;
+ }
+ }
+ unlock();
+ return false;
+}
+
+bool AUD_OpenALDevice::resume(AUD_Handle* handle)
+{
+ // only songs that are paused can be resumed
+ lock();
+ for(AUD_HandleIterator i = m_pausedSounds->begin();
+ i != m_pausedSounds->end(); i++)
+ {
+ if(*i == handle)
+ {
+ m_playingSounds->push_back(*i);
+ alSourcePlay((*i)->source);
+ start();
+ m_pausedSounds->erase(i);
+ unlock();
+ return true;
+ }
+ }
+ unlock();
+ return false;
+}
+
+bool AUD_OpenALDevice::stop(AUD_Handle* handle)
+{
+ AUD_OpenALHandle* sound;
+
+ 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; AUD_DELETE("reader")
+ alDeleteBuffers(3, sound->buffers);
+ }
+ delete *i; AUD_DELETE("handle")
+ m_playingSounds->erase(i);
+ unlock();
+ return true;
+ }
+ }
+ 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; AUD_DELETE("reader")
+ alDeleteBuffers(3, sound->buffers);
+ }
+ delete *i; AUD_DELETE("handle")
+ m_pausedSounds->erase(i);
+ unlock();
+ return true;
+ }
+ }
+ unlock();
+ return false;
+}
+
+bool AUD_OpenALDevice::setKeep(AUD_Handle* handle, bool keep)
+{
+ lock();
+ if(isValid(handle))
+ {
+ ((AUD_OpenALHandle*)handle)->keep = keep;
+ unlock();
+ return true;
+ }
+ unlock();
+ return false;
+}
+
+bool AUD_OpenALDevice::sendMessage(AUD_Handle* handle, AUD_Message &message)
+{
+ lock();
+
+ bool result = false;
+
+ if(handle == 0)
+ {
+ for(AUD_HandleIterator i = m_playingSounds->begin();
+ i != m_playingSounds->end(); i++)
+ if(!(*i)->isBuffered)
+ result |= (*i)->reader->notify(message);
+ for(AUD_HandleIterator i = m_pausedSounds->begin();
+ i != m_pausedSounds->end(); i++)
+ if(!(*i)->isBuffered)
+ result |= (*i)->reader->notify(message);
+ }
+ else if(isValid(handle))
+ if(!((AUD_OpenALHandle*)handle)->isBuffered)
+ result = ((AUD_OpenALHandle*)handle)->reader->notify(message);
+ unlock();
+ return result;
+}
+
+bool AUD_OpenALDevice::seek(AUD_Handle* handle, float position)
+{
+ 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));
+ unlock();
+ return true;
+ }
+
+ unlock();
+ return false;
+}
+
+AUD_Status AUD_OpenALDevice::getStatus(AUD_Handle* handle)
+{
+ lock();
+ for(AUD_HandleIterator i = m_playingSounds->begin();
+ i != m_playingSounds->end(); i++)
+ {
+ if(*i == handle)
+ {
+ unlock();
+ return AUD_STATUS_PLAYING;
+ }
+ }
+ for(AUD_HandleIterator i = m_pausedSounds->begin();
+ i != m_pausedSounds->end(); i++)
+ {
+ if(*i == handle)
+ {
+ unlock();
+ return AUD_STATUS_PAUSED;
+ }
+ }
+ unlock();
+ return AUD_STATUS_INVALID;
+}
+
+void AUD_OpenALDevice::lock()
+{
+ pthread_mutex_lock(&m_mutex);
+}
+
+void AUD_OpenALDevice::unlock()
+{
+ pthread_mutex_unlock(&m_mutex);
+}
+
+/******************************************************************************/
+/**************************** Capabilities Code *******************************/
+/******************************************************************************/
+
+bool AUD_OpenALDevice::checkCapability(int capability)
+{
+ return capability == AUD_CAPS_3D_DEVICE ||
+ capability == AUD_CAPS_VOLUME ||
+ capability == AUD_CAPS_SOURCE_VOLUME ||
+ capability == AUD_CAPS_SOURCE_PITCH ||
+ capability == AUD_CAPS_BUFFERED_FACTORY;
+}
+
+bool AUD_OpenALDevice::setCapability(int capability, void *value)
+{
+ switch(capability)
+ {
+ case AUD_CAPS_VOLUME:
+ alListenerf(AL_GAIN, *((float*)value));
+ return true;
+ case AUD_CAPS_SOURCE_VOLUME:
+ {
+ AUD_SourceCaps* caps = (AUD_SourceCaps*) value;
+ lock();
+ if(isValid(caps->handle))
+ {
+ alSourcef(((AUD_OpenALHandle*)caps->handle)->source,
+ AL_GAIN, caps->value);
+ unlock();
+ return true;
+ }
+ unlock();
+ }
+ break;
+ case AUD_CAPS_SOURCE_PITCH:
+ {
+ AUD_SourceCaps* caps = (AUD_SourceCaps*) value;
+ lock();
+ if(isValid(caps->handle))
+ {
+ alSourcef(((AUD_OpenALHandle*)caps->handle)->source,
+ AL_PITCH, caps->value);
+ unlock();
+ return true;
+ }
+ unlock();
+ }
+ break;
+ case AUD_CAPS_BUFFERED_FACTORY:
+ {
+ AUD_IFactory* factory = (AUD_IFactory*) value;
+
+ // load the factory into an OpenAL buffer
+ if(factory)
+ {
+ lock();
+ for(AUD_BFIterator i = m_bufferedFactories->begin();
+ i != m_bufferedFactories->end(); i++)
+ {
+ if((*i)->factory == factory)
+ {
+ unlock();
+ return true;
+ }
+ }
+ unlock();
+
+ AUD_IReader* reader = factory->createReader();
+
+ if(reader == NULL)
+ return false;
+
+ AUD_Specs specs;
+
+ specs = reader->getSpecs();
+
+ // determine format
+ bool valid = reader->getType() == AUD_TYPE_BUFFER;
+
+ if(valid)
+ {
+ if(specs.format == AUD_FORMAT_INVALID)
+ valid = false;
+ else if(specs.format == AUD_FORMAT_S24 ||
+ specs.format == AUD_FORMAT_S32 ||
+ specs.format == AUD_FORMAT_FLOAT32 ||
+ specs.format == AUD_FORMAT_FLOAT64)
+ {
+ m_converter->setReader(reader);
+ reader = m_converter->createReader();
+ specs = reader->getSpecs();
+ }
+ }
+
+ ALenum format;
+
+ if(valid)
+ valid = getFormat(format, specs);
+
+ if(!valid)
+ {
+ delete reader; AUD_DELETE("reader")
+ return false;
+ }
+
+ // load into a buffer
+ lock();
+ alcSuspendContext(m_context);
+
+ AUD_OpenALBufferedFactory* bf = new AUD_OpenALBufferedFactory;
+ AUD_NEW("bufferedfactory");
+ bf->factory = factory;
+
+ try
+ {
+ alGenBuffers(1, &bf->buffer);
+ if(alGetError() != AL_NO_ERROR)
+ AUD_THROW(AUD_ERROR_OPENAL);
+
+ try
+ {
+ sample_t* buf;
+ int length = reader->getLength();
+
+ reader->read(length, buf);
+ alBufferData(bf->buffer, format, buf,
+ length * AUD_SAMPLE_SIZE(specs),
+ specs.rate);
+ if(alGetError() != AL_NO_ERROR)
+ AUD_THROW(AUD_ERROR_OPENAL);
+ }
+ catch(AUD_Exception e)
+ {
+ alDeleteBuffers(1, &bf->buffer);
+ throw;
+ }
+ }
+ catch(AUD_Exception e)
+ {
+ delete bf; AUD_DELETE("bufferedfactory")
+ delete reader; AUD_DELETE("reader")
+ alcProcessContext(m_context);
+ unlock();
+ return false;
+ }
+
+ m_bufferedFactories->push_back(bf);
+
+ alcProcessContext(m_context);
+ unlock();
+ }
+ else
+ {
+ // stop all playing and paused buffered sources
+ lock();
+ alcSuspendContext(m_context);
+
+ AUD_OpenALHandle* sound;
+ AUD_HandleIterator it = m_playingSounds->begin();
+ while(it != m_playingSounds->end())
+ {
+ sound = *it;
+ ++it;
+
+ if(sound->isBuffered)
+ stop(sound);
+ }
+ alcProcessContext(m_context);
+
+ while(!m_bufferedFactories->empty())
+ {
+ alDeleteBuffers(1,
+ &(*(m_bufferedFactories->begin()))->buffer);
+ delete *m_bufferedFactories->begin();
+ AUD_DELETE("bufferedfactory");
+ m_bufferedFactories->erase(m_bufferedFactories->begin());
+ }
+ unlock();
+ }
+
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+bool AUD_OpenALDevice::getCapability(int capability, void *value)
+{
+ switch(capability)
+ {
+ case AUD_CAPS_VOLUME:
+ alGetListenerf(AL_GAIN, (float*)value);
+ return true;
+ case AUD_CAPS_SOURCE_VOLUME:
+ {
+ AUD_SourceCaps* caps = (AUD_SourceCaps*) value;
+ lock();
+ if(isValid(caps->handle))
+ {
+ alGetSourcef(((AUD_OpenALHandle*)caps->handle)->source,
+ AL_GAIN, &caps->value);
+ unlock();
+ return true;
+ }
+ unlock();
+ }
+ break;
+ case AUD_CAPS_SOURCE_PITCH:
+ {
+ AUD_SourceCaps* caps = (AUD_SourceCaps*) value;
+ lock();
+ if(isValid(caps->handle))
+ {
+ alGetSourcef(((AUD_OpenALHandle*)caps->handle)->source,
+ AL_PITCH, &caps->value);
+ unlock();
+ return true;
+ }
+ unlock();
+ }
+ break;
+ }
+ return false;
+}
+
+/******************************************************************************/
+/**************************** 3D Device Code **********************************/
+/******************************************************************************/
+
+AUD_Handle* AUD_OpenALDevice::play3D(AUD_IFactory* factory, bool keep)
+{
+ return play(factory, keep);
+}
+
+bool AUD_OpenALDevice::updateListener(AUD_3DData &data)
+{
+ alListenerfv(AL_POSITION, (ALfloat*)data.position);
+ alListenerfv(AL_VELOCITY, (ALfloat*)data.velocity);
+ alListenerfv(AL_ORIENTATION, (ALfloat*)data.orientation);
+}
+
+bool AUD_OpenALDevice::setSetting(AUD_3DSetting setting, float value)
+{
+ switch(setting)
+ {
+ case AUD_3DS_DISTANCE_MODEL:
+ if(value == AUD_DISTANCE_MODEL_NONE)
+ alDistanceModel(AL_NONE);
+ else if(value == AUD_DISTANCE_MODEL_INVERSE)
+ alDistanceModel(AL_INVERSE_DISTANCE);
+ else if(value == AUD_DISTANCE_MODEL_INVERSE_CLAMPED)
+ alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
+ else if(value == AUD_DISTANCE_MODEL_LINEAR)
+ alDistanceModel(AL_LINEAR_DISTANCE);
+ else if(value == AUD_DISTANCE_MODEL_LINEAR_CLAMPED)
+ alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
+ else if(value == AUD_DISTANCE_MODEL_EXPONENT)
+ alDistanceModel(AL_EXPONENT_DISTANCE);
+ else if(value == AUD_DISTANCE_MODEL_EXPONENT_CLAMPED)
+ alDistanceModel(AL_EXPONENT_DISTANCE_CLAMPED);
+ else
+ return false;
+ return true;
+ case AUD_3DS_DOPPLER_FACTOR:
+ alDopplerFactor(value);
+ return true;
+ case AUD_3DS_SPEED_OF_SOUND:
+ alSpeedOfSound(value);
+ return true;
+ }
+ return false;
+}
+
+float AUD_OpenALDevice::getSetting(AUD_3DSetting setting)
+{
+ switch(setting)
+ {
+ case AUD_3DS_DISTANCE_MODEL:
+ switch(alGetInteger(AL_DISTANCE_MODEL))
+ {
+ case AL_NONE:
+ return AUD_DISTANCE_MODEL_NONE;
+ case AL_INVERSE_DISTANCE:
+ return AUD_DISTANCE_MODEL_INVERSE;
+ case AL_INVERSE_DISTANCE_CLAMPED:
+ return AUD_DISTANCE_MODEL_INVERSE_CLAMPED;
+ case AL_LINEAR_DISTANCE:
+ return AUD_DISTANCE_MODEL_LINEAR;
+ case AL_LINEAR_DISTANCE_CLAMPED:
+ return AUD_DISTANCE_MODEL_LINEAR_CLAMPED;
+ case AL_EXPONENT_DISTANCE:
+ return AUD_DISTANCE_MODEL_EXPONENT;
+ case AL_EXPONENT_DISTANCE_CLAMPED:
+ return AUD_DISTANCE_MODEL_EXPONENT_CLAMPED;
+ }
+ case AUD_3DS_DOPPLER_FACTOR:
+ return alGetFloat(AL_DOPPLER_FACTOR);
+ case AUD_3DS_SPEED_OF_SOUND:
+ return alGetFloat(AL_SPEED_OF_SOUND);
+ }
+ return std::numeric_limits<float>::quiet_NaN();
+}
+
+bool AUD_OpenALDevice::updateSource(AUD_Handle* handle, AUD_3DData &data)
+{
+ lock();
+
+ if(isValid(handle))
+ {
+ int source = ((AUD_OpenALHandle*)handle)->source;
+ alSourcefv(source, AL_POSITION, (ALfloat*)data.position);
+ alSourcefv(source, AL_VELOCITY, (ALfloat*)data.velocity);
+ alSourcefv(source, AL_ORIENTATION, (ALfloat*)data.orientation);
+ unlock();
+ return true;
+ }
+
+ unlock();
+ return false;
+}
+
+bool AUD_OpenALDevice::setSourceSetting(AUD_Handle* handle,
+ AUD_3DSourceSetting setting,
+ float value)
+{
+ lock();
+
+ bool result = false;
+
+ if(isValid(handle))
+ {
+ int source = ((AUD_OpenALHandle*)handle)->source;
+
+ switch(setting)
+ {
+ case AUD_3DSS_CONE_INNER_ANGLE:
+ alSourcef(source, AL_CONE_INNER_ANGLE, value);
+ result = true;
+ break;
+ case AUD_3DSS_CONE_OUTER_ANGLE:
+ alSourcef(source, AL_CONE_OUTER_ANGLE, value);
+ result = true;
+ break;
+ case AUD_3DSS_CONE_OUTER_GAIN:
+ alSourcef(source, AL_CONE_OUTER_GAIN, value);
+ result = true;
+ break;
+ case AUD_3DSS_IS_RELATIVE:
+ alSourcei(source, AL_SOURCE_RELATIVE, value > 1.0);
+ result = true;
+ break;
+ case AUD_3DSS_MAX_DISTANCE:
+ alSourcef(source, AL_MAX_DISTANCE, value);
+ result = true;
+ break;
+ case AUD_3DSS_MAX_GAIN:
+ alSourcef(source, AL_MAX_GAIN, value);
+ result = true;
+ break;
+ case AUD_3DSS_MIN_GAIN:
+ alSourcef(source, AL_MIN_GAIN, value);
+ result = true;
+ break;
+ case AUD_3DSS_REFERENCE_DISTANCE:
+ alSourcef(source, AL_REFERENCE_DISTANCE, value);
+ result = true;
+ break;
+ case AUD_3DSS_ROLLOFF_FACTOR:
+ alSourcef(source, AL_ROLLOFF_FACTOR, value);
+ result = true;
+ break;
+ }
+ }
+
+ unlock();
+ return result;
+}
+
+float AUD_OpenALDevice::getSourceSetting(AUD_Handle* handle,
+ AUD_3DSourceSetting setting)
+{
+ float result = std::numeric_limits<float>::quiet_NaN();;
+
+ lock();
+
+ if(isValid(handle))
+ {
+ int source = ((AUD_OpenALHandle*)handle)->source;
+
+ switch(setting)
+ {
+ case AUD_3DSS_CONE_INNER_ANGLE:
+ alGetSourcef(source, AL_CONE_INNER_ANGLE, &result);
+ break;
+ case AUD_3DSS_CONE_OUTER_ANGLE:
+ alGetSourcef(source, AL_CONE_OUTER_ANGLE, &result);
+ break;
+ case AUD_3DSS_CONE_OUTER_GAIN:
+ alGetSourcef(source, AL_CONE_OUTER_GAIN, &result);
+ break;
+ case AUD_3DSS_IS_RELATIVE:
+ {
+ ALint i;
+ alGetSourcei(source, AL_SOURCE_RELATIVE, &i);
+ result = i ? 1.0 : 0.0;
+ break;
+ }
+ case AUD_3DSS_MAX_DISTANCE:
+ alGetSourcef(source, AL_MAX_DISTANCE, &result);
+ break;
+ case AUD_3DSS_MAX_GAIN:
+ alGetSourcef(source, AL_MAX_GAIN, &result);
+ break;
+ case AUD_3DSS_MIN_GAIN:
+ alGetSourcef(source, AL_MIN_GAIN, &result);
+ break;
+ case AUD_3DSS_REFERENCE_DISTANCE:
+ alGetSourcef(source, AL_REFERENCE_DISTANCE, &result);
+ break;
+ case AUD_3DSS_ROLLOFF_FACTOR:
+ alGetSourcef(source, AL_ROLLOFF_FACTOR, &result);
+ break;
+ }
+ }
+
+ unlock();
+ return result;
+}
diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.h b/intern/audaspace/OpenAL/AUD_OpenALDevice.h
new file mode 100644
index 00000000000..e1d86867fd6
--- /dev/null
+++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.h
@@ -0,0 +1,170 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_OPENALDEVICE
+#define AUD_OPENALDEVICE
+
+#include "AUD_IDevice.h"
+#include "AUD_I3DDevice.h"
+struct AUD_OpenALHandle;
+struct AUD_OpenALBufferedFactory;
+class AUD_ConverterFactory;
+
+#include <al.h>
+#include <alc.h>
+#include <list>
+#include <pthread.h>
+
+/**
+ * This device plays through OpenAL.
+ */
+class AUD_OpenALDevice : public AUD_IDevice, public AUD_I3DDevice
+{
+private:
+ /**
+ * The OpenAL device handle.
+ */
+ ALCdevice* m_device;
+
+ /**
+ * The OpenAL context.
+ */
+ ALCcontext* m_context;
+
+ /**
+ * The specification of the device.
+ */
+ AUD_Specs m_specs;
+
+ /**
+ * Whether the device has the AL_EXT_MCFORMATS extension.
+ */
+ bool m_useMC;
+
+ /**
+ * The converter factory for readers with wrong input format.
+ */
+ AUD_ConverterFactory* m_converter;
+
+ /**
+ * The list of sounds that are currently playing.
+ */
+ std::list<AUD_OpenALHandle*>* m_playingSounds;
+
+ /**
+ * The list of sounds that are currently paused.
+ */
+ std::list<AUD_OpenALHandle*>* m_pausedSounds;
+
+ /**
+ * The list of buffered factories.
+ */
+ std::list<AUD_OpenALBufferedFactory*>* m_bufferedFactories;
+
+ /**
+ * The mutex for locking.
+ */
+ pthread_mutex_t m_mutex;
+
+ /**
+ * The streaming thread.
+ */
+ pthread_t m_thread;
+
+ /**
+ * The condition for streaming thread wakeup.
+ */
+ bool m_playing;
+
+ /**
+ * Buffer size.
+ */
+ int m_buffersize;
+
+ /**
+ * Starts the streaming thread.
+ */
+ void start();
+
+ /**
+ * Checks if a handle is valid.
+ * \param handle The handle to check.
+ * \return Whether the handle is valid.
+ */
+ bool isValid(AUD_Handle* handle);
+
+ /**
+ * Gets the format according to the specs.
+ * \param format The variable to put the format into.
+ * \param specs The specs to read the format from.
+ * \return Whether the format is valid or not.
+ */
+ bool getFormat(ALenum &format, AUD_Specs specs);
+
+public:
+ /**
+ * Opens the OpenAL audio device for playback.
+ * \param specs The wanted audio specification.
+ * \param buffersize The size of the internal buffer.
+ * \note The specification really used for opening the device may differ.
+ * \note The buffersize will be multiplicated by three for this device.
+ * \exception AUD_Exception Thrown if the audio device cannot be opened.
+ */
+ AUD_OpenALDevice(AUD_Specs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE);
+
+ /**
+ * Streaming thread main function.
+ */
+ void updateStreams();
+
+ virtual ~AUD_OpenALDevice();
+
+ virtual AUD_Specs getSpecs();
+ 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 setKeep(AUD_Handle* handle, bool keep);
+ virtual bool sendMessage(AUD_Handle* handle, AUD_Message &message);
+ virtual bool seek(AUD_Handle* handle, float position);
+ virtual AUD_Status getStatus(AUD_Handle* handle);
+ virtual void lock();
+ virtual void unlock();
+ virtual bool checkCapability(int capability);
+ virtual bool setCapability(int capability, void *value);
+ virtual bool getCapability(int capability, void *value);
+
+ virtual AUD_Handle* play3D(AUD_IFactory* factory, bool keep = false);
+ virtual bool updateListener(AUD_3DData &data);
+ virtual bool setSetting(AUD_3DSetting setting, float value);
+ virtual float getSetting(AUD_3DSetting setting);
+ virtual bool updateSource(AUD_Handle* handle, AUD_3DData &data);
+ virtual bool setSourceSetting(AUD_Handle* handle,
+ AUD_3DSourceSetting setting, float value);
+ virtual float getSourceSetting(AUD_Handle* handle,
+ AUD_3DSourceSetting setting);
+};
+
+#endif //AUD_OPENALDEVICE
diff --git a/intern/audaspace/SConscript b/intern/audaspace/SConscript
index 4ef723a7093..7d8a803ff7e 100644
--- a/intern/audaspace/SConscript
+++ b/intern/audaspace/SConscript
@@ -2,12 +2,23 @@
Import ('env')
-sources = env.Glob('SDL/*.cpp') + env.Glob('intern/*.cpp')
-
-incs = '. intern intern SDL ffmpeg ' + env['BF_SDL_INC'] + ' ' + env['BF_PTHREADS_INC']
+sources = env.Glob('intern/*.cpp') + env.Glob('FX/*.cpp') + env.Glob('SRC/*.cpp')
+incs = '. intern FX SRC ' + env['BF_PTHREADS_INC'] + ' ' + env['BF_LIBSAMPLERATE_INC']
defs = ''
+
if env['WITH_BF_FFMPEG']:
sources += env.Glob('ffmpeg/*.cpp')
- incs += ' ' + env['BF_FFMPEG_INC']
+ incs += ' ffmpeg ' + env['BF_FFMPEG_INC']
+ defs = 'WITH_FFMPEG'
+
+if env['WITH_BF_SDL']:
+ sources += env.Glob('SDL/*.cpp')
+ incs += ' SDL ' + env['BF_SDL_INC']
+ defs = 'WITH_SDL'
+
+if env['WITH_BF_OPENAL']:
+ sources += env.Glob('OpenAL/*.cpp')
+ incs += ' OpenAL ' + env['BF_OPENAL_INC']
+ defs = 'WITH_OPENAL'
env.BlenderLib ('bf_audaspace', sources, Split(incs), Split(defs), libtype=['intern'], priority = [25] )
diff --git a/intern/audaspace/SDL/AUD_SDLDevice.cpp b/intern/audaspace/SDL/AUD_SDLDevice.cpp
index d742b3c3da0..9ea5f1a74ee 100644
--- a/intern/audaspace/SDL/AUD_SDLDevice.cpp
+++ b/intern/audaspace/SDL/AUD_SDLDevice.cpp
@@ -23,10 +23,9 @@
* ***** END LGPL LICENSE BLOCK *****
*/
+#include "AUD_SDLMixer.h"
#include "AUD_SDLDevice.h"
-#include "AUD_SDLMixerFactory.h"
#include "AUD_IReader.h"
-#include "AUD_SDLSuperposer.h"
#include <SDL.h>
@@ -37,13 +36,18 @@ void mixAudio(void *data, Uint8* buffer, int length)
device->SDLmix((sample_t *)buffer, length);
}
-void AUD_SDLDevice::init()
+AUD_SDLDevice::AUD_SDLDevice(AUD_Specs specs, int buffersize)
{
- SDL_AudioSpec format, obtained;
+ if(specs.channels == AUD_CHANNELS_INVALID)
+ specs.channels = AUD_CHANNELS_STEREO;
+ if(specs.format == AUD_FORMAT_INVALID)
+ specs.format = AUD_FORMAT_S16;
+ if(specs.rate == AUD_RATE_INVALID)
+ specs.rate = AUD_RATE_44100;
- // SDL only supports mono and stereo
- if(m_specs.channels > 2)
- m_specs.channels = AUD_CHANNELS_STEREO;
+ m_specs = specs;
+
+ SDL_AudioSpec format, obtained;
format.freq = m_specs.rate;
if(m_specs.format == AUD_FORMAT_U8)
@@ -51,7 +55,7 @@ void AUD_SDLDevice::init()
else
format.format = AUDIO_S16SYS;
format.channels = m_specs.channels;
- format.samples = 1024;
+ format.samples = buffersize;
format.callback = &mixAudio;
format.userdata = this;
@@ -67,33 +71,19 @@ void AUD_SDLDevice::init()
else
AUD_THROW(AUD_ERROR_SDL);
- m_mixer = new AUD_SDLMixerFactory(m_specs);
- m_superposer = new AUD_SDLSuperposer();
+ m_mixer = new AUD_SDLMixer(); AUD_NEW("mixer")
+ m_mixer->setSpecs(m_specs);
create();
}
-AUD_SDLDevice::AUD_SDLDevice(AUD_Specs specs)
-{
- m_specs = specs;
-
- init();
-}
-
-AUD_SDLDevice::AUD_SDLDevice()
-{
- m_specs.channels = AUD_CHANNELS_STEREO;
- m_specs.format = AUD_FORMAT_S16;
- m_specs.rate = AUD_RATE_44100;
-
- init();
-}
-
AUD_SDLDevice::~AUD_SDLDevice()
{
- destroy();
-
+ lock();
SDL_CloseAudio();
+ unlock();
+
+ destroy();
}
void AUD_SDLDevice::SDLmix(sample_t* buffer, int length)
diff --git a/intern/audaspace/SDL/AUD_SDLDevice.h b/intern/audaspace/SDL/AUD_SDLDevice.h
index fa24508a2f6..3eb93d28762 100644
--- a/intern/audaspace/SDL/AUD_SDLDevice.h
+++ b/intern/audaspace/SDL/AUD_SDLDevice.h
@@ -28,8 +28,6 @@
#include "AUD_SoftwareDevice.h"
-#include <list>
-
/**
* This device plays back through SDL, the simple direct media layer.
*/
@@ -38,26 +36,15 @@ class AUD_SDLDevice : public AUD_SoftwareDevice
protected:
virtual void playing(bool playing);
-private:
- /**
- * Initializes the device.
- */
- void init();
-
public:
/**
* Opens the SDL audio device for playback.
- * \exception AUD_Exception Thrown if the audio device cannot be opened.
- */
- AUD_SDLDevice();
-
- /**
- * Opens the SDL audio device for playback.
* \param specs The wanted audio specification.
+ * \param buffersize The size of the internal buffer.
* \note The specification really used for opening the device may differ.
* \exception AUD_Exception Thrown if the audio device cannot be opened.
*/
- AUD_SDLDevice(AUD_Specs specs);
+ AUD_SDLDevice(AUD_Specs specs, int buffersize = AUD_DEFAULT_BUFFER_SIZE);
/**
* Closes the SDL audio device.
diff --git a/intern/audaspace/SDL/AUD_SDLMixer.cpp b/intern/audaspace/SDL/AUD_SDLMixer.cpp
new file mode 100644
index 00000000000..cacc0c7063c
--- /dev/null
+++ b/intern/audaspace/SDL/AUD_SDLMixer.cpp
@@ -0,0 +1,83 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_SDLMixer.h"
+#include "AUD_SDLMixerFactory.h"
+
+#include <SDL.h>
+
+AUD_SDLMixer::AUD_SDLMixer()
+{
+ m_factory = NULL;
+}
+
+AUD_SDLMixer::~AUD_SDLMixer()
+{
+ if(m_factory)
+ {
+ delete m_factory; AUD_DELETE("factory")
+ }
+}
+
+AUD_IReader* AUD_SDLMixer::prepare(AUD_IReader* reader)
+{
+ m_factory->setReader(reader);
+ return m_factory->createReader();
+}
+
+void AUD_SDLMixer::setSpecs(AUD_Specs specs)
+{
+ m_samplesize = AUD_SAMPLE_SIZE(specs);
+ if(m_factory)
+ {
+ delete m_factory; AUD_DELETE("factory")
+ }
+ m_factory = new AUD_SDLMixerFactory(specs); AUD_NEW("factory")
+}
+
+void AUD_SDLMixer::add(sample_t* buffer, AUD_Specs specs, int length,
+ float volume)
+{
+ AUD_SDLMixerBuffer buf;
+ buf.buffer = buffer;
+ buf.length = length;
+ buf.volume = volume;
+ m_buffers.push_back(buf);
+}
+
+void AUD_SDLMixer::superpose(sample_t* buffer, int length, float volume)
+{
+ AUD_SDLMixerBuffer buf;
+
+ while(!m_buffers.empty())
+ {
+ buf = m_buffers.front();
+ m_buffers.pop_front();
+ SDL_MixAudio((Uint8*)buffer,
+ (Uint8*)buf.buffer,
+ buf.length * m_samplesize,
+ (int)(SDL_MIX_MAXVOLUME * volume * buf.volume));
+ }
+}
diff --git a/intern/audaspace/SDL/AUD_SDLMixer.h b/intern/audaspace/SDL/AUD_SDLMixer.h
new file mode 100644
index 00000000000..2cc4e51f66d
--- /dev/null
+++ b/intern/audaspace/SDL/AUD_SDLMixer.h
@@ -0,0 +1,76 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_SDLMIXER
+#define AUD_SDLMIXER
+
+#include "AUD_IMixer.h"
+class AUD_SDLMixerFactory;
+#include <list>
+
+struct AUD_SDLMixerBuffer
+{
+ sample_t* buffer;
+ int length;
+ float volume;
+};
+
+/**
+ * This class is able to mix audiosignals with the help of SDL.
+ */
+class AUD_SDLMixer : public AUD_IMixer
+{
+private:
+ /**
+ * The mixer factory that prepares all readers for superposition.
+ */
+ AUD_SDLMixerFactory* m_factory;
+
+ /**
+ * The list of buffers to superpose.
+ */
+ std::list<AUD_SDLMixerBuffer> m_buffers;
+
+ /**
+ * The size of an output sample.
+ */
+ int m_samplesize;
+
+public:
+ /**
+ * Creates the mixer.
+ */
+ AUD_SDLMixer();
+
+ virtual ~AUD_SDLMixer();
+
+ virtual AUD_IReader* prepare(AUD_IReader* reader);
+ virtual void setSpecs(AUD_Specs specs);
+ virtual void add(sample_t* buffer, AUD_Specs specs, int length,
+ float volume);
+ virtual void superpose(sample_t* buffer, int length, float volume);
+};
+
+#endif //AUD_SDLMIXER
diff --git a/intern/audaspace/SDL/AUD_SDLMixerFactory.cpp b/intern/audaspace/SDL/AUD_SDLMixerFactory.cpp
index d68ab722d76..1633a1498fa 100644
--- a/intern/audaspace/SDL/AUD_SDLMixerFactory.cpp
+++ b/intern/audaspace/SDL/AUD_SDLMixerFactory.cpp
@@ -26,21 +26,37 @@
#include "AUD_SDLMixerFactory.h"
#include "AUD_SDLMixerReader.h"
+AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_IReader* reader, AUD_Specs specs) :
+ AUD_MixerFactory(reader, specs) {}
+
+AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_IFactory* factory, AUD_Specs specs) :
+ AUD_MixerFactory(factory, specs) {}
+
+AUD_SDLMixerFactory::AUD_SDLMixerFactory(AUD_Specs specs) :
+ AUD_MixerFactory(specs) {}
+
AUD_IReader* AUD_SDLMixerFactory::createReader()
{
AUD_IReader* reader = getReader();
if(reader != 0)
{
- try
- {
- reader = new AUD_SDLMixerReader(reader, m_specs); AUD_NEW("reader")
- }
- catch(AUD_Exception e)
+ AUD_Specs specs = reader->getSpecs();
+ if(memcmp(&m_specs, &specs, sizeof(AUD_Specs)) != 0)
{
- // return 0 in case SDL cannot mix the source
- if(e.error != AUD_ERROR_SDL)
- throw;
+ try
+ {
+ reader = new AUD_SDLMixerReader(reader, m_specs);
+ AUD_NEW("reader")
+ }
+ catch(AUD_Exception e)
+ {
+ // return 0 in case SDL cannot mix the source
+ if(e.error != AUD_ERROR_SDL)
+ throw;
+ else
+ reader = NULL;
+ }
}
}
return reader;
diff --git a/intern/audaspace/SDL/AUD_SDLMixerFactory.h b/intern/audaspace/SDL/AUD_SDLMixerFactory.h
index eb704673689..44b36d06859 100644
--- a/intern/audaspace/SDL/AUD_SDLMixerFactory.h
+++ b/intern/audaspace/SDL/AUD_SDLMixerFactory.h
@@ -35,12 +35,9 @@
class AUD_SDLMixerFactory : public AUD_MixerFactory
{
public:
- AUD_SDLMixerFactory(AUD_IReader* reader, AUD_Specs specs) :
- AUD_MixerFactory(reader, specs) {}
- AUD_SDLMixerFactory(AUD_IFactory* factory, AUD_Specs specs) :
- AUD_MixerFactory(factory, specs) {}
- AUD_SDLMixerFactory(AUD_Specs specs) :
- AUD_MixerFactory(specs) {}
+ AUD_SDLMixerFactory(AUD_IReader* reader, AUD_Specs specs);
+ AUD_SDLMixerFactory(AUD_IFactory* factory, AUD_Specs specs);
+ AUD_SDLMixerFactory(AUD_Specs specs);
virtual AUD_IReader* createReader();
};
diff --git a/intern/audaspace/SDL/AUD_SDLMixerReader.cpp b/intern/audaspace/SDL/AUD_SDLMixerReader.cpp
index f5ecfd0d15e..1a0d990eaf2 100644
--- a/intern/audaspace/SDL/AUD_SDLMixerReader.cpp
+++ b/intern/audaspace/SDL/AUD_SDLMixerReader.cpp
@@ -75,10 +75,7 @@ AUD_SDLMixerReader::AUD_SDLMixerReader(AUD_IReader* reader,
try
{
- // SDL only supports mono and stereo
- if(m_tspecs.channels > 2 || m_sspecs.channels > 2)
- AUD_THROW(AUD_ERROR_SDL);
-
+ // SDL only supports 8 and 16 bit sample formats
if(SDL_BuildAudioCVT(&m_cvt,
AUD_TO_SDL(m_sspecs.format),
m_sspecs.channels,
@@ -100,8 +97,8 @@ AUD_SDLMixerReader::AUD_SDLMixerReader(AUD_IReader* reader,
m_ssize = m_sspecs.rate / gcd(specs.rate, m_sspecs.rate);
m_tsize = m_tspecs.rate * m_ssize / m_sspecs.rate;
- m_buffer = new AUD_Buffer(0); AUD_NEW("buffer")
- m_rsbuffer = new AUD_Buffer(0); AUD_NEW("buffer")
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+ m_rsbuffer = new AUD_Buffer(); AUD_NEW("buffer")
}
AUD_SDLMixerReader::~AUD_SDLMixerReader()
@@ -142,6 +139,11 @@ AUD_ReaderType AUD_SDLMixerReader::getType()
return m_reader->getType();
}
+bool AUD_SDLMixerReader::notify(AUD_Message &message)
+{
+ return m_reader->notify(message);
+}
+
void AUD_SDLMixerReader::read(int & length, sample_t* & buffer)
{
// sample count for the target buffer without getting a shift
@@ -158,15 +160,15 @@ void AUD_SDLMixerReader::read(int & length, sample_t* & buffer)
// resize if necessary
if(m_rsbuffer->getSize() < buf_size)
- m_rsbuffer->resize(buf_size);
+ m_rsbuffer->resize(buf_size, true);
if(m_buffer->getSize() < length*tss)
- m_buffer->resize(length*tss, false);
+ m_buffer->resize(length*tss);
buffer = m_buffer->getBuffer();
int size;
int index = 0;
- unsigned char* buf;
+ sample_t* buf;
while(index < length)
{
diff --git a/intern/audaspace/SDL/AUD_SDLMixerReader.h b/intern/audaspace/SDL/AUD_SDLMixerReader.h
index cd835b87347..56668d02171 100644
--- a/intern/audaspace/SDL/AUD_SDLMixerReader.h
+++ b/intern/audaspace/SDL/AUD_SDLMixerReader.h
@@ -121,6 +121,7 @@ public:
virtual int getPosition();
virtual AUD_Specs getSpecs();
virtual AUD_ReaderType getType();
+ virtual bool notify(AUD_Message &message);
virtual void read(int & length, sample_t* & buffer);
};
diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp
new file mode 100644
index 00000000000..bcace340b24
--- /dev/null
+++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.cpp
@@ -0,0 +1,53 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_SRCResampleFactory.h"
+#include "AUD_SRCResampleReader.h"
+
+AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IReader* reader,
+ AUD_Specs specs) :
+ AUD_ResampleFactory(reader, specs) {}
+
+AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_IFactory* factory,
+ AUD_Specs specs) :
+ AUD_ResampleFactory(factory, specs) {}
+
+AUD_SRCResampleFactory::AUD_SRCResampleFactory(AUD_Specs specs) :
+ AUD_ResampleFactory(specs) {}
+
+AUD_IReader* AUD_SRCResampleFactory::createReader()
+{
+ AUD_IReader* reader = getReader();
+
+ if(reader != 0)
+ {
+ if(reader->getSpecs().rate != m_specs.rate)
+ {
+ reader = new AUD_SRCResampleReader(reader, m_specs);
+ AUD_NEW("reader")
+ }
+ }
+ return reader;
+}
diff --git a/intern/audaspace/SRC/AUD_SRCResampleFactory.h b/intern/audaspace/SRC/AUD_SRCResampleFactory.h
new file mode 100644
index 00000000000..c23c1d2c82e
--- /dev/null
+++ b/intern/audaspace/SRC/AUD_SRCResampleFactory.h
@@ -0,0 +1,46 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_SRCRESAMPLEFACTORY
+#define AUD_SRCRESAMPLEFACTORY
+
+#include "AUD_ResampleFactory.h"
+
+/**
+ * This factory creates a resampling reader that uses libsamplerate for
+ * resampling.
+ * \note The format of the input must be float.
+ */
+class AUD_SRCResampleFactory : public AUD_ResampleFactory
+{
+public:
+ AUD_SRCResampleFactory(AUD_IReader* reader, AUD_Specs specs);
+ AUD_SRCResampleFactory(AUD_IFactory* factory, AUD_Specs specs);
+ AUD_SRCResampleFactory(AUD_Specs specs);
+
+ virtual AUD_IReader* createReader();
+};
+
+#endif //AUD_SRCRESAMPLEFACTORY
diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.cpp b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp
new file mode 100644
index 00000000000..f7564d3c010
--- /dev/null
+++ b/intern/audaspace/SRC/AUD_SRCResampleReader.cpp
@@ -0,0 +1,119 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_SRCResampleReader.h"
+#include "AUD_Buffer.h"
+
+#include <math.h>
+#include <cstring>
+#include <stdio.h>
+
+static long src_callback(void *cb_data, float **data)
+{
+ return ((AUD_SRCResampleReader*)cb_data)->doCallback(data);
+}
+
+AUD_SRCResampleReader::AUD_SRCResampleReader(AUD_IReader* reader,
+ AUD_Specs specs) :
+ AUD_EffectReader(reader)
+{
+ m_sspecs = reader->getSpecs();
+
+ if(m_sspecs.format != AUD_FORMAT_FLOAT32)
+ {
+ delete m_reader; AUD_DELETE("reader")
+ AUD_THROW(AUD_ERROR_READER);
+ }
+
+ m_tspecs = specs;
+ m_tspecs.channels = m_sspecs.channels;
+ m_tspecs.format = m_sspecs.format;
+ m_factor = (double)m_tspecs.rate / (double)m_sspecs.rate;
+
+ int error;
+ m_src = src_callback_new(src_callback,
+ SRC_SINC_MEDIUM_QUALITY,
+ m_sspecs.channels,
+ &error,
+ this);
+
+ if(!m_src)
+ {
+ // XXX printf("%s\n", src_strerror(error));
+ delete m_reader; AUD_DELETE("reader")
+ AUD_THROW(AUD_ERROR_READER);
+ }
+
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+}
+
+AUD_SRCResampleReader::~AUD_SRCResampleReader()
+{
+ delete m_buffer; AUD_DELETE("buffer")
+
+ src_delete(m_src);
+}
+
+long AUD_SRCResampleReader::doCallback(float** data)
+{
+ int length = m_buffer->getSize() / 4 / m_tspecs.channels;
+ sample_t* buffer;
+
+ m_reader->read(length, buffer);
+
+ *data = (float*)buffer;
+ return length;
+}
+
+void AUD_SRCResampleReader::seek(int position)
+{
+ m_reader->seek(position / m_factor);
+ src_reset(m_src);
+}
+
+int AUD_SRCResampleReader::getLength()
+{
+ return m_reader->getLength() * m_factor;
+}
+
+int AUD_SRCResampleReader::getPosition()
+{
+ return m_reader->getPosition() * m_factor;
+}
+
+AUD_Specs AUD_SRCResampleReader::getSpecs()
+{
+ return m_tspecs;
+}
+
+void AUD_SRCResampleReader::read(int & length, sample_t* & buffer)
+{
+ if(m_buffer->getSize() < length * m_tspecs.channels * 4)
+ m_buffer->resize(length * m_tspecs.channels * 4);
+
+ buffer = m_buffer->getBuffer();
+
+ length = src_callback_read(m_src, m_factor, length, (float*)buffer);
+}
diff --git a/intern/audaspace/SRC/AUD_SRCResampleReader.h b/intern/audaspace/SRC/AUD_SRCResampleReader.h
new file mode 100644
index 00000000000..1bacdb3965c
--- /dev/null
+++ b/intern/audaspace/SRC/AUD_SRCResampleReader.h
@@ -0,0 +1,102 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_SRCRESAMPLEREADER
+#define AUD_SRCRESAMPLEREADER
+
+#include "AUD_EffectReader.h"
+class AUD_Buffer;
+
+#include <samplerate.h>
+
+/**
+ * This class mixes a sound source with help of the SDL library.
+ * Unfortunately SDL is only capable of 8 and 16 bit audio, mono and stereo, as
+ * well as resampling only 2^n sample rate relationships where n is a natural
+ * number.
+ * \warning Although SDL can only resample 2^n sample rate relationships, this
+ * class doesn't check for compliance, so in case of other factors,
+ * the behaviour is undefined.
+ */
+class AUD_SRCResampleReader : public AUD_EffectReader
+{
+private:
+ /**
+ * The resampling factor.
+ */
+ double m_factor;
+
+ /**
+ * The sound output buffer.
+ */
+ AUD_Buffer *m_buffer;
+
+ /**
+ * The target specification.
+ */
+ AUD_Specs m_tspecs;
+
+ /**
+ * The sample specification of the source.
+ */
+ AUD_Specs m_sspecs;
+
+ /**
+ * The src state structure.
+ */
+ SRC_STATE* m_src;
+
+public:
+ /**
+ * Creates a resampling reader.
+ * \param reader The reader to mix.
+ * \param specs The target specification.
+ * \exception AUD_Exception Thrown if the source specification cannot be
+ * mixed to the target specification or if the reader is
+ * NULL.
+ */
+ AUD_SRCResampleReader(AUD_IReader* reader, AUD_Specs specs);
+
+ /**
+ * Destroys the reader.
+ */
+ ~AUD_SRCResampleReader();
+
+ /**
+ * The callback function for SRC.
+ * \warning Do not call!
+ * \param data The pointer to the float data.
+ * \return The count of samples in the float data.
+ */
+ long doCallback(float** data);
+
+ virtual void seek(int position);
+ virtual int getLength();
+ virtual int getPosition();
+ virtual AUD_Specs getSpecs();
+ virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_SRCRESAMPLEREADER
diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp
index 2a1cfa90227..5f9006b0ec0 100644
--- a/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp
+++ b/intern/audaspace/ffmpeg/AUD_FFMPEGFactory.cpp
@@ -33,8 +33,13 @@ extern "C" {
AUD_FFMPEGFactory::AUD_FFMPEGFactory(const char* filename)
{
- m_filename = new char[strlen(filename)+1];
- strcpy(m_filename, filename);
+ if(filename != 0)
+ {
+ m_filename = new char[strlen(filename)+1]; AUD_NEW("string")
+ strcpy(m_filename, filename);
+ }
+ else
+ m_filename = 0;
m_buffer = 0;
m_size = 0;
}
@@ -42,7 +47,7 @@ AUD_FFMPEGFactory::AUD_FFMPEGFactory(const char* filename)
AUD_FFMPEGFactory::AUD_FFMPEGFactory(unsigned char* buffer, int size)
{
m_filename = 0;
- m_buffer = (unsigned char*)av_malloc(size);
+ m_buffer = (unsigned char*)av_malloc(size); AUD_NEW("buffer")
m_size = size;
memcpy(m_buffer, buffer, size);
}
@@ -50,9 +55,13 @@ AUD_FFMPEGFactory::AUD_FFMPEGFactory(unsigned char* buffer, int size)
AUD_FFMPEGFactory::~AUD_FFMPEGFactory()
{
if(m_filename)
- delete[] m_filename;
+ {
+ delete[] m_filename; AUD_DELETE("string")
+ }
if(m_buffer)
- av_free(m_buffer);
+ {
+ av_free(m_buffer); AUD_DELETE("buffer")
+ }
}
AUD_IReader* AUD_FFMPEGFactory::createReader()
diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
index 01898a884d4..50d609094cb 100644
--- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
+++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp
@@ -66,9 +66,6 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename)
if(av_find_stream_info(m_formatCtx)<0)
AUD_THROW(AUD_ERROR_FFMPEG);
- // this prints file information to stdout:
- //dump_format(m_formatCtx, 0, filename, 0);
-
// find audio stream and codec
m_stream = -1;
@@ -84,10 +81,6 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename)
m_codecCtx = m_formatCtx->streams[m_stream]->codec;
- m_specs.channels = (AUD_Channels) m_codecCtx->channels;
- m_specs.format = FFMPEG_TO_AUD(m_codecCtx->sample_fmt);
- m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate;
-
// get a decoder and open it
AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id);
if(!aCodec)
@@ -95,6 +88,13 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename)
if(avcodec_open(m_codecCtx, aCodec)<0)
AUD_THROW(AUD_ERROR_FFMPEG);
+
+ // XXX this prints file information to stdout:
+ //dump_format(m_formatCtx, 0, filename, 0);
+
+ m_specs.channels = (AUD_Channels) m_codecCtx->channels;
+ m_specs.format = FFMPEG_TO_AUD(m_codecCtx->sample_fmt);
+ m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate;
}
catch(AUD_Exception e)
{
@@ -103,8 +103,9 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename)
}
// last but not least if there hasn't been any error, create the buffers
- m_buffer = new AUD_Buffer(0); AUD_NEW("buffer")
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_pkgbuf = new AUD_Buffer(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1);
+ AUD_NEW("buffer")
}
AUD_FFMPEGReader::AUD_FFMPEGReader(unsigned char* buffer, int size)
@@ -112,6 +113,7 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(unsigned char* buffer, int size)
m_position = 0;
m_pkgbuf_left = 0;
m_byteiocontext = (ByteIOContext*)av_mallocz(sizeof(ByteIOContext));
+ AUD_NEW("byteiocontext")
if(init_put_byte(m_byteiocontext, buffer, size, 0,
NULL, NULL, NULL, NULL) != 0)
@@ -132,9 +134,6 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(unsigned char* buffer, int size)
if(av_find_stream_info(m_formatCtx)<0)
AUD_THROW(AUD_ERROR_FFMPEG);
- // XXX this prints stream information to stdout:
- //dump_format(m_formatCtx, 0, NULL, 0);
-
// find audio stream and codec
m_stream = -1;
@@ -150,10 +149,6 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(unsigned char* buffer, int size)
m_codecCtx = m_formatCtx->streams[m_stream]->codec;
- m_specs.channels = (AUD_Channels) m_codecCtx->channels;
- m_specs.format = FFMPEG_TO_AUD(m_codecCtx->sample_fmt);
- m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate;
-
// get a decoder and open it
AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id);
if(!aCodec)
@@ -161,17 +156,25 @@ AUD_FFMPEGReader::AUD_FFMPEGReader(unsigned char* buffer, int size)
if(avcodec_open(m_codecCtx, aCodec)<0)
AUD_THROW(AUD_ERROR_FFMPEG);
+
+ // XXX this prints stream information to stdout:
+ //dump_format(m_formatCtx, 0, NULL, 0);
+
+ m_specs.channels = (AUD_Channels) m_codecCtx->channels;
+ m_specs.format = FFMPEG_TO_AUD(m_codecCtx->sample_fmt);
+ m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate;
}
catch(AUD_Exception e)
{
av_close_input_stream(m_formatCtx);
- delete m_byteiocontext;
+ av_free(m_byteiocontext); AUD_DELETE("byteiocontext")
throw;
}
// last but not least if there hasn't been any error, create the buffers
- m_buffer = new AUD_Buffer(0); AUD_NEW("buffer")
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_pkgbuf = new AUD_Buffer(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1);
+ AUD_NEW("buffer")
}
AUD_FFMPEGReader::~AUD_FFMPEGReader()
@@ -181,13 +184,13 @@ AUD_FFMPEGReader::~AUD_FFMPEGReader()
if(m_byteiocontext)
{
av_close_input_stream(m_formatCtx);
- av_free(m_byteiocontext);
+ av_free(m_byteiocontext); AUD_DELETE("byteiocontext")
}
else
av_close_input_file(m_formatCtx);
delete m_buffer; AUD_DELETE("buffer")
- delete m_pkgbuf;
+ delete m_pkgbuf; AUD_DELETE("buffer")
}
bool AUD_FFMPEGReader::isSeekable()
@@ -240,6 +243,11 @@ AUD_ReaderType AUD_FFMPEGReader::getType()
return AUD_TYPE_STREAM;
}
+bool AUD_FFMPEGReader::notify(AUD_Message &message)
+{
+ return false;
+}
+
void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
{
// read packages and decode them
@@ -255,7 +263,7 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
// resize output buffer if necessary
if(m_buffer->getSize() < length*sample_size)
- m_buffer->resize(length*sample_size, false);
+ m_buffer->resize(length*sample_size);
buffer = m_buffer->getBuffer();
pkgbuf_pos = m_pkgbuf_left;
@@ -289,12 +297,16 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
{
// XXX printf("resizing\n");
m_pkgbuf->resize(pkgbuf_size +
- AVCODEC_MAX_AUDIO_FRAME_SIZE);
+ AVCODEC_MAX_AUDIO_FRAME_SIZE, true);
pkgbuf_size += AVCODEC_MAX_AUDIO_FRAME_SIZE;
}
// read samples from the packet
data_size = pkgbuf_size-pkgbuf_pos;
+ /*read_length = avcodec_decode_audio3(m_codecCtx,
+ (int16_t*)(m_pkgbuf->getBuffer()+pkgbuf_pos),
+ &data_size,
+ &packet);*/
read_length = avcodec_decode_audio2(m_codecCtx,
(int16_t*)(m_pkgbuf->getBuffer()+pkgbuf_pos),
&data_size,
@@ -328,6 +340,8 @@ void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
}
buffer = m_buffer->getBuffer();
- length -= left;
+
+ if(left > 0)
+ length -= left;
m_position += length;
}
diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h
index 8a3728878a6..f0654836670 100644
--- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h
+++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.h
@@ -38,10 +38,8 @@ extern "C" {
* \warning Seeking may not be accurate! Moreover the position is updated after
* a buffer reading call. So calling getPosition right after seek
* normally results in a wrong value.
- * \bug When tried playing back a wav file with S24 or FLOAT32 as sample format
- * ffmpeg always returned S16 as sample format, resulting in wrong
- * playback.
- * \bug Playback of an ogg file seems to result in a segfault on windows.
+ * \warning Playback of an ogg with some outdated ffmpeg versions results in a
+ * segfault on windows.
*/
class AUD_FFMPEGReader : public AUD_IReader
{
@@ -120,6 +118,7 @@ public:
virtual int getPosition();
virtual AUD_Specs getSpecs();
virtual AUD_ReaderType getType();
+ virtual bool notify(AUD_Message &message);
virtual void read(int & length, sample_t* & buffer);
};
diff --git a/intern/audaspace/intern/AUD_Buffer.cpp b/intern/audaspace/intern/AUD_Buffer.cpp
index ba868793bd9..71deae0e87e 100644
--- a/intern/audaspace/intern/AUD_Buffer.cpp
+++ b/intern/audaspace/intern/AUD_Buffer.cpp
@@ -34,15 +34,15 @@
AUD_Buffer::AUD_Buffer(int size)
{
m_size = size;
- m_buffer = (unsigned char*) malloc(size+15);
+ m_buffer = (sample_t*) malloc(size+16); AUD_NEW("buffer")
}
AUD_Buffer::~AUD_Buffer()
{
- free(m_buffer);
+ free(m_buffer); AUD_DELETE("buffer")
}
-unsigned char* AUD_Buffer::getBuffer()
+sample_t* AUD_Buffer::getBuffer()
{
return AUD_ALIGN(m_buffer);
}
@@ -54,13 +54,13 @@ int AUD_Buffer::getSize()
void AUD_Buffer::resize(int size, bool keep)
{
- unsigned char* buffer = (unsigned char*) malloc(size+15);
+ sample_t* buffer = (sample_t*) malloc(size+16); AUD_NEW("buffer")
// copy old data over if wanted
if(keep)
memcpy(AUD_ALIGN(buffer), AUD_ALIGN(m_buffer), AUD_MIN(size, m_size));
- free(m_buffer);
+ free(m_buffer); AUD_DELETE("buffer")
m_buffer = buffer;
m_size = size;
diff --git a/intern/audaspace/intern/AUD_Buffer.h b/intern/audaspace/intern/AUD_Buffer.h
index 1331db50884..64959b03799 100644
--- a/intern/audaspace/intern/AUD_Buffer.h
+++ b/intern/audaspace/intern/AUD_Buffer.h
@@ -26,6 +26,8 @@
#ifndef AUD_BUFFER
#define AUD_BUFFER
+#include "AUD_Space.h"
+
/**
* This class is a simple buffer in RAM which is 16 Byte aligned and provides
* resize functionality.
@@ -37,14 +39,14 @@ private:
int m_size;
/// The pointer to the buffer memory.
- unsigned char* m_buffer;
+ sample_t* m_buffer;
public:
/**
* Creates a new buffer.
* \param size The size of the buffer in bytes.
*/
- AUD_Buffer(int size);
+ AUD_Buffer(int size = 0);
/**
* Destroys the buffer.
@@ -54,7 +56,7 @@ public:
/**
* Returns the pointer to the buffer in memory.
*/
- unsigned char* getBuffer();
+ sample_t* getBuffer();
/**
* Returns the size of the buffer in bytes.
@@ -67,7 +69,7 @@ public:
* \param keep Whether to keep the old data. If the new buffer is smaller,
* the data at the end will be lost.
*/
- void resize(int size, bool keep = true);
+ void resize(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 e7ce6a9bbd5..1e828cfb0f1 100644
--- a/intern/audaspace/intern/AUD_BufferReader.cpp
+++ b/intern/audaspace/intern/AUD_BufferReader.cpp
@@ -52,7 +52,7 @@ void AUD_BufferReader::seek(int position)
int AUD_BufferReader::getLength()
{
- return m_buffer.get()->getSize()/AUD_SAMPLE_SIZE(m_specs)-m_position;
+ return m_buffer.get()->getSize()/AUD_SAMPLE_SIZE(m_specs);
}
int AUD_BufferReader::getPosition()
@@ -70,6 +70,11 @@ AUD_ReaderType AUD_BufferReader::getType()
return AUD_TYPE_BUFFER;
}
+bool AUD_BufferReader::notify(AUD_Message &message)
+{
+ return false;
+}
+
void AUD_BufferReader::read(int & length, sample_t* & buffer)
{
int sample_size = AUD_SAMPLE_SIZE(m_specs);
@@ -80,5 +85,7 @@ void AUD_BufferReader::read(int & length, sample_t* & buffer)
if(m_buffer.get()->getSize() < (m_position+length)*sample_size)
length = m_buffer.get()->getSize()/sample_size-m_position;
+ if(length < 0)
+ length = 0;
m_position += length;
}
diff --git a/intern/audaspace/intern/AUD_BufferReader.h b/intern/audaspace/intern/AUD_BufferReader.h
index 3a5cfb8efd5..f2d8ff6b57d 100644
--- a/intern/audaspace/intern/AUD_BufferReader.h
+++ b/intern/audaspace/intern/AUD_BufferReader.h
@@ -67,6 +67,7 @@ public:
virtual int getPosition();
virtual AUD_Specs getSpecs();
virtual AUD_ReaderType getType();
+ virtual bool notify(AUD_Message &message);
virtual void read(int & length, sample_t* & buffer);
};
diff --git a/intern/audaspace/intern/AUD_C-API.cpp b/intern/audaspace/intern/AUD_C-API.cpp
index 0c561a21e16..27a39ed6467 100644
--- a/intern/audaspace/intern/AUD_C-API.cpp
+++ b/intern/audaspace/intern/AUD_C-API.cpp
@@ -43,7 +43,11 @@ int AUD_init()
av_register_all();
try
{
- AUD_device = new AUD_SDLDevice();
+ AUD_Specs specs;
+ specs.channels = AUD_CHANNELS_STEREO;
+ specs.format = AUD_FORMAT_S16;
+ specs.rate = AUD_RATE_44100;
+ AUD_device = new AUD_SDLDevice(specs);
return true;
}
catch(AUD_Exception e)
@@ -76,16 +80,13 @@ void AUD_unload(AUD_Sound* sound)
delete sound;
}
-AUD_Handle* AUD_play(AUD_Sound* sound,
- AUD_EndBehaviour endBehaviour,
- double seekTo)
+AUD_Handle* AUD_play(AUD_Sound* sound, int keep)
{
assert(AUD_device);
assert(sound);
- int position = (int)(seekTo * AUD_device->getSpecs().rate);
try
{
- return AUD_device->play(sound, endBehaviour, position);
+ return AUD_device->play(sound, keep);
}
catch(AUD_Exception e)
{
@@ -111,11 +112,10 @@ int AUD_stop(AUD_Handle* handle)
return AUD_device->stop(handle);
}
-int AUD_setEndBehaviour(AUD_Handle* handle,
- AUD_EndBehaviour endBehaviour)
+int AUD_setKeep(AUD_Handle* handle, int keep)
{
assert(AUD_device);
- return AUD_device->setEndBehaviour(handle, endBehaviour);
+ return AUD_device->setKeep(handle, keep);
}
int AUD_seek(AUD_Handle* handle, double seekTo)
diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp
new file mode 100644
index 00000000000..66205a58015
--- /dev/null
+++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.cpp
@@ -0,0 +1,125 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_ChannelMapperFactory.h"
+#include "AUD_ChannelMapperReader.h"
+
+#include <cstring>
+
+AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IReader* reader,
+ AUD_Specs specs) :
+ AUD_MixerFactory(reader, specs)
+{
+ memset(m_mapping, 0, sizeof(m_mapping));
+}
+
+AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_IFactory* factory,
+ AUD_Specs specs) :
+ AUD_MixerFactory(factory, specs)
+{
+ memset(m_mapping, 0, sizeof(m_mapping));
+}
+
+AUD_ChannelMapperFactory::AUD_ChannelMapperFactory(AUD_Specs specs) :
+ AUD_MixerFactory(specs)
+{
+ memset(m_mapping, 0, sizeof(m_mapping));
+}
+
+AUD_ChannelMapperFactory::~AUD_ChannelMapperFactory()
+{
+ 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]; AUD_NEW("mapping")
+ m_mapping[ic][channels] = 0;
+
+ for(int i = 0; i < channels; i++)
+ {
+ m_mapping[ic][i] = new float[ic+1]; AUD_NEW("mapping")
+ 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]; AUD_DELETE("mapping")
+ }
+ else
+ break;
+ }
+ delete[] m_mapping[ic]; AUD_DELETE("mapping")
+ m_mapping[ic] = 0;
+ }
+}
+
+AUD_IReader* AUD_ChannelMapperFactory::createReader()
+{
+ AUD_IReader* reader = getReader();
+
+ if(reader != 0)
+ {
+ int ic = reader->getSpecs().channels;
+
+ reader = new AUD_ChannelMapperReader(reader, getMapping(ic));
+ AUD_NEW("reader")
+ }
+
+ return reader;
+}
diff --git a/intern/audaspace/intern/AUD_ChannelMapperFactory.h b/intern/audaspace/intern/AUD_ChannelMapperFactory.h
new file mode 100644
index 00000000000..c2c39f4bdf6
--- /dev/null
+++ b/intern/audaspace/intern/AUD_ChannelMapperFactory.h
@@ -0,0 +1,65 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_CHANNELMAPPERFACTORY
+#define AUD_CHANNELMAPPERFACTORY
+
+#include "AUD_MixerFactory.h"
+
+/**
+ * This factory creates a reader that maps a sound source's channels to a
+ * specific output channel count.
+ */
+class AUD_ChannelMapperFactory : public AUD_MixerFactory
+{
+private:
+ /**
+ * The mapping specification.
+ */
+ float **m_mapping[9];
+
+public:
+ AUD_ChannelMapperFactory(AUD_IReader* reader, AUD_Specs specs);
+ AUD_ChannelMapperFactory(AUD_IFactory* factory, AUD_Specs specs);
+ AUD_ChannelMapperFactory(AUD_Specs specs);
+
+ 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);
+
+ virtual AUD_IReader* createReader();
+};
+
+#endif //AUD_CHANNELMAPPERFACTORY
diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.cpp b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp
new file mode 100644
index 00000000000..61f97c08a8e
--- /dev/null
+++ b/intern/audaspace/intern/AUD_ChannelMapperReader.cpp
@@ -0,0 +1,108 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_ChannelMapperReader.h"
+#include "AUD_Buffer.h"
+
+AUD_ChannelMapperReader::AUD_ChannelMapperReader(AUD_IReader* reader,
+ float **mapping) :
+ AUD_EffectReader(reader)
+{
+ m_specs = reader->getSpecs();
+
+ if(m_specs.format != AUD_FORMAT_FLOAT32)
+ {
+ delete m_reader; AUD_DELETE("reader")
+ AUD_THROW(AUD_ERROR_READER);
+ }
+
+ int channels = -1;
+ m_rch = m_specs.channels;
+ while(mapping[++channels] != 0);
+
+ m_mapping = new float*[channels]; AUD_NEW("mapping")
+ m_specs.channels = (AUD_Channels)channels;
+
+ float sum;
+ int i;
+
+ while(channels--)
+ {
+ m_mapping[channels] = new float[m_rch]; AUD_NEW("mapping")
+ 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.0 ? mapping[channels][i]/sum : 0.0;
+ }
+
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+}
+
+AUD_ChannelMapperReader::~AUD_ChannelMapperReader()
+{
+ int channels = m_specs.channels;
+
+ while(channels--)
+ {
+ delete[] m_mapping[channels]; AUD_DELETE("mapping")
+ }
+
+ delete[] m_mapping; AUD_DELETE("mapping")
+
+ delete m_buffer; AUD_DELETE("buffer")
+}
+
+AUD_Specs AUD_ChannelMapperReader::getSpecs()
+{
+ return m_specs;
+}
+
+void AUD_ChannelMapperReader::read(int & length, sample_t* & buffer)
+{
+ m_reader->read(length, buffer);
+
+ int channels = m_specs.channels;
+
+ if(m_buffer->getSize() < length * 4 * channels)
+ m_buffer->resize(length * 4 * channels);
+
+ float* in = (float*)buffer;
+ float* out = (float*)m_buffer->getBuffer();
+ float sum;
+
+ for(int i = 0; i < length; i++)
+ {
+ for(int j = 0; j < channels; j++)
+ {
+ sum = 0;
+ for(int k = 0; k < m_rch; k++)
+ sum += m_mapping[j][k] * in[i * m_rch + k];
+ out[i * channels + j] = sum;
+ }
+ }
+
+ buffer = m_buffer->getBuffer();
+}
diff --git a/intern/audaspace/intern/AUD_ChannelMapperReader.h b/intern/audaspace/intern/AUD_ChannelMapperReader.h
new file mode 100644
index 00000000000..fe79ab6edd6
--- /dev/null
+++ b/intern/audaspace/intern/AUD_ChannelMapperReader.h
@@ -0,0 +1,76 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_CHANNELMAPPERREADER
+#define AUD_CHANNELMAPPERREADER
+
+#include "AUD_EffectReader.h"
+class AUD_Buffer;
+
+/**
+ * This class maps a sound source's channels to a specific output channel count.
+ * \note The input sample format must be float.
+ */
+class AUD_ChannelMapperReader : public AUD_EffectReader
+{
+private:
+ /**
+ * The sound output buffer.
+ */
+ AUD_Buffer *m_buffer;
+
+ /**
+ * The output specification.
+ */
+ AUD_Specs m_specs;
+
+ /**
+ * The channel count of the reader.
+ */
+ int m_rch;
+
+ /**
+ * The mapping specification.
+ */
+ float **m_mapping;
+
+public:
+ /**
+ * Creates a channel mapper reader.
+ * \param reader The reader to map.
+ * \param mapping The mapping specification as two dimensional float array.
+ * \exception AUD_Exception Thrown if the reader is NULL.
+ */
+ AUD_ChannelMapperReader(AUD_IReader* reader, float **mapping);
+ /**
+ * Destroys the reader.
+ */
+ ~AUD_ChannelMapperReader();
+
+ virtual AUD_Specs getSpecs();
+ virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_CHANNELMAPPERREADER
diff --git a/intern/audaspace/intern/AUD_ConverterFactory.cpp b/intern/audaspace/intern/AUD_ConverterFactory.cpp
new file mode 100644
index 00000000000..a1a86662072
--- /dev/null
+++ b/intern/audaspace/intern/AUD_ConverterFactory.cpp
@@ -0,0 +1,54 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_ConverterFactory.h"
+#include "AUD_ConverterReader.h"
+
+AUD_ConverterFactory::AUD_ConverterFactory(AUD_IReader* reader,
+ AUD_Specs specs) :
+ AUD_MixerFactory(reader, specs) {}
+
+AUD_ConverterFactory::AUD_ConverterFactory(AUD_IFactory* factory,
+ AUD_Specs specs) :
+ AUD_MixerFactory(factory, specs) {}
+
+AUD_ConverterFactory::AUD_ConverterFactory(AUD_Specs specs) :
+ AUD_MixerFactory(specs) {}
+
+AUD_IReader* AUD_ConverterFactory::createReader()
+{
+ AUD_IReader* reader = getReader();
+
+ if(reader != 0)
+ {
+ if(reader->getSpecs().format != m_specs.format)
+ {
+ reader = new AUD_ConverterReader(reader, m_specs);
+ AUD_NEW("reader")
+ }
+ }
+
+ return reader;
+}
diff --git a/intern/audaspace/SDL/AUD_SDLSuperposer.h b/intern/audaspace/intern/AUD_ConverterFactory.h
index 2381c0313ec..3778e8d8f03 100644
--- a/intern/audaspace/SDL/AUD_SDLSuperposer.h
+++ b/intern/audaspace/intern/AUD_ConverterFactory.h
@@ -23,25 +23,23 @@
* ***** END LGPL LICENSE BLOCK *****
*/
-#ifndef AUD_SDLSUPERPOSER
-#define AUD_SDLSUPERPOSER
+#ifndef AUD_CONVERTERFACTORY
+#define AUD_CONVERTERFACTORY
-#include "AUD_ISuperposer.h"
+#include "AUD_MixerFactory.h"
/**
- * This class is able to superpose two audiosignals with the help of SDL.
- * The specification of the audio signals has to be the same as the
- * specification of the device.
+ * This factory creates a converter reader that is able to convert from one
+ * audio format to another.
*/
-class AUD_SDLSuperposer : public AUD_ISuperposer
+class AUD_ConverterFactory : public AUD_MixerFactory
{
public:
- /**
- * Creates the superposer.
- */
- AUD_SDLSuperposer();
+ AUD_ConverterFactory(AUD_IReader* reader, AUD_Specs specs);
+ AUD_ConverterFactory(AUD_IFactory* factory, AUD_Specs specs);
+ AUD_ConverterFactory(AUD_Specs specs);
- virtual void superpose(sample_t* destination, sample_t* source, int length);
+ virtual AUD_IReader* createReader();
};
-#endif //AUD_SDLSUPERPOSER
+#endif //AUD_CONVERTERFACTORY
diff --git a/intern/audaspace/intern/AUD_ConverterFunctions.cpp b/intern/audaspace/intern/AUD_ConverterFunctions.cpp
new file mode 100644
index 00000000000..b6d5dffa1a2
--- /dev/null
+++ b/intern/audaspace/intern/AUD_ConverterFunctions.cpp
@@ -0,0 +1,502 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_ConverterFunctions.h"
+#include "AUD_Buffer.h"
+
+#define AUD_U8_0 0x80
+#define AUD_S16_MAX 0x7FFF
+#define AUD_S16_MIN 0x8000
+#define AUD_S16_FLT 32768.0
+#define AUD_S32_MAX 0x7FFFFFFF
+#define AUD_S32_MIN 0x80000000
+#define AUD_S32_FLT 2147483648.0
+#define AUD_FLT_MAX 1.0
+#define AUD_FLT_MIN -1.0
+
+void AUD_convert_u8_s16(sample_t* target, sample_t* source, int length)
+{
+ int16_t* t = (int16_t*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = (((int16_t)source[i]) - AUD_U8_0) << 8;
+}
+
+void AUD_convert_u8_s24_be(sample_t* target, sample_t* source, int length)
+{
+ for(int i = 0; i < length; i++)
+ {
+ target[i*3] = source[i] - AUD_U8_0;
+ target[i*3+1] = 0;
+ target[i*3+2] = 0;
+ }
+}
+
+void AUD_convert_u8_s24_le(sample_t* target, sample_t* source, int length)
+{
+ for(int i = 0; i < length; i++)
+ {
+ target[i*3+2] = source[i] - AUD_U8_0;
+ target[i*3+1] = 0;
+ target[i*3] = 0;
+ }
+}
+
+void AUD_convert_u8_s32(sample_t* target, sample_t* source, int length)
+{
+ int32_t* t = (int32_t*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = (((int32_t)source[i]) - AUD_U8_0) << 24;
+}
+
+void AUD_convert_u8_float(sample_t* target, sample_t* source, int length)
+{
+ float* t = (float*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((float)AUD_U8_0);
+}
+
+void AUD_convert_u8_double(sample_t* target, sample_t* source, int length)
+{
+ double* t = (double*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = (((int32_t)source[i]) - AUD_U8_0) / ((double)AUD_U8_0);
+}
+
+void AUD_convert_s16_u8(sample_t* target, sample_t* source, int length)
+{
+ int16_t* s = (int16_t*) source;
+ for(int i = 0; i < length; i++)
+ target[i] = (unsigned char)((s[i] >> 8) + AUD_U8_0);
+}
+
+void AUD_convert_s16_s24_be(sample_t* target, sample_t* source, int length)
+{
+ int16_t* s = (int16_t*) source;
+ for(int i = 0; i < length; i++)
+ {
+ target[i*3] = s[i] >> 8 & 0xFF;
+ target[i*3+1] = s[i] & 0xFF;
+ target[i*3+2] = 0;
+ }
+}
+
+void AUD_convert_s16_s24_le(sample_t* target, sample_t* source, int length)
+{
+ int16_t* s = (int16_t*) source;
+ for(int i = 0; i < length; i++)
+ {
+ target[i*3+2] = s[i] >> 8 & 0xFF;
+ target[i*3+1] = s[i] & 0xFF;
+ target[i*3] = 0;
+ }
+}
+
+void AUD_convert_s16_s32(sample_t* target, sample_t* source, int length)
+{
+ int16_t* s = (int16_t*) source;
+ int32_t* t = (int32_t*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = ((int32_t)s[i]) << 16;
+}
+
+void AUD_convert_s16_float(sample_t* target, sample_t* source, int length)
+{
+ int16_t* s = (int16_t*) source;
+ float* t = (float*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = s[i] / AUD_S16_FLT;
+}
+
+void AUD_convert_s16_double(sample_t* target, sample_t* source, int length)
+{
+ int16_t* s = (int16_t*) source;
+ double* t = (double*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = s[i] / AUD_S16_FLT;
+}
+
+void AUD_convert_s24_u8_be(sample_t* target, sample_t* source, int length)
+{
+ for(int i = 0; i < length; i++)
+ target[i] = source[i*3] ^ AUD_U8_0;
+}
+
+void AUD_convert_s24_u8_le(sample_t* target, sample_t* source, int length)
+{
+ for(int i = 0; i < length; i++)
+ target[i] = source[i*3+2] ^ AUD_U8_0;
+}
+
+void AUD_convert_s24_s16_be(sample_t* target, sample_t* source, int length)
+{
+ int16_t* t = (int16_t*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = source[i*3] << 8 | source[i*3+1];
+}
+
+void AUD_convert_s24_s16_le(sample_t* target, sample_t* source, int length)
+{
+ int16_t* t = (int16_t*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = source[i*3+2] << 8 | source[i*3+1];
+}
+
+void AUD_convert_s24_s24(sample_t* target, sample_t* source, int length)
+{
+ memcpy(target, source, length * 3);
+}
+
+void AUD_convert_s24_s32_be(sample_t* target, sample_t* source, int length)
+{
+ int32_t* t = (int32_t*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = source[i*3] << 24 | source[i*3+1] << 16 | source[i*3+2] << 8;
+}
+
+void AUD_convert_s24_s32_le(sample_t* target, sample_t* source, int length)
+{
+ int32_t* t = (int32_t*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = source[i*3+2] << 24 | source[i*3+1] << 16 | source[i*3] << 8;
+}
+
+void AUD_convert_s24_float_be(sample_t* target, sample_t* source, int length)
+{
+ float* t = (float*) target;
+ int32_t s;
+ for(int i = 0; i < length; i++)
+ {
+ s = source[i*3] << 24 | source[i*3+1] << 16 | source[i*3+2] << 8;
+ t[i] = s / AUD_S32_FLT;
+ }
+}
+
+void AUD_convert_s24_float_le(sample_t* target, sample_t* source, int length)
+{
+ float* t = (float*) target;
+ int32_t s;
+ for(int i = 0; i < length; i++)
+ {
+ s = source[i*3+2] << 24 | source[i*3+1] << 16 | source[i*3] << 8;
+ t[i] = s / AUD_S32_FLT;
+ }
+}
+
+void AUD_convert_s24_double_be(sample_t* target, sample_t* source, int length)
+{
+ double* t = (double*) target;
+ int32_t s;
+ for(int i = 0; i < length; i++)
+ {
+ s = source[i*3] << 24 | source[i*3+1] << 16 | source[i*3+2] << 8;
+ t[i] = s / AUD_S32_FLT;
+ }
+}
+
+void AUD_convert_s24_double_le(sample_t* target, sample_t* source, int length)
+{
+ double* t = (double*) target;
+ int32_t s;
+ for(int i = 0; i < length; i++)
+ {
+ s = source[i*3+2] << 24 | source[i*3+1] << 16 | source[i*3] << 8;
+ t[i] = s / AUD_S32_FLT;
+ }
+}
+
+void AUD_convert_s32_u8(sample_t* target, sample_t* source, int length)
+{
+ int16_t* s = (int16_t*) source;
+ for(int i = 0; i < length; i++)
+ target[i] = (unsigned char)((s[i] >> 24) + AUD_U8_0);
+}
+
+void AUD_convert_s32_s16(sample_t* target, sample_t* source, int length)
+{
+ int16_t* t = (int16_t*) target;
+ int32_t* s = (int32_t*) source;
+ for(int i = 0; i < length; i++)
+ t[i] = s[i] >> 16;
+}
+
+void AUD_convert_s32_s24_be(sample_t* target, sample_t* source, int length)
+{
+ int32_t* s = (int32_t*) source;
+ 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;
+ }
+}
+
+void AUD_convert_s32_s24_le(sample_t* target, sample_t* source, int length)
+{
+ int16_t* s = (int16_t*) source;
+ 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;
+ }
+}
+
+void AUD_convert_s32_float(sample_t* target, sample_t* source, int length)
+{
+ int32_t* s = (int32_t*) source;
+ float* t = (float*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = s[i] / AUD_S32_FLT;
+}
+
+void AUD_convert_s32_double(sample_t* target, sample_t* source, int length)
+{
+ int32_t* s = (int32_t*) source;
+ double* t = (double*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = s[i] / AUD_S32_FLT;
+}
+
+void AUD_convert_float_u8(sample_t* target, sample_t* source, int length)
+{
+ float* s = (float*) source;
+ float t;
+ for(int i = 0; i < length; i++)
+ {
+ t = s[i] + AUD_FLT_MAX;
+ if(t <= 0.0f)
+ target[i] = 0;
+ else if(t >= 2.0f)
+ target[i] = 255;
+ else
+ target[i] = (unsigned char)(t*127);
+ }
+}
+
+void AUD_convert_float_s16(sample_t* target, sample_t* source, int length)
+{
+ int16_t* t = (int16_t*) target;
+ float* s = (float*) source;
+ for(int i = 0; i < length; i++)
+ {
+ if(s[i] <= AUD_FLT_MIN)
+ t[i] = AUD_S16_MIN;
+ else if(s[i] >= AUD_FLT_MAX)
+ t[i] = AUD_S16_MAX;
+ else
+ t[i] = (int16_t)(s[i] * AUD_S16_MAX);
+ }
+}
+
+void AUD_convert_float_s24_be(sample_t* target, sample_t* source, int length)
+{
+ int32_t t;
+ float* s = (float*) source;
+ for(int i = 0; i < length; i++)
+ {
+ if(s[i] <= AUD_FLT_MIN)
+ t = AUD_S32_MIN;
+ else if(s[i] >= AUD_FLT_MAX)
+ t = AUD_S32_MAX;
+ else
+ t = (int32_t)(s[i]*AUD_S32_MAX);
+ target[i*3] = t >> 24 & 0xFF;
+ target[i*3+1] = t >> 16 & 0xFF;
+ target[i*3+2] = t >> 8 & 0xFF;
+ }
+}
+
+void AUD_convert_float_s24_le(sample_t* target, sample_t* source, int length)
+{
+ int32_t t;
+ float* s = (float*) source;
+ for(int i = 0; i < length; i++)
+ {
+ if(s[i] <= AUD_FLT_MIN)
+ t = AUD_S32_MIN;
+ else if(s[i] >= AUD_FLT_MAX)
+ t = AUD_S32_MAX;
+ else
+ t = (int32_t)(s[i]*AUD_S32_MAX);
+ target[i*3+2] = t >> 24 & 0xFF;
+ target[i*3+1] = t >> 16 & 0xFF;
+ target[i*3] = t >> 8 & 0xFF;
+ }
+}
+
+void AUD_convert_float_s32(sample_t* target, sample_t* source, int length)
+{
+ int32_t* t = (int32_t*) target;
+ float* s = (float*) source;
+ for(int i = 0; i < length; i++)
+ {
+ if(s[i] <= AUD_FLT_MIN)
+ t[i] = AUD_S32_MIN;
+ else if(s[i] >= AUD_FLT_MAX)
+ t[i] = AUD_S32_MAX;
+ else
+ t[i] = (int32_t)(s[i]*AUD_S32_MAX);
+ }
+}
+
+void AUD_convert_float_double(sample_t* target, sample_t* source, int length)
+{
+ float* s = (float*) source;
+ double* t = (double*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = s[i];
+}
+
+void AUD_convert_double_u8(sample_t* target, sample_t* source, int length)
+{
+ double* s = (double*) source;
+ double t;
+ for(int i = 0; i < length; i++)
+ {
+ t = s[i] + AUD_FLT_MAX;
+ if(t <= 0.0)
+ target[i] = 0;
+ else if(t >= 2.0)
+ target[i] = 255;
+ else
+ target[i] = (unsigned char)(t*127);
+ }
+}
+
+void AUD_convert_double_s16(sample_t* target, sample_t* source, int length)
+{
+ int16_t* t = (int16_t*) target;
+ double* s = (double*) source;
+ for(int i = 0; i < length; i++)
+ {
+ if(s[i] <= AUD_FLT_MIN)
+ t[i] = AUD_S16_MIN;
+ else if(s[i] >= AUD_FLT_MAX)
+ t[i] = AUD_S16_MAX;
+ else
+ t[i] = (int16_t)(s[i]*AUD_S16_MAX);
+ }
+}
+
+void AUD_convert_double_s24_be(sample_t* target, sample_t* source, int length)
+{
+ int32_t t;
+ double* s = (double*) source;
+ for(int i = 0; i < length; i++)
+ {
+ if(s[i] <= AUD_FLT_MIN)
+ t = AUD_S32_MIN;
+ else if(s[i] >= AUD_FLT_MAX)
+ t = AUD_S32_MAX;
+ else
+ t = (int32_t)(s[i]*AUD_S32_MAX);
+ target[i*3] = t >> 24 & 0xFF;
+ target[i*3+1] = t >> 16 & 0xFF;
+ target[i*3+2] = t >> 8 & 0xFF;
+ }
+}
+
+void AUD_convert_double_s24_le(sample_t* target, sample_t* source, int length)
+{
+ int32_t t;
+ double* s = (double*) source;
+ for(int i = 0; i < length; i++)
+ {
+ if(s[i] <= AUD_FLT_MIN)
+ t = AUD_S32_MIN;
+ else if(s[i] >= AUD_FLT_MAX)
+ t = AUD_S32_MAX;
+ else
+ t = (int32_t)(s[i]*AUD_S32_MAX);
+ target[i*3+2] = t >> 24 & 0xFF;
+ target[i*3+1] = t >> 16 & 0xFF;
+ target[i*3] = t >> 8 & 0xFF;
+ }
+}
+
+void AUD_convert_double_s32(sample_t* target, sample_t* source, int length)
+{
+ int32_t* t = (int32_t*) target;
+ double* s = (double*) source;
+ for(int i = 0; i < length; i++)
+ {
+ if(s[i] <= AUD_FLT_MIN)
+ t[i] = AUD_S32_MIN;
+ else if(s[i] >= AUD_FLT_MAX)
+ t[i] = AUD_S32_MAX;
+ else
+ t[i] = (int32_t)(s[i]*AUD_S32_MAX);
+ }
+}
+
+void AUD_convert_double_float(sample_t* target, sample_t* source, int length)
+{
+ double* s = (double*) source;
+ float* t = (float*) target;
+ for(int i = 0; i < length; i++)
+ t[i] = s[i];
+}
+
+void AUD_volume_adjust_u8(sample_t* target, sample_t* source,
+ int count, float volume)
+{
+ for(int i=0; i<count; i++)
+ target[i] = (unsigned char)((source[i]-0x0080) * volume + 0x80);
+}
+
+void AUD_volume_adjust_s24_le(sample_t* target, sample_t* source,
+ int count, float volume)
+{
+ count *= 3;
+ int value;
+
+ for(int i=0; i<count; i+=3)
+ {
+ value = source[i+2] << 16 | source[i+1] << 8 | source[i];
+ value |= (((value & 0x800000) >> 23) * 255) << 24;
+ value *= volume;
+ target[i+2] = value >> 16;
+ target[i+1] = value >> 8;
+ target[i] = value;
+ }
+}
+
+void AUD_volume_adjust_s24_be(sample_t* target, sample_t* source,
+ int count, float volume)
+{
+ count *= 3;
+ int value;
+
+ for(int i=0; i < count; i+=3)
+ {
+ value = source[i] << 16 | source[i+1] << 8 | source[i+2];
+ value |= (((value & 0x800000) >> 23) * 255) << 24;
+ value *= volume;
+ target[i] = value >> 16;
+ target[i+1] = value >> 8;
+ target[i+2] = value;
+ }
+}
+
diff --git a/intern/audaspace/intern/AUD_ConverterFunctions.h b/intern/audaspace/intern/AUD_ConverterFunctions.h
new file mode 100644
index 00000000000..c1dd0f4a3a2
--- /dev/null
+++ b/intern/audaspace/intern/AUD_ConverterFunctions.h
@@ -0,0 +1,156 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_CONVERTERFUNCTIONS
+#define AUD_CONVERTERFUNCTIONS
+
+#include "AUD_Space.h"
+
+#include <cstring>
+#ifdef _MSC_VER
+#if (_MSC_VER < 1300)
+ typedef short int16_t;
+ typedef int int32_t;
+#else
+ typedef __int16 int16_t;
+ typedef __int32 int32_t;
+#endif
+#else
+#include <stdint.h>
+#endif
+
+typedef void (*AUD_convert_f)(sample_t* target, sample_t* source, int length);
+
+typedef void (*AUD_volume_adjust_f)(sample_t* target, sample_t* source,
+ int count, float volume);
+
+template <class T>
+void AUD_convert_copy(sample_t* target, sample_t* source, int length)
+{
+ memcpy(target, source, length*sizeof(T));
+}
+
+void AUD_convert_u8_s16(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_u8_s24_be(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_u8_s24_le(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_u8_s32(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_u8_float(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_u8_double(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s16_u8(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s16_s24_be(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s16_s24_le(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s16_s32(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s16_float(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s16_double(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s24_u8_be(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s24_u8_le(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s24_s16_be(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s24_s16_le(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s24_s24(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s24_s32_be(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s24_s32_le(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s24_float_be(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s24_float_le(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s24_double_be(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s24_double_le(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s32_u8(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s32_s16(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s32_s24_be(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s32_s24_le(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s32_float(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_s32_double(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_float_u8(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_float_s16(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_float_s24_be(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_float_s24_le(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_float_s32(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_float_double(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_double_u8(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_double_s16(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_double_s24_be(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_double_s24_le(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_double_s32(sample_t* target, sample_t* source, int length);
+
+void AUD_convert_double_float(sample_t* target, sample_t* source, int length);
+
+template <class T>
+void AUD_volume_adjust(sample_t* target, sample_t* source,
+ int count, float volume)
+{
+ T* t = (T*)target;
+ T* s = (T*)source;
+ for(int i=0; i < count; i++)
+ t[i] = (T)(s[i] * volume);
+}
+
+void AUD_volume_adjust_u8(sample_t* target, sample_t* source,
+ int count, float volume);
+
+void AUD_volume_adjust_s24_le(sample_t* target, sample_t* source,
+ int count, float volume);
+
+void AUD_volume_adjust_s24_be(sample_t* target, sample_t* source,
+ int count, float volume);
+
+#endif //AUD_CONVERTERFUNCTIONS
diff --git a/intern/audaspace/intern/AUD_ConverterReader.cpp b/intern/audaspace/intern/AUD_ConverterReader.cpp
new file mode 100644
index 00000000000..2ff4925644c
--- /dev/null
+++ b/intern/audaspace/intern/AUD_ConverterReader.cpp
@@ -0,0 +1,244 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_ConverterReader.h"
+#include "AUD_Buffer.h"
+
+AUD_ConverterReader::AUD_ConverterReader(AUD_IReader* reader, AUD_Specs specs) :
+ AUD_EffectReader(reader)
+{
+ m_specs = reader->getSpecs();
+
+ int bigendian = 1;
+ bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
+
+ switch(m_specs.format)
+ {
+ case AUD_FORMAT_U8:
+ switch(specs.format)
+ {
+ case AUD_FORMAT_U8:
+ m_convert = AUD_convert_copy<unsigned char>;
+ break;
+ case AUD_FORMAT_S16:
+ m_convert = AUD_convert_u8_s16;
+ break;
+ case AUD_FORMAT_S24:
+ if(bigendian)
+ m_convert = AUD_convert_u8_s24_be;
+ else
+ m_convert = AUD_convert_u8_s24_le;
+ break;
+ case AUD_FORMAT_S32:
+ m_convert = AUD_convert_u8_s32;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ m_convert = AUD_convert_u8_float;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ m_convert = AUD_convert_u8_double;
+ break;
+ }
+ break;
+ case AUD_FORMAT_S16:
+ switch(specs.format)
+ {
+ case AUD_FORMAT_U8:
+ m_convert = AUD_convert_s16_u8;
+ break;
+ case AUD_FORMAT_S16:
+ m_convert = AUD_convert_copy<int16_t>;
+ break;
+ case AUD_FORMAT_S24:
+ if(bigendian)
+ m_convert = AUD_convert_s16_s24_be;
+ else
+ m_convert = AUD_convert_s16_s24_le;
+ break;
+ case AUD_FORMAT_S32:
+ m_convert = AUD_convert_s16_s32;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ m_convert = AUD_convert_s16_float;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ m_convert = AUD_convert_s16_double;
+ break;
+ }
+ break;
+ case AUD_FORMAT_S24:
+ if(bigendian)
+ switch(specs.format)
+ {
+ case AUD_FORMAT_U8:
+ m_convert = AUD_convert_u8_s24_be;
+ break;
+ case AUD_FORMAT_S16:
+ m_convert = AUD_convert_s16_s24_be;
+ break;
+ case AUD_FORMAT_S24:
+ m_convert = AUD_convert_s24_s24;
+ break;
+ case AUD_FORMAT_S32:
+ m_convert = AUD_convert_s32_s24_be;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ m_convert = AUD_convert_float_s24_be;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ m_convert = AUD_convert_double_s24_be;
+ break;
+ }
+ else
+ switch(specs.format)
+ {
+ case AUD_FORMAT_U8:
+ m_convert = AUD_convert_u8_s24_le;
+ break;
+ case AUD_FORMAT_S16:
+ m_convert = AUD_convert_s16_s24_le;
+ break;
+ case AUD_FORMAT_S24:
+ m_convert = AUD_convert_s24_s24;
+ break;
+ case AUD_FORMAT_S32:
+ m_convert = AUD_convert_s32_s24_le;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ m_convert = AUD_convert_float_s24_le;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ m_convert = AUD_convert_double_s24_le;
+ break;
+ }
+ break;
+ case AUD_FORMAT_S32:
+ switch(specs.format)
+ {
+ case AUD_FORMAT_U8:
+ m_convert = AUD_convert_s32_u8;
+ break;
+ case AUD_FORMAT_S16:
+ m_convert = AUD_convert_s32_s16;
+ break;
+ case AUD_FORMAT_S24:
+ if(bigendian)
+ m_convert = AUD_convert_s32_s24_be;
+ else
+ m_convert = AUD_convert_s32_s24_le;
+ break;
+ case AUD_FORMAT_S32:
+ m_convert = AUD_convert_copy<int32_t>;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ m_convert = AUD_convert_s32_float;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ m_convert = AUD_convert_s32_double;
+ break;
+ }
+ break;
+ case AUD_FORMAT_FLOAT32:
+ switch(specs.format)
+ {
+ case AUD_FORMAT_U8:
+ m_convert = AUD_convert_float_u8;
+ break;
+ case AUD_FORMAT_S16:
+ m_convert = AUD_convert_float_s16;
+ break;
+ case AUD_FORMAT_S24:
+ if(bigendian)
+ m_convert = AUD_convert_float_s24_be;
+ else
+ m_convert = AUD_convert_float_s24_le;
+ break;
+ case AUD_FORMAT_S32:
+ m_convert = AUD_convert_float_s32;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ m_convert = AUD_convert_copy<float>;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ m_convert = AUD_convert_float_double;
+ break;
+ }
+ break;
+ case AUD_FORMAT_FLOAT64:
+ switch(specs.format)
+ {
+ case AUD_FORMAT_U8:
+ m_convert = AUD_convert_double_u8;
+ break;
+ case AUD_FORMAT_S16:
+ m_convert = AUD_convert_double_s16;
+ break;
+ case AUD_FORMAT_S24:
+ if(bigendian)
+ m_convert = AUD_convert_double_s24_be;
+ else
+ m_convert = AUD_convert_double_s24_le;
+ break;
+ case AUD_FORMAT_S32:
+ m_convert = AUD_convert_double_s32;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ m_convert = AUD_convert_double_float;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ m_convert = AUD_convert_copy<double>;
+ break;
+ }
+ break;
+ }
+
+ m_specs.format = specs.format;
+
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+}
+
+AUD_ConverterReader::~AUD_ConverterReader()
+{
+ delete m_buffer; AUD_DELETE("buffer")
+}
+
+AUD_Specs AUD_ConverterReader::getSpecs()
+{
+ return m_specs;
+}
+
+void AUD_ConverterReader::read(int & length, sample_t* & buffer)
+{
+ m_reader->read(length, buffer);
+
+ int samplesize = AUD_SAMPLE_SIZE(m_specs);
+
+ if(m_buffer->getSize() < length*samplesize)
+ m_buffer->resize(length*samplesize);
+
+ m_convert(m_buffer->getBuffer(), buffer, length*m_specs.channels);
+
+ buffer = m_buffer->getBuffer();
+}
diff --git a/intern/audaspace/intern/AUD_ConverterReader.h b/intern/audaspace/intern/AUD_ConverterReader.h
new file mode 100644
index 00000000000..f855372b636
--- /dev/null
+++ b/intern/audaspace/intern/AUD_ConverterReader.h
@@ -0,0 +1,71 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_CONVERTERREADER
+#define AUD_CONVERTERREADER
+
+#include "AUD_EffectReader.h"
+#include "AUD_ConverterFunctions.h"
+class AUD_Buffer;
+
+/**
+ * This class converts a sound source from one to another format.
+ */
+class AUD_ConverterReader : public AUD_EffectReader
+{
+private:
+ /**
+ * The sound output buffer.
+ */
+ AUD_Buffer *m_buffer;
+
+ /**
+ * The target specification.
+ */
+ AUD_Specs m_specs;
+
+ /**
+ * Converter function.
+ */
+ AUD_convert_f m_convert;
+
+public:
+ /**
+ * Creates a converter reader.
+ * \param reader The reader to convert.
+ * \param specs The target specification.
+ * \exception AUD_Exception Thrown if the reader is NULL.
+ */
+ AUD_ConverterReader(AUD_IReader* reader, AUD_Specs specs);
+ /**
+ * Destroys the reader.
+ */
+ ~AUD_ConverterReader();
+
+ virtual AUD_Specs getSpecs();
+ virtual void read(int & length, sample_t* & buffer);
+};
+
+#endif //AUD_CONVERTERREADER
diff --git a/intern/audaspace/intern/AUD_FloatMixer.cpp b/intern/audaspace/intern/AUD_FloatMixer.cpp
new file mode 100644
index 00000000000..1678c169845
--- /dev/null
+++ b/intern/audaspace/intern/AUD_FloatMixer.cpp
@@ -0,0 +1,170 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_FloatMixer.h"
+#include "AUD_ConverterFactory.h"
+#include "AUD_SRCResampleFactory.h"
+#include "AUD_ChannelMapperFactory.h"
+#include "AUD_IReader.h"
+#include "AUD_Buffer.h"
+
+#include <cstring>
+
+AUD_FloatMixer::AUD_FloatMixer()
+{
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
+
+ m_converter = NULL;
+ m_resampler = NULL;
+ m_mapper = NULL;
+}
+
+AUD_FloatMixer::~AUD_FloatMixer()
+{
+ delete m_buffer; AUD_DELETE("buffer")
+
+ if(m_converter)
+ {
+ delete m_converter; AUD_DELETE("factory")
+ }
+ if(m_resampler)
+ {
+ delete m_resampler; AUD_DELETE("factory")
+ }
+ if(m_mapper)
+ {
+ delete m_mapper; AUD_DELETE("factory")
+ }
+}
+
+AUD_IReader* AUD_FloatMixer::prepare(AUD_IReader* reader)
+{
+ m_converter->setReader(reader);
+ reader = m_converter->createReader();
+
+ m_resampler->setReader(reader);
+ reader = m_resampler->createReader();
+
+ if(reader->getSpecs().channels != m_specs.channels)
+ {
+ m_mapper->setReader(reader);
+ reader = m_mapper->createReader();
+ }
+
+ return reader;
+}
+
+void AUD_FloatMixer::setSpecs(AUD_Specs specs)
+{
+ m_specs = specs;
+
+ if(m_converter)
+ {
+ delete m_converter; AUD_DELETE("factory")
+ }
+ if(m_resampler)
+ {
+ delete m_resampler; AUD_DELETE("factory")
+ }
+ if(m_mapper)
+ {
+ delete m_mapper; AUD_DELETE("factory")
+ }
+
+ specs.format = AUD_FORMAT_FLOAT32;
+
+ m_converter = new AUD_ConverterFactory(specs); AUD_NEW("factory")
+ m_resampler = new AUD_SRCResampleFactory(specs); AUD_NEW("factory")
+ m_mapper = new AUD_ChannelMapperFactory(specs); AUD_NEW("factory")
+
+ int bigendian = 1;
+ bigendian = (((char*)&bigendian)[0]) ? 0: 1; // 1 if Big Endian
+
+ switch(m_specs.format)
+ {
+ case AUD_FORMAT_U8:
+ m_convert = AUD_convert_float_u8;
+ break;
+ case AUD_FORMAT_S16:
+ m_convert = AUD_convert_float_s16;
+ break;
+ case AUD_FORMAT_S24:
+ if(bigendian)
+ m_convert = AUD_convert_float_s24_be;
+ else
+ m_convert = AUD_convert_float_s24_le;
+ break;
+ case AUD_FORMAT_S32:
+ m_convert = AUD_convert_float_s32;
+ break;
+ case AUD_FORMAT_FLOAT32:
+ m_convert = AUD_convert_copy<float>;
+ break;
+ case AUD_FORMAT_FLOAT64:
+ m_convert = AUD_convert_float_double;
+ break;
+ }
+}
+
+void AUD_FloatMixer::add(sample_t* buffer, AUD_Specs specs, int length,
+ float volume)
+{
+ AUD_FloatMixerBuffer buf;
+ buf.buffer = buffer;
+ buf.length = length;
+ buf.volume = volume;
+ m_buffers.push_back(buf);
+}
+
+void AUD_FloatMixer::superpose(sample_t* buffer, int length, float volume)
+{
+ AUD_FloatMixerBuffer buf;
+
+ int channels = m_specs.channels;
+
+ if(m_buffer->getSize() < length * channels * 4)
+ m_buffer->resize(length * channels * 4);
+
+ float* out = (float*)m_buffer->getBuffer();
+ float* in;
+
+ memset(out, 0, length * channels * 4);
+
+ int end;
+
+ while(!m_buffers.empty())
+ {
+ buf = m_buffers.front();
+ m_buffers.pop_front();
+
+ end = buf.length*channels;
+ in = (float*) buf.buffer;
+
+ for(int i = 0; i < end; i++)
+ out[i] += in[i]*buf.volume * volume;
+ }
+
+ m_convert(buffer, (sample_t*) out, length * channels);
+}
diff --git a/intern/audaspace/intern/AUD_FloatMixer.h b/intern/audaspace/intern/AUD_FloatMixer.h
new file mode 100644
index 00000000000..728a0faf3cb
--- /dev/null
+++ b/intern/audaspace/intern/AUD_FloatMixer.h
@@ -0,0 +1,100 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_FLOATMIXER
+#define AUD_FLOATMIXER
+
+#include "AUD_IMixer.h"
+#include "AUD_ConverterFunctions.h"
+class AUD_ConverterFactory;
+class AUD_SRCResampleFactory;
+class AUD_ChannelMapperFactory;
+class AUD_Buffer;
+#include <list>
+
+struct AUD_FloatMixerBuffer
+{
+ sample_t* buffer;
+ int length;
+ float volume;
+};
+
+/**
+ * This class is able to mix two audiosignals with floats.
+ */
+class AUD_FloatMixer : public AUD_IMixer
+{
+private:
+ /**
+ * The converter factory that converts all readers for superposition.
+ */
+ AUD_ConverterFactory* m_converter;
+
+ /**
+ * The resampling factory that resamples all readers for superposition.
+ */
+ AUD_SRCResampleFactory* m_resampler;
+
+ /**
+ * The channel mapper factory that maps all readers for superposition.
+ */
+ AUD_ChannelMapperFactory* m_mapper;
+
+ /**
+ * The list of buffers to superpose.
+ */
+ std::list<AUD_FloatMixerBuffer> m_buffers;
+
+ /**
+ * The output specification.
+ */
+ AUD_Specs m_specs;
+
+ /**
+ * The temporary mixing buffer.
+ */
+ AUD_Buffer* m_buffer;
+
+ /**
+ * Converter function.
+ */
+ AUD_convert_f m_convert;
+
+public:
+ /**
+ * Creates the mixer.
+ */
+ AUD_FloatMixer();
+
+ virtual ~AUD_FloatMixer();
+
+ virtual AUD_IReader* prepare(AUD_IReader* reader);
+ virtual void setSpecs(AUD_Specs specs);
+ virtual void add(sample_t* buffer, AUD_Specs specs, int length,
+ float volume);
+ virtual void superpose(sample_t* buffer, int length, float volume);
+};
+
+#endif //AUD_FLOATMIXER
diff --git a/intern/audaspace/intern/AUD_I3DDevice.h b/intern/audaspace/intern/AUD_I3DDevice.h
new file mode 100644
index 00000000000..2cf35344957
--- /dev/null
+++ b/intern/audaspace/intern/AUD_I3DDevice.h
@@ -0,0 +1,150 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_I3DDEVICE
+#define AUD_I3DDEVICE
+
+#include "AUD_Space.h"
+
+/// 3D device settings.
+typedef enum
+{
+ AUD_3DS_NONE, /// No setting.
+ AUD_3DS_SPEED_OF_SOUND, /// Speed of sound.
+ AUD_3DS_DOPPLER_FACTOR, /// Doppler factor.
+ AUD_3DS_DISTANCE_MODEL /// Distance model.
+} AUD_3DSetting;
+
+/// Possible distance models for the 3D device.
+#define AUD_DISTANCE_MODEL_NONE 0.0f
+#define AUD_DISTANCE_MODEL_INVERSE 1.0f
+#define AUD_DISTANCE_MODEL_INVERSE_CLAMPED 2.0f
+#define AUD_DISTANCE_MODEL_LINEAR 3.0f
+#define AUD_DISTANCE_MODEL_LINEAR_CLAMPED 4.0f
+#define AUD_DISTANCE_MODEL_EXPONENT 5.0f
+#define AUD_DISTANCE_MODEL_EXPONENT_CLAMPED 6.0f
+
+/// 3D source settings.
+typedef enum
+{
+ AUD_3DSS_NONE, /// No setting.
+ AUD_3DSS_IS_RELATIVE, /// > 0 tells that the sound source is
+ /// relative to the listener
+ AUD_3DSS_MIN_GAIN, /// Minimum gain.
+ AUD_3DSS_MAX_GAIN, /// Maximum gain.
+ AUD_3DSS_REFERENCE_DISTANCE, /// Reference distance.
+ AUD_3DSS_MAX_DISTANCE, /// Maximum distance.
+ AUD_3DSS_ROLLOFF_FACTOR, /// Rolloff factor.
+ AUD_3DSS_CONE_INNER_ANGLE, /// Cone inner angle.
+ AUD_3DSS_CONE_OUTER_ANGLE, /// Cone outer angle.
+ AUD_3DSS_CONE_OUTER_GAIN /// Cone outer gain.
+} AUD_3DSourceSetting;
+
+/// Handle structure, for inherition.
+typedef struct
+{
+ /// x, y and z coordinates of the object.
+ float position[3];
+
+ /// x, y and z coordinates telling the velocity and direction of the object.
+ float velocity[3];
+
+ /// 3x3 matrix telling the orientation of the object.
+ float orientation[3][3];
+} AUD_3DData;
+
+/**
+ * This class represents an output device for 3D sound.
+ * Whether a normal device supports this or not can be checked with the
+ * AUD_CAPS_3D_DEVICE capability.
+ */
+class AUD_I3DDevice
+{
+public:
+ /**
+ * Plays a 3D sound source.
+ * \param factory The factory to create the reader for the sound source.
+ * \param keep When keep is true the sound source will not be deleted but
+ * set to paused when its end has been reached.
+ * \return Returns a handle with which the playback can be controlled.
+ * This is NULL if the sound couldn't be played back.
+ * \exception AUD_Exception Thrown if there's an unexpected (from the
+ * device side) error during creation of the reader.
+ * \note The factory must provide a mono (single channel) source otherwise
+ * the sound is played back normally.
+ */
+ virtual AUD_Handle* play3D(AUD_IFactory* factory, bool keep = false)=0;
+
+ /**
+ * Updates a listeners 3D data.
+ * \param data The 3D data.
+ * \return Whether the action succeeded.
+ */
+ virtual bool updateListener(AUD_3DData &data)=0;
+
+ /**
+ * Sets a 3D device setting.
+ * \param setting The setting type.
+ * \param value The new setting value.
+ * \return Whether the action succeeded.
+ */
+ virtual bool setSetting(AUD_3DSetting setting, float value)=0;
+
+ /**
+ * Retrieves a 3D device setting.
+ * \param setting The setting type.
+ * \return The setting value.
+ */
+ virtual float getSetting(AUD_3DSetting setting)=0;
+
+ /**
+ * Updates a listeners 3D data.
+ * \param handle The source handle.
+ * \param data The 3D data.
+ * \return Whether the action succeeded.
+ */
+ virtual bool updateSource(AUD_Handle* handle, AUD_3DData &data)=0;
+
+ /**
+ * Sets a 3D source setting.
+ * \param handle The source handle.
+ * \param setting The setting type.
+ * \param value The new setting value.
+ * \return Whether the action succeeded.
+ */
+ virtual bool setSourceSetting(AUD_Handle* handle,
+ AUD_3DSourceSetting setting, float value)=0;
+
+ /**
+ * Retrieves a 3D source setting.
+ * \param handle The source handle.
+ * \param setting The setting type.
+ * \return The setting value.
+ */
+ virtual float getSourceSetting(AUD_Handle* handle,
+ AUD_3DSourceSetting setting)=0;
+};
+
+#endif //AUD_I3DDEVICE
diff --git a/intern/audaspace/intern/AUD_IDevice.h b/intern/audaspace/intern/AUD_IDevice.h
index 37ab4770b8a..3200169e41c 100644
--- a/intern/audaspace/intern/AUD_IDevice.h
+++ b/intern/audaspace/intern/AUD_IDevice.h
@@ -46,6 +46,11 @@ class AUD_IDevice
{
public:
/**
+ * Destroys the device.
+ */
+ virtual ~AUD_IDevice() {}
+
+ /**
* Returns the specification of the device.
*/
virtual AUD_Specs getSpecs()=0;
@@ -53,17 +58,14 @@ public:
/**
* Plays a sound source.
* \param factory The factory to create the reader for the sound source.
- * \param endBehaviour The behaviour of the device when the sound source
- * doesn't return any more data.
- * \param seekTo A seek value for the start of the playback.
+ * \param keep When keep is true the sound source will not be deleted but
+ * set to paused when its end has been reached.
* \return Returns a handle with which the playback can be controlled.
* This is NULL if the sound couldn't be played back.
* \exception AUD_Exception Thrown if there's an unexpected (from the
* device side) error during creation of the reader.
*/
- virtual AUD_Handle* play(AUD_IFactory* factory,
- AUD_EndBehaviour endBehaviour = AUD_BEHAVIOUR_STOP,
- int seekTo = 0)=0;
+ virtual AUD_Handle* play(AUD_IFactory* factory, bool keep = false)=0;
/**
* Pauses a played back sound.
@@ -96,29 +98,33 @@ public:
* 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 endBehaviour The new behaviour.
+ * \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.
- * \see AUD_EndBehaviour
*/
- virtual bool setEndBehaviour(AUD_Handle* handle,
- AUD_EndBehaviour endBehaviour)=0;
+ virtual bool setKeep(AUD_Handle* handle, bool keep)=0;
+
+ /**
+ * Sends a message to a sound or all sounds that are currently played or
+ * paused.
+ * \param handle The sound that should receive the message or NULL if all
+ * sounds should receive it.
+ * \param message The message.
+ * \return True if the message has been read by at least one sound.
+ */
+ virtual bool sendMessage(AUD_Handle* handle, AUD_Message &message)=0;
/**
* Seeks in a played back sound.
* \param handle The handle returned by the play function.
- * \param position The new position from where to play back, measured in
- * samples. To get this value simply multiply the desired time in
- * seconds with the sample rate of the device.
- * A negative value indicates that the playback should be started
- * from the start after -position samples.
+ * \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, int position)=0;
+ virtual bool seek(AUD_Handle* handle, float position)=0;
/**
* Returns the status of a played back sound.
@@ -146,6 +152,31 @@ public:
* Unlocks the previously locked device.
*/
virtual void unlock()=0;
+
+ /**
+ * Checks if a specific capability as available on a device.
+ * \param capability The capability.
+ * \return Whether it is available or not.
+ */
+ virtual bool checkCapability(int capability)=0;
+
+ /**
+ * Set a value of a capability. The data behind the pointer depends on the
+ * capability.
+ * \param capability The capability.
+ * \param value The value.
+ * \return Whether the action succeeded or not.
+ */
+ virtual bool setCapability(int capability, void *value)=0;
+
+ /**
+ * Retrieves a value of a capability. The data behind the pointer depends on
+ * the capability.
+ * \param capability The capability.
+ * \param value The value.
+ * \return Whether the action succeeded or not.
+ */
+ virtual bool getCapability(int capability, void *value)=0;
};
#endif //AUD_IDevice
diff --git a/intern/audaspace/intern/AUD_IMixer.h b/intern/audaspace/intern/AUD_IMixer.h
new file mode 100644
index 00000000000..c65e4c69cf7
--- /dev/null
+++ b/intern/audaspace/intern/AUD_IMixer.h
@@ -0,0 +1,77 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_IMIXER
+#define AUD_IMIXER
+
+#include "AUD_Space.h"
+class AUD_IReader;
+
+/**
+ * This class is able to mix audiosignals of different format and channel count.
+ * \note This class doesn't do resampling!
+ */
+class AUD_IMixer
+{
+public:
+ /**
+ * Destroys the mixer.
+ */
+ virtual ~AUD_IMixer(){}
+
+ /**
+ * This funuction prepares a reader for playback.
+ * \param reader The reader to prepare.
+ * \return The reader that should be used for playback.
+ */
+ virtual AUD_IReader* prepare(AUD_IReader* reader)=0;
+
+ /**
+ * Sets the target specification for superposing.
+ * \param specs The target specification.
+ */
+ virtual void setSpecs(AUD_Specs specs)=0;
+
+ /**
+ * Adds a buffer for superposition.
+ * \param buffer The buffer to superpose.
+ * \param specs The specification of the buffer.
+ * \param start The start sample of the buffer.
+ * \param length The length of the buffer in samples.
+ * \param volume The mixing volume. Must be a value between 0.0 and 1.0.
+ */
+ virtual void add(sample_t* buffer, AUD_Specs specs, int length,
+ float volume)=0;
+
+ /**
+ * Superposes all added buffers 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(sample_t* buffer, int length, float volume)=0;
+};
+
+#endif //AUD_IMIXER
diff --git a/intern/audaspace/intern/AUD_IReader.h b/intern/audaspace/intern/AUD_IReader.h
index df15c3e583e..4b563100659 100644
--- a/intern/audaspace/intern/AUD_IReader.h
+++ b/intern/audaspace/intern/AUD_IReader.h
@@ -60,10 +60,9 @@ public:
virtual void seek(int position)=0;
/**
- * Returns an aproximated remaining length of the source in samples.
- * For readers of the type buffer this has to return a correct
- * value!
- * \return The remaining length as sample count. May be negative if unknown.
+ * Returns an aproximated length of the source in samples.
+ * For readers of the type buffer this has to return a correct value!
+ * \return The length as sample count. May be negative if unknown.
* \see getType
*/
virtual int getLength()=0;
@@ -94,6 +93,15 @@ public:
virtual AUD_ReaderType getType()=0;
/**
+ * Sends a message to this reader and if it has subreaders it broadcasts
+ * the message to them.
+ * \param message The message.
+ * \return Whether the message has been read by the reader or one of his
+ * subreaders.
+ */
+ virtual bool notify(AUD_Message &message)=0;
+
+ /**
* 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.
diff --git a/intern/audaspace/intern/AUD_MixerFactory.cpp b/intern/audaspace/intern/AUD_MixerFactory.cpp
index 5c41caf2ba8..db38d1004db 100644
--- a/intern/audaspace/intern/AUD_MixerFactory.cpp
+++ b/intern/audaspace/intern/AUD_MixerFactory.cpp
@@ -74,7 +74,9 @@ AUD_MixerFactory::AUD_MixerFactory(AUD_Specs specs)
AUD_MixerFactory::~AUD_MixerFactory()
{
if(m_reader != 0)
- delete m_reader;
+ {
+ delete m_reader; AUD_DELETE("reader")
+ }
}
AUD_Specs AUD_MixerFactory::getSpecs()
@@ -90,7 +92,9 @@ void AUD_MixerFactory::setSpecs(AUD_Specs specs)
void AUD_MixerFactory::setReader(AUD_IReader* reader)
{
if(m_reader != 0)
- delete m_reader;
+ {
+ delete m_reader; AUD_DELETE("reader")
+ }
m_reader = reader;
}
diff --git a/intern/audaspace/intern/AUD_MixerFactory.h b/intern/audaspace/intern/AUD_MixerFactory.h
index 14b4561b8df..c61dd283c67 100644
--- a/intern/audaspace/intern/AUD_MixerFactory.h
+++ b/intern/audaspace/intern/AUD_MixerFactory.h
@@ -29,7 +29,7 @@
#include "AUD_IFactory.h"
/**
- * This factory creates a resampling reader.
+ * This factory is a base class for all mixer factories.
*/
class AUD_MixerFactory : public AUD_IFactory
{
diff --git a/intern/audaspace/intern/AUD_NULLDevice.cpp b/intern/audaspace/intern/AUD_NULLDevice.cpp
new file mode 100644
index 00000000000..20bde0164ce
--- /dev/null
+++ b/intern/audaspace/intern/AUD_NULLDevice.cpp
@@ -0,0 +1,103 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_NULLDevice.h"
+#include "AUD_IReader.h"
+#include "AUD_IFactory.h"
+
+AUD_NULLDevice::AUD_NULLDevice()
+{
+ m_specs.channels = AUD_CHANNELS_INVALID;
+ m_specs.format = AUD_FORMAT_INVALID;
+ m_specs.rate = AUD_RATE_INVALID;
+}
+
+AUD_Specs AUD_NULLDevice::getSpecs()
+{
+ return m_specs;
+}
+
+AUD_Handle* AUD_NULLDevice::play(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::setKeep(AUD_Handle* handle, bool keep)
+{
+ return false;
+}
+
+bool AUD_NULLDevice::sendMessage(AUD_Handle* handle, AUD_Message &message)
+{
+ return false;
+}
+
+bool AUD_NULLDevice::seek(AUD_Handle* handle, float position)
+{
+ return false;
+}
+
+AUD_Status AUD_NULLDevice::getStatus(AUD_Handle* handle)
+{
+ return AUD_STATUS_INVALID;
+}
+
+void AUD_NULLDevice::lock()
+{
+}
+
+void AUD_NULLDevice::unlock()
+{
+}
+
+bool AUD_NULLDevice::checkCapability(int capability)
+{
+ return false;
+}
+
+bool AUD_NULLDevice::setCapability(int capability, void *value)
+{
+ return false;
+}
+
+bool AUD_NULLDevice::getCapability(int capability, void *value)
+{
+ return false;
+}
diff --git a/intern/audaspace/intern/AUD_NULLDevice.h b/intern/audaspace/intern/AUD_NULLDevice.h
new file mode 100644
index 00000000000..c0cf7ed4e51
--- /dev/null
+++ b/intern/audaspace/intern/AUD_NULLDevice.h
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_NULLDEVICE
+#define AUD_NULLDEVICE
+
+#include "AUD_IDevice.h"
+
+/**
+ * This device plays nothing.
+ */
+class AUD_NULLDevice : public AUD_IDevice
+{
+private:
+ /**
+ * The specs of the device.
+ */
+ AUD_Specs m_specs;
+
+public:
+ /**
+ * Creates a new NULL device.
+ */
+ AUD_NULLDevice();
+
+ virtual AUD_Specs getSpecs();
+ 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 setKeep(AUD_Handle* handle, bool keep);
+ virtual bool sendMessage(AUD_Handle* handle, AUD_Message &message);
+ virtual bool seek(AUD_Handle* handle, float position);
+ virtual AUD_Status getStatus(AUD_Handle* handle);
+ virtual void lock();
+ virtual void unlock();
+ virtual bool checkCapability(int capability);
+ virtual bool setCapability(int capability, void *value);
+ virtual bool getCapability(int capability, void *value);
+};
+
+#endif //AUD_NULLDEVICE
diff --git a/intern/audaspace/intern/AUD_ReadDevice.cpp b/intern/audaspace/intern/AUD_ReadDevice.cpp
new file mode 100644
index 00000000000..e2c1d2fac81
--- /dev/null
+++ b/intern/audaspace/intern/AUD_ReadDevice.cpp
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#include "AUD_FloatMixer.h"
+#include "AUD_ReadDevice.h"
+#include "AUD_IReader.h"
+
+#include <cstring>
+
+AUD_ReadDevice::AUD_ReadDevice(AUD_Specs specs)
+{
+ m_specs = specs;
+
+ m_mixer = new AUD_FloatMixer(); AUD_NEW("mixer")
+ m_mixer->setSpecs(m_specs);
+
+ m_playing = false;
+
+ create();
+}
+
+AUD_ReadDevice::~AUD_ReadDevice()
+{
+ destroy();
+}
+
+bool AUD_ReadDevice::read(sample_t* buffer, int length)
+{
+ if(m_playing)
+ mix(buffer, length);
+ else
+ if(m_specs.format == AUD_FORMAT_U8)
+ memset(buffer, 0x80, length * AUD_SAMPLE_SIZE(m_specs));
+ else
+ memset(buffer, 0, length * AUD_SAMPLE_SIZE(m_specs));
+ return m_playing;
+}
+
+void AUD_ReadDevice::playing(bool playing)
+{
+ m_playing = playing;
+}
diff --git a/intern/audaspace/intern/AUD_ReadDevice.h b/intern/audaspace/intern/AUD_ReadDevice.h
new file mode 100644
index 00000000000..d69b0c31ea5
--- /dev/null
+++ b/intern/audaspace/intern/AUD_ReadDevice.h
@@ -0,0 +1,68 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_READDEVICE
+#define AUD_READDEVICE
+
+#include "AUD_SoftwareDevice.h"
+
+/**
+ * This device enables to let the user read raw data out of it.
+ */
+class AUD_ReadDevice : public AUD_SoftwareDevice
+{
+protected:
+ virtual void playing(bool playing);
+
+private:
+ /**
+ * Whether the device currently.
+ */
+ bool m_playing;
+
+public:
+ /**
+ * Creates a new read device.
+ * \param specs The wanted audio specification.
+ */
+ AUD_ReadDevice(AUD_Specs specs);
+
+ /**
+ * Closes the device.
+ */
+ virtual ~AUD_ReadDevice();
+
+ /**
+ * Reads the next bytes into the supplied buffer.
+ * \param buffer The target buffer.
+ * \param length The length in samples to be filled.
+ * \return True if the reading succeeded, false if there are no sounds
+ * played back currently, in that case the buffer is filled with
+ * silence.
+ */
+ bool read(sample_t* buffer, int length);
+};
+
+#endif //AUD_READDEVICE
diff --git a/intern/audaspace/intern/AUD_Reference.h b/intern/audaspace/intern/AUD_Reference.h
index 48732291e48..9bb9d7440b3 100644
--- a/intern/audaspace/intern/AUD_Reference.h
+++ b/intern/audaspace/intern/AUD_Reference.h
@@ -45,7 +45,7 @@ public:
AUD_Reference(T* reference = 0)
{
m_reference = reference;
- m_refcount = new int;
+ m_refcount = new int; AUD_NEW("int")
*m_refcount = 1;
}
@@ -70,8 +70,10 @@ public:
if(*m_refcount == 0)
{
if(m_reference != 0)
- delete m_reference;
- delete m_refcount;
+ {
+ delete m_reference; AUD_DELETE("buffer")
+ }
+ delete m_refcount; AUD_DELETE("int")
}
}
@@ -88,8 +90,10 @@ public:
if(*m_refcount == 0)
{
if(m_reference != 0)
- delete m_reference;
- delete m_refcount;
+ {
+ delete m_reference; AUD_DELETE("buffer")
+ }
+ delete m_refcount; AUD_DELETE("int")
}
m_reference = ref.m_reference;
diff --git a/intern/audaspace/intern/AUD_ResampleFactory.h b/intern/audaspace/intern/AUD_ResampleFactory.h
new file mode 100644
index 00000000000..5493e1005b7
--- /dev/null
+++ b/intern/audaspace/intern/AUD_ResampleFactory.h
@@ -0,0 +1,33 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_RESAMPLEFACTORY
+#define AUD_RESAMPLEFACTORY
+
+#include "AUD_MixerFactory.h"
+
+typedef AUD_MixerFactory AUD_ResampleFactory;
+
+#endif //AUD_RESAMPLEFACTORY
diff --git a/intern/audaspace/intern/AUD_SinusReader.cpp b/intern/audaspace/intern/AUD_SinusReader.cpp
index f33adcdfe03..87e2f789d66 100644
--- a/intern/audaspace/intern/AUD_SinusReader.cpp
+++ b/intern/audaspace/intern/AUD_SinusReader.cpp
@@ -36,7 +36,7 @@ AUD_SinusReader::AUD_SinusReader(double frequency, AUD_SampleRate sampleRate)
{
m_frequency = frequency;
m_position = 0;
- m_buffer = new AUD_Buffer(0); AUD_NEW("buffer")
+ m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
m_sampleRate = sampleRate;
}
@@ -79,11 +79,16 @@ AUD_ReaderType AUD_SinusReader::getType()
return AUD_TYPE_STREAM;
}
+bool AUD_SinusReader::notify(AUD_Message &message)
+{
+ return false;
+}
+
void AUD_SinusReader::read(int & length, sample_t* & buffer)
{
// resize if necessary
if(m_buffer->getSize() < length*4)
- m_buffer->resize(length*4, false);
+ m_buffer->resize(length*4);
// fill with sine data
short* buf = (short*) m_buffer->getBuffer();
@@ -94,6 +99,6 @@ void AUD_SinusReader::read(int & length, sample_t* & buffer)
buf[i*2+1] = buf[i*2];
}
- buffer = (unsigned char*)buf;
+ buffer = (sample_t*)buf;
m_position += length;
}
diff --git a/intern/audaspace/intern/AUD_SinusReader.h b/intern/audaspace/intern/AUD_SinusReader.h
index fb4a7e60b01..cb060dd8a43 100644
--- a/intern/audaspace/intern/AUD_SinusReader.h
+++ b/intern/audaspace/intern/AUD_SinusReader.h
@@ -79,6 +79,7 @@ public:
virtual int getPosition();
virtual AUD_Specs getSpecs();
virtual AUD_ReaderType getType();
+ virtual bool notify(AUD_Message &message);
virtual void read(int & length, sample_t* & buffer);
};
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
index bffa5667b93..0de79f988bc 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
@@ -25,8 +25,9 @@
#include "AUD_SoftwareDevice.h"
#include "AUD_IReader.h"
-#include "AUD_MixerFactory.h"
-#include "AUD_ISuperposer.h"
+#include "AUD_IMixer.h"
+#include "AUD_IFactory.h"
+#include "AUD_SourceCaps.h"
#include <cstring>
@@ -36,18 +37,21 @@ struct AUD_SoftwareHandle : AUD_Handle
/// The reader source.
AUD_IReader* reader;
- /// The behaviour if end of the source is reached.
- AUD_EndBehaviour endBehaviour;
+ /// Whether to keep the source if end of it is reached.
+ bool keep;
- /// Sample count until playback starts.
- int delay;
+ /// The volume of the source.
+ float volume;
};
+typedef std::list<AUD_SoftwareHandle*>::iterator AUD_HandleIterator;
+
void AUD_SoftwareDevice::create()
{
- m_playingSounds = new std::list<AUD_SoftwareHandle*>();
- m_pausedSounds = new std::list<AUD_SoftwareHandle*>();
+ m_playingSounds = new std::list<AUD_SoftwareHandle*>(); AUD_NEW("list")
+ m_pausedSounds = new std::list<AUD_SoftwareHandle*>(); AUD_NEW("list")
m_playback = false;
+ m_volume = 1.0;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
@@ -63,46 +67,41 @@ void AUD_SoftwareDevice::destroy()
if(m_playback)
playing(m_playback = false);
- delete m_mixer;
-
- delete m_superposer;
+ delete m_mixer; AUD_DELETE("mixer")
// delete all playing sounds
while(m_playingSounds->begin() != m_playingSounds->end())
{
delete (*(m_playingSounds->begin()))->reader; AUD_DELETE("reader")
- delete *(m_playingSounds->begin());
+ delete *(m_playingSounds->begin()); AUD_DELETE("handle")
m_playingSounds->erase(m_playingSounds->begin());
}
- delete m_playingSounds;
+ delete m_playingSounds; AUD_DELETE("list")
// delete all paused sounds
while(m_pausedSounds->begin() != m_pausedSounds->end())
{
delete (*(m_pausedSounds->begin()))->reader; AUD_DELETE("reader")
- delete *(m_pausedSounds->begin());
+ delete *(m_pausedSounds->begin()); AUD_DELETE("handle")
m_pausedSounds->erase(m_pausedSounds->begin());
}
- delete m_pausedSounds;
+ delete m_pausedSounds; AUD_DELETE("list")
pthread_mutex_destroy(&m_mutex);
}
void AUD_SoftwareDevice::mix(sample_t* buffer, int length)
{
- pthread_mutex_lock(&m_mutex);
+ lock();
AUD_SoftwareHandle* sound;
- int len, left, pos;
- unsigned char* buf;
+ int len, left;
+ sample_t* buf;
int sample_size = AUD_SAMPLE_SIZE(m_specs);
- bool looped;
-
- // fill with silence
- memset(buffer, 0, length*sample_size);
+ std::list<AUD_SoftwareHandle*> stopSounds;
// for all sounds
- std::list<AUD_SoftwareHandle*>::iterator it = m_playingSounds->begin();
+ AUD_HandleIterator it = m_playingSounds->begin();
while(it != m_playingSounds->end())
{
sound = *it;
@@ -110,68 +109,59 @@ void AUD_SoftwareDevice::mix(sample_t* buffer, int length)
// in case the sound gets deleted after stopping
++it;
- pos = sound->delay;
+ // get the buffer from the source
+ len = length;
+ sound->reader->read(len, buf);
- // check for playback start
- if(pos >= length)
- {
- sound->delay -= length;
- continue;
- }
+ m_mixer->add(buf, sound->reader->getSpecs(), len, sound->volume);
- // remove delay if exists
- if(pos > 0)
- sound->delay = 0;
-
- left = length-pos;
- looped = false;
- while(left > 0)
+ // in case the end of the sound is reached
+ if(len < length)
{
- // get the buffer from the source
- len = left;
- sound->reader->read(len, buf);
- left -= len;
-
- if(len == 0)
- {
- // prevent endless loop
- if(looped)
- {
- stop(sound);
- break;
- }
- }
+ if(sound->keep)
+ pause(sound);
else
- looped = false;
+ stopSounds.push_back(sound);
+ }
+ }
- m_superposer->superpose(buffer + pos*sample_size,
- buf,
- len*sample_size);
+ // fill with silence
+ if(m_specs.format == AUD_FORMAT_U8)
+ memset(buffer, 0x80, length * sample_size);
+ else
+ memset(buffer, 0, length * sample_size);
- pos += len;
+ // superpose
+ m_mixer->superpose(buffer, length, m_volume);
- // in case the end of the sound is reached
- if(left > 0)
- {
- // looping requires us to seek back
- if(sound->endBehaviour == AUD_BEHAVIOUR_LOOP)
- {
- sound->reader->seek(0);
- looped = true;
- }
- else
- {
- if(sound->endBehaviour == AUD_BEHAVIOUR_PAUSE)
- pause(sound);
- else
- stop(sound);
- break;
- }
- }
- }
+ while(!stopSounds.empty())
+ {
+ sound = stopSounds.front();
+ stopSounds.pop_front();
+ stop(sound);
}
- pthread_mutex_unlock(&m_mutex);
+ unlock();
+}
+
+bool AUD_SoftwareDevice::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;
+}
+
+void AUD_SoftwareDevice::setMixer(AUD_IMixer* mixer)
+{
+ delete m_mixer; AUD_DELETE("mixer")
+ m_mixer = mixer;
+ mixer->setSpecs(m_specs);
}
AUD_Specs AUD_SoftwareDevice::getSpecs()
@@ -179,44 +169,32 @@ AUD_Specs AUD_SoftwareDevice::getSpecs()
return m_specs;
}
-AUD_Handle* AUD_SoftwareDevice::play(AUD_IFactory* factory,
- AUD_EndBehaviour endBehaviour,
- int seekTo)
+AUD_Handle* AUD_SoftwareDevice::play(AUD_IFactory* factory, bool keep)
{
AUD_IReader* reader = factory->createReader();
if(reader == NULL)
AUD_THROW(AUD_ERROR_READER);
- // check if the reader needs to be mixed
- AUD_Specs specs = reader->getSpecs();
- if(memcmp(&m_specs, &specs, sizeof(AUD_Specs)) != 0)
- {
- m_mixer->setReader(reader);
- reader = m_mixer->createReader();
- if(reader == NULL)
- return NULL;
- }
+ // prepare the reader
+ reader = m_mixer->prepare(reader);
+ if(reader == NULL)
+ return NULL;
AUD_Specs rs = reader->getSpecs();
// play sound
- AUD_SoftwareHandle* sound = new AUD_SoftwareHandle;
- sound->endBehaviour = endBehaviour;
+ AUD_SoftwareHandle* sound = new AUD_SoftwareHandle; AUD_NEW("handle")
+ sound->keep = keep;
sound->reader = reader;
- sound->delay = 0;
-
- if(seekTo > 0)
- reader->seek(seekTo);
- else if(seekTo < 0)
- sound->delay = -seekTo;
+ sound->volume = 1.0;
- pthread_mutex_lock(&m_mutex);
+ lock();
m_playingSounds->push_back(sound);
if(!m_playback)
playing(m_playback = true);
- pthread_mutex_unlock(&m_mutex);
+ unlock();
return sound;
}
@@ -224,8 +202,8 @@ AUD_Handle* AUD_SoftwareDevice::play(AUD_IFactory* factory,
bool AUD_SoftwareDevice::pause(AUD_Handle* handle)
{
// only songs that are played can be paused
- pthread_mutex_lock(&m_mutex);
- for(std::list<AUD_SoftwareHandle*>::iterator i = m_playingSounds->begin();
+ lock();
+ for(AUD_HandleIterator i = m_playingSounds->begin();
i != m_playingSounds->end(); i++)
{
if(*i == handle)
@@ -234,19 +212,19 @@ bool AUD_SoftwareDevice::pause(AUD_Handle* handle)
m_playingSounds->erase(i);
if(m_playingSounds->empty())
playing(m_playback = false);
- pthread_mutex_unlock(&m_mutex);
+ unlock();
return true;
}
}
- pthread_mutex_unlock(&m_mutex);
+ unlock();
return false;
}
bool AUD_SoftwareDevice::resume(AUD_Handle* handle)
{
// only songs that are paused can be resumed
- pthread_mutex_lock(&m_mutex);
- for(std::list<AUD_SoftwareHandle*>::iterator i = m_pausedSounds->begin();
+ lock();
+ for(AUD_HandleIterator i = m_pausedSounds->begin();
i != m_pausedSounds->end(); i++)
{
if(*i == handle)
@@ -255,124 +233,119 @@ bool AUD_SoftwareDevice::resume(AUD_Handle* handle)
m_pausedSounds->erase(i);
if(!m_playback)
playing(m_playback = true);
- pthread_mutex_unlock(&m_mutex);
+ unlock();
return true;
}
}
- pthread_mutex_unlock(&m_mutex);
+ unlock();
return false;
}
bool AUD_SoftwareDevice::stop(AUD_Handle* handle)
{
- pthread_mutex_lock(&m_mutex);
- for(std::list<AUD_SoftwareHandle*>::iterator i = m_playingSounds->begin();
+ lock();
+ for(AUD_HandleIterator i = m_playingSounds->begin();
i != m_playingSounds->end(); i++)
{
if(*i == handle)
{
delete (*i)->reader; AUD_DELETE("reader")
- delete *i;
+ delete *i; AUD_DELETE("handle")
m_playingSounds->erase(i);
if(m_playingSounds->empty())
playing(m_playback = false);
- pthread_mutex_unlock(&m_mutex);
+ unlock();
return true;
}
}
- for(std::list<AUD_SoftwareHandle*>::iterator i = m_pausedSounds->begin();
+ for(AUD_HandleIterator i = m_pausedSounds->begin();
i != m_pausedSounds->end(); i++)
{
if(*i == handle)
{
delete (*i)->reader; AUD_DELETE("reader")
- delete *i;
+ delete *i; AUD_DELETE("handle")
m_pausedSounds->erase(i);
- pthread_mutex_unlock(&m_mutex);
+ unlock();
return true;
}
}
- pthread_mutex_unlock(&m_mutex);
+ unlock();
return false;
}
-bool AUD_SoftwareDevice::setEndBehaviour(AUD_Handle* handle,
- AUD_EndBehaviour endBehaviour)
+bool AUD_SoftwareDevice::setKeep(AUD_Handle* handle, bool keep)
{
- pthread_mutex_lock(&m_mutex);
- for(std::list<AUD_SoftwareHandle*>::iterator i = m_playingSounds->begin();
- i != m_playingSounds->end(); i++)
- {
- if(*i == handle)
- {
- (*i)->endBehaviour = endBehaviour;
- pthread_mutex_unlock(&m_mutex);
- return true;
- }
- }
- for(std::list<AUD_SoftwareHandle*>::iterator i = m_pausedSounds->begin();
- i != m_pausedSounds->end(); i++)
+ lock();
+ if(isValid(handle))
{
- if(*i == handle)
- {
- (*i)->endBehaviour = endBehaviour;
- pthread_mutex_unlock(&m_mutex);
- return true;
- }
+ ((AUD_SoftwareHandle*)handle)->keep = keep;
+ unlock();
+ return true;
}
- pthread_mutex_unlock(&m_mutex);
+ unlock();
return false;
}
-bool AUD_SoftwareDevice::seek(AUD_Handle* handle, int position)
+bool AUD_SoftwareDevice::sendMessage(AUD_Handle* handle, AUD_Message &message)
{
- pthread_mutex_lock(&m_mutex);
- for(std::list<AUD_SoftwareHandle*>::iterator i = m_playingSounds->begin();
- i != m_playingSounds->end(); i++)
+ lock();
+
+ bool result = false;
+
+ if(handle == 0)
{
- if(*i == handle)
- {
- (*i)->reader->seek(position);
- pthread_mutex_unlock(&m_mutex);
- return true;
- }
+ for(AUD_HandleIterator i = m_playingSounds->begin();
+ i != m_playingSounds->end(); i++)
+ result |= (*i)->reader->notify(message);
+ for(AUD_HandleIterator i = m_pausedSounds->begin();
+ i != m_pausedSounds->end(); i++)
+ result |= (*i)->reader->notify(message);
}
- for(std::list<AUD_SoftwareHandle*>::iterator i = m_pausedSounds->begin();
- i != m_pausedSounds->end(); i++)
+ else if(isValid(handle))
+ result = ((AUD_SoftwareHandle*)handle)->reader->notify(message);
+ unlock();
+ return result;
+}
+
+bool AUD_SoftwareDevice::seek(AUD_Handle* handle, float position)
+{
+ lock();
+
+ if(isValid(handle))
{
- if(*i == handle)
- {
- (*i)->reader->seek(position);
- pthread_mutex_unlock(&m_mutex);
- return true;
- }
+ AUD_IReader* reader = ((AUD_SoftwareHandle*)handle)->reader;
+ reader->seek((int)(position * reader->getSpecs().rate));
+ unlock();
+ return true;
}
- pthread_mutex_unlock(&m_mutex);
+
+ unlock();
return false;
}
AUD_Status AUD_SoftwareDevice::getStatus(AUD_Handle* handle)
{
- pthread_mutex_lock(&m_mutex);
- for(std::list<AUD_SoftwareHandle*>::iterator i = m_playingSounds->begin();
+ lock();
+ for(AUD_HandleIterator i = m_playingSounds->begin();
i != m_playingSounds->end(); i++)
{
if(*i == handle)
{
- pthread_mutex_unlock(&m_mutex);
+ unlock();
return AUD_STATUS_PLAYING;
}
}
- for(std::list<AUD_SoftwareHandle*>::iterator i = m_pausedSounds->begin();
+ for(AUD_HandleIterator i = m_pausedSounds->begin();
i != m_pausedSounds->end(); i++)
{
if(*i == handle)
{
- pthread_mutex_unlock(&m_mutex);
+ unlock();
return AUD_STATUS_PAUSED;
}
}
- pthread_mutex_unlock(&m_mutex);
+ unlock();
return AUD_STATUS_INVALID;
}
@@ -385,3 +358,71 @@ void AUD_SoftwareDevice::unlock()
{
pthread_mutex_unlock(&m_mutex);
}
+
+bool AUD_SoftwareDevice::checkCapability(int capability)
+{
+ return capability == AUD_CAPS_SOFTWARE_DEVICE ||
+ capability == AUD_CAPS_VOLUME ||
+ capability == AUD_CAPS_SOURCE_VOLUME;
+}
+
+bool AUD_SoftwareDevice::setCapability(int capability, void *value)
+{
+ switch(capability)
+ {
+ case AUD_CAPS_VOLUME:
+ lock();
+ m_volume = *((float*)value);
+ if(m_volume > 1.0)
+ m_volume = 1.0;
+ else if(m_volume < 0.0)
+ m_volume = 0.0;
+ unlock();
+ return true;
+ case AUD_CAPS_SOURCE_VOLUME:
+ {
+ AUD_SourceCaps* caps = (AUD_SourceCaps*) value;
+ lock();
+ if(isValid(caps->handle))
+ {
+ AUD_SoftwareHandle* handle = (AUD_SoftwareHandle*)caps->handle;
+ handle->volume = caps->value;
+ if(handle->volume > 1.0)
+ handle->volume = 1.0;
+ else if(handle->volume < 0.0)
+ handle->volume = 0.0;
+ unlock();
+ return true;
+ }
+ unlock();
+ }
+ break;
+ }
+ return false;
+}
+
+bool AUD_SoftwareDevice::getCapability(int capability, void *value)
+{
+ switch(capability)
+ {
+ case AUD_CAPS_VOLUME:
+ lock();
+ *((float*)value) = m_volume;
+ unlock();
+ return true;
+ case AUD_CAPS_SOURCE_VOLUME:
+ {
+ AUD_SourceCaps* caps = (AUD_SourceCaps*) value;
+ lock();
+ if(isValid(caps->handle))
+ {
+ caps->value = ((AUD_SoftwareHandle*)caps->handle)->volume;
+ unlock();
+ return true;
+ }
+ unlock();
+ }
+ break;
+ }
+ return false;
+}
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.h b/intern/audaspace/intern/AUD_SoftwareDevice.h
index ed22cd6e745..afab92fc4cd 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.h
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.h
@@ -27,9 +27,8 @@
#define AUD_SOFTWAREDEVICE
#include "AUD_IDevice.h"
-class AUD_MixerFactory;
-class AUD_ISuperposer;
struct AUD_SoftwareHandle;
+class AUD_IMixer;
#include <list>
#include <pthread.h>
@@ -38,7 +37,7 @@ struct AUD_SoftwareHandle;
* This device plays is a generic device with software mixing.
* Classes implementing this have to:
* - Implement the playing function.
- * - Prepare the m_specs, m_mixer and m_superposer variables.
+ * - Prepare the m_specs, m_mixer variables.
* - Call the create and destroy functions.
* - Call the mix function to retrieve their audio data.
*/
@@ -51,14 +50,9 @@ protected:
AUD_Specs m_specs;
/**
- * The resampling factory. Will be deleted by the destroy function.
+ * The mixer. Will be deleted by the destroy function.
*/
- AUD_MixerFactory* m_mixer;
-
- /**
- * The superposer. Will be deleted by the destroy function.
- */
- AUD_ISuperposer* m_superposer;
+ AUD_IMixer* m_mixer;
/**
* Initializes member variables.
@@ -104,20 +98,39 @@ private:
*/
pthread_mutex_t m_mutex;
+ /**
+ * The overall volume of the device.
+ */
+ 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);
+
public:
+ /**
+ * Sets a new mixer.
+ * \param mixer The new mixer.
+ */
+ void setMixer(AUD_IMixer* mixer);
+
virtual AUD_Specs getSpecs();
- virtual AUD_Handle* play(AUD_IFactory* factory,
- AUD_EndBehaviour endBehaviour = AUD_BEHAVIOUR_STOP,
- int seekTo = 0);
+ 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 setEndBehaviour(AUD_Handle* handle,
- AUD_EndBehaviour endBehaviour);
- virtual bool seek(AUD_Handle* handle, int position);
+ virtual bool setKeep(AUD_Handle* handle, bool keep);
+ virtual bool sendMessage(AUD_Handle* handle, AUD_Message &message);
+ virtual bool seek(AUD_Handle* handle, float position);
virtual AUD_Status getStatus(AUD_Handle* handle);
virtual void lock();
virtual void unlock();
+ virtual bool checkCapability(int capability);
+ virtual bool setCapability(int capability, void *value);
+ virtual bool getCapability(int capability, void *value);
};
#endif //AUD_SOFTWAREDEVICE
diff --git a/intern/audaspace/intern/AUD_SourceCaps.h b/intern/audaspace/intern/AUD_SourceCaps.h
new file mode 100644
index 00000000000..b1edd2b9b4e
--- /dev/null
+++ b/intern/audaspace/intern/AUD_SourceCaps.h
@@ -0,0 +1,41 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN LGPL LICENSE BLOCK *****
+ *
+ * Copyright 2009 Jörg Hermann Müller
+ *
+ * This file is part of AudaSpace.
+ *
+ * AudaSpace is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AudaSpace is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with AudaSpace. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * ***** END LGPL LICENSE BLOCK *****
+ */
+
+#ifndef AUD_SOURCECAPS
+#define AUD_SOURCECAPS
+
+#include "AUD_IDevice.h"
+
+/// The structure for source capabilities.
+typedef struct
+{
+ /// The source to apply the capability on.
+ AUD_Handle* handle;
+
+ /// The value for the capability.
+ float value;
+} AUD_SourceCaps;
+
+#endif //AUD_SOURCECAPS
diff --git a/intern/audaspace/intern/AUD_Space.h b/intern/audaspace/intern/AUD_Space.h
index 961856a72bf..990a3743b5f 100644
--- a/intern/audaspace/intern/AUD_Space.h
+++ b/intern/audaspace/intern/AUD_Space.h
@@ -23,9 +23,11 @@
* ***** END LGPL LICENSE BLOCK *****
*/
-#ifndef AUD_ENUMS
-#define AUD_ENUMS
+#ifndef AUD_SPACE
+#define AUD_SPACE
+/// The size of a format in bytes.
+#define AUD_FORMAT_SIZE(format) (format & 0x0F)
/// The size of a sample in the specified format in bytes.
#define AUD_SAMPLE_SIZE(specs) (specs.channels * (specs.format & 0x0F))
/// Throws a AUD_Exception with the provided error code.
@@ -40,7 +42,56 @@
/// The size by which a buffer should be resized if the final extent is unknown.
#define AUD_BUFFER_RESIZE_BYTES 5292000
-/// Used for debugging memory leaks.
+/// The default playback buffer size of a device.
+#define AUD_DEFAULT_BUFFER_SIZE 1024
+
+// Capability defines
+
+/// This capability checks whether a device is a 3D device. See AUD_I3DDevice.h.
+#define AUD_CAPS_3D_DEVICE 0x0001
+
+/**
+ * This capability checks whether a device is a software device. See
+ * AUD_SoftwareDevice.
+ */
+#define AUD_CAPS_SOFTWARE_DEVICE 0x0002
+
+/**
+ * This capability enables the user to set the overall volume of the device.
+ * You can set and get it with the pointer pointing to a float value between
+ * 0.0 (muted) and 1.0 (maximum volume).
+ */
+#define AUD_CAPS_VOLUME 0x0101
+
+/**
+ * This capability enables the user to set the volume of a source.
+ * You can set and get it with the pointer pointing to a AUD_SourceValue
+ * structure defined in AUD_SourceCaps.h.
+ */
+#define AUD_CAPS_SOURCE_VOLUME 0x1001
+
+/**
+ * This capability enables the user to set the pitch of a source.
+ * You can set and get it with the pointer pointing to a AUD_SourceValue
+ * structure defined in AUD_SourceCaps.h.
+ */
+#define AUD_CAPS_SOURCE_PITCH 0x1002
+
+/**
+ * This capability enables the user to buffer a factory into the device.
+ * Setting with the factory as pointer loads the factory into a device internal
+ * buffer. Play function calls with the buffered factory as argument result in
+ * the internal buffer being played back, so there's no reader created, what
+ * also results in not being able to send messages to that handle.
+ * A repeated call with the same factory doesn't do anything.
+ * A set call with a NULL pointer results in all buffered factories being
+ * deleted.
+ * \note This is only possible with factories that create readers of the buffer
+ * type.
+ */
+#define AUD_CAPS_BUFFERED_FACTORY 0x2001
+
+// Used for debugging memory leaks.
//#define AUD_DEBUG_MEMORY
#ifdef AUD_DEBUG_MEMORY
@@ -52,14 +103,6 @@ int AUD_References(int count = 0, const char* text = "");
#define AUD_DELETE(text)
#endif
-/// The behaviour of the playback device for a source that reached its end.
-typedef enum
-{
- AUD_BEHAVIOUR_STOP, /// Stop the sound (deletes the reader).
- AUD_BEHAVIOUR_PAUSE, /// Pause the sound.
- AUD_BEHAVIOUR_LOOP /// Seek to front and replay.
-} AUD_EndBehaviour;
-
/**
* The format of a sample.
* The last 4 bit save the byte count of the format.
@@ -71,7 +114,6 @@ typedef enum
AUD_FORMAT_S16 = 0x12, /// 2 byte signed integer.
AUD_FORMAT_S24 = 0x13, /// 3 byte signed integer.
AUD_FORMAT_S32 = 0x14, /// 4 byte signed integer.
- AUD_FORMAT_S64 = 0x18, /// 8 byte signed integer.
AUD_FORMAT_FLOAT32 = 0x24, /// 4 byte float.
AUD_FORMAT_FLOAT64 = 0x28 /// 8 byte float.
} AUD_SampleFormat;
@@ -137,9 +179,25 @@ typedef enum
AUD_ERROR_FACTORY,
AUD_ERROR_FILE,
AUD_ERROR_FFMPEG,
- AUD_ERROR_SDL
+ AUD_ERROR_SDL,
+ AUD_ERROR_OPENAL
} AUD_Error;
+/// Message codes.
+typedef enum
+{
+ AUD_MSG_INVALID = 0, /// Invalid message.
+ AUD_MSG_LOOP, /// Loop reader message.
+ AUD_MSG_VOLUME /// Volume reader message.
+} AUD_MessageType;
+
+/// Fading types.
+typedef enum
+{
+ AUD_FADE_IN,
+ AUD_FADE_OUT
+} AUD_FadeType;
+
/// Sample pointer type.
typedef unsigned char sample_t;
@@ -168,4 +226,22 @@ typedef struct
// void* userData; - for the case it is needed someday
} AUD_Exception;
-#endif //AUD_ENUMS
+/// Message structure.
+typedef struct
+{
+ /**
+ * The message type.
+ */
+ AUD_MessageType type;
+
+ union
+ {
+ // loop reader
+ int loopcount;
+
+ // volume reader
+ float volume;
+ };
+} AUD_Message;
+
+#endif //AUD_SPACE
diff --git a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp
index f16c2a522a7..11391fa4a08 100644
--- a/intern/audaspace/intern/AUD_StreamBufferFactory.cpp
+++ b/intern/audaspace/intern/AUD_StreamBufferFactory.cpp
@@ -37,12 +37,12 @@ AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory)
AUD_THROW(AUD_ERROR_READER);
m_specs = reader->getSpecs();
- m_buffer = AUD_Reference<AUD_Buffer>(new AUD_Buffer(0));
+ m_buffer = AUD_Reference<AUD_Buffer>(new AUD_Buffer()); AUD_NEW("buffer")
int sample_size = AUD_SAMPLE_SIZE(m_specs);
int length;
int index = 0;
- unsigned char* buffer;
+ sample_t* buffer;
// get an aproximated size if possible
int size = reader->getLength();
@@ -56,7 +56,7 @@ AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory)
while(index == m_buffer.get()->getSize() / sample_size)
{
// increase
- m_buffer.get()->resize(size*sample_size);
+ m_buffer.get()->resize(size*sample_size, true);
// read more
length = size-index;
@@ -68,7 +68,7 @@ AUD_StreamBufferFactory::AUD_StreamBufferFactory(AUD_IFactory* factory)
index += length;
}
- m_buffer.get()->resize(index*sample_size);
+ m_buffer.get()->resize(index*sample_size, true);
delete reader; AUD_DELETE("reader")
}