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
diff options
context:
space:
mode:
Diffstat (limited to 'extern/audaspace/bindings')
-rw-r--r--extern/audaspace/bindings/C/AUD_Device.cpp336
-rw-r--r--extern/audaspace/bindings/C/AUD_Device.h258
-rw-r--r--extern/audaspace/bindings/C/AUD_DynamicMusic.cpp144
-rw-r--r--extern/audaspace/bindings/C/AUD_DynamicMusic.h145
-rw-r--r--extern/audaspace/bindings/C/AUD_HRTF.cpp50
-rw-r--r--extern/audaspace/bindings/C/AUD_HRTF.h48
-rw-r--r--extern/audaspace/bindings/C/AUD_Handle.cpp384
-rw-r--r--extern/audaspace/bindings/C/AUD_Handle.h308
-rw-r--r--extern/audaspace/bindings/C/AUD_ImpulseResponse.cpp44
-rw-r--r--extern/audaspace/bindings/C/AUD_ImpulseResponse.h40
-rw-r--r--extern/audaspace/bindings/C/AUD_PlaybackManager.cpp94
-rw-r--r--extern/audaspace/bindings/C/AUD_PlaybackManager.h103
-rw-r--r--extern/audaspace/bindings/C/AUD_Sequence.cpp315
-rw-r--r--extern/audaspace/bindings/C/AUD_Sequence.h338
-rw-r--r--extern/audaspace/bindings/C/AUD_Sound.cpp709
-rw-r--r--extern/audaspace/bindings/C/AUD_Sound.h370
-rw-r--r--extern/audaspace/bindings/C/AUD_Source.cpp84
-rw-r--r--extern/audaspace/bindings/C/AUD_Source.h84
-rw-r--r--extern/audaspace/bindings/C/AUD_Special.cpp420
-rw-r--r--extern/audaspace/bindings/C/AUD_Special.h138
-rw-r--r--extern/audaspace/bindings/C/AUD_ThreadPool.cpp42
-rw-r--r--extern/audaspace/bindings/C/AUD_ThreadPool.h40
-rw-r--r--extern/audaspace/bindings/C/AUD_Types.h179
-rw-r--r--extern/audaspace/bindings/doc/conf.py.in261
-rw-r--r--extern/audaspace/bindings/doc/device.rst7
-rw-r--r--extern/audaspace/bindings/doc/handle.rst7
-rw-r--r--extern/audaspace/bindings/doc/index.rst35
-rw-r--r--extern/audaspace/bindings/doc/sequence.rst7
-rw-r--r--extern/audaspace/bindings/doc/sequence_entry.rst7
-rw-r--r--extern/audaspace/bindings/doc/sound.rst7
-rw-r--r--extern/audaspace/bindings/doc/tutorials.rst166
-rw-r--r--extern/audaspace/bindings/python/PyAPI.cpp231
-rw-r--r--extern/audaspace/bindings/python/PyAPI.h45
-rw-r--r--extern/audaspace/bindings/python/PyDevice.cpp785
-rw-r--r--extern/audaspace/bindings/python/PyDevice.h33
-rw-r--r--extern/audaspace/bindings/python/PyDynamicMusic.cpp467
-rw-r--r--extern/audaspace/bindings/python/PyDynamicMusic.h33
-rw-r--r--extern/audaspace/bindings/python/PyHRTF.cpp247
-rw-r--r--extern/audaspace/bindings/python/PyHRTF.h33
-rw-r--r--extern/audaspace/bindings/python/PyHandle.cpp1126
-rw-r--r--extern/audaspace/bindings/python/PyHandle.h33
-rw-r--r--extern/audaspace/bindings/python/PyImpulseResponse.cpp137
-rw-r--r--extern/audaspace/bindings/python/PyImpulseResponse.h33
-rw-r--r--extern/audaspace/bindings/python/PyPlaybackManager.cpp389
-rw-r--r--extern/audaspace/bindings/python/PyPlaybackManager.h33
-rw-r--r--extern/audaspace/bindings/python/PySequence.cpp655
-rw-r--r--extern/audaspace/bindings/python/PySequence.h33
-rw-r--r--extern/audaspace/bindings/python/PySequenceEntry.cpp740
-rw-r--r--extern/audaspace/bindings/python/PySequenceEntry.h33
-rw-r--r--extern/audaspace/bindings/python/PySound.cpp1966
-rw-r--r--extern/audaspace/bindings/python/PySound.h33
-rw-r--r--extern/audaspace/bindings/python/PySource.cpp260
-rw-r--r--extern/audaspace/bindings/python/PySource.h33
-rw-r--r--extern/audaspace/bindings/python/PyThreadPool.cpp134
-rw-r--r--extern/audaspace/bindings/python/PyThreadPool.h33
-rw-r--r--extern/audaspace/bindings/python/examples/binaural.py13
-rw-r--r--extern/audaspace/bindings/python/examples/convolution.py10
-rw-r--r--extern/audaspace/bindings/python/examples/dynamicmusic.py20
-rw-r--r--extern/audaspace/bindings/python/examples/playbackmanager.py27
-rw-r--r--extern/audaspace/bindings/python/examples/player.py7
-rw-r--r--extern/audaspace/bindings/python/examples/randomSounds.py21
-rw-r--r--extern/audaspace/bindings/python/examples/simple.py7
-rw-r--r--extern/audaspace/bindings/python/examples/siren.py19
-rw-r--r--extern/audaspace/bindings/python/examples/siren2.py23
-rw-r--r--extern/audaspace/bindings/python/examples/tetris.py66
-rw-r--r--extern/audaspace/bindings/python/examples/tetris2.py64
-rw-r--r--extern/audaspace/bindings/python/examples/tetris3.py63
-rw-r--r--extern/audaspace/bindings/python/setup.py.in61
68 files changed, 13116 insertions, 0 deletions
diff --git a/extern/audaspace/bindings/C/AUD_Device.cpp b/extern/audaspace/bindings/C/AUD_Device.cpp
new file mode 100644
index 00000000000..441f228deac
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_Device.cpp
@@ -0,0 +1,336 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#include "devices/DeviceManager.h"
+#include "devices/I3DDevice.h"
+#include "devices/IDeviceFactory.h"
+#include "devices/ReadDevice.h"
+#include "Exception.h"
+
+#include <cassert>
+
+using namespace aud;
+
+#define AUD_CAPI_IMPLEMENTATION
+#include "AUD_Device.h"
+
+static inline aud::Specs convCToSpec(AUD_Specs specs)
+{
+ aud::Specs s;
+ s.channels = static_cast<Channels>(specs.channels);
+ s.rate = static_cast<SampleRate>(specs.rate);
+ return s;
+}
+
+static inline aud::DeviceSpecs convCToDSpec(AUD_DeviceSpecs specs)
+{
+ aud::DeviceSpecs s;
+ s.specs = convCToSpec(specs.specs);
+ s.format = static_cast<SampleFormat>(specs.format);
+ return s;
+}
+
+AUD_API AUD_Device* AUD_Device_open(const char* type, AUD_DeviceSpecs specs, int buffersize, const char* name)
+{
+ DeviceSpecs dspecs = convCToDSpec(specs);
+
+ if(dspecs.channels == CHANNELS_INVALID)
+ dspecs.channels = CHANNELS_STEREO;
+ if(dspecs.format == FORMAT_INVALID)
+ dspecs.format = FORMAT_FLOAT32;
+ if(dspecs.rate == RATE_INVALID)
+ dspecs.rate = RATE_48000;
+ if(buffersize < 128)
+ buffersize = AUD_DEFAULT_BUFFER_SIZE;
+ if(name == nullptr)
+ name = "";
+
+ try
+ {
+ if(!type)
+ {
+ auto device = DeviceManager::getDevice();
+ if(!device)
+ {
+ DeviceManager::openDefaultDevice();
+ device = DeviceManager::getDevice();
+ }
+ return new AUD_Device(device);
+ }
+
+ if(type == std::string("read"))
+ {
+ return new AUD_Device(new ReadDevice(dspecs));
+ }
+
+ std::shared_ptr<IDeviceFactory> factory;
+ if(!*type)
+ factory = DeviceManager::getDefaultDeviceFactory();
+ else
+ factory = DeviceManager::getDeviceFactory(type);
+
+ if(factory)
+ {
+ factory->setName(name);
+ factory->setSpecs(dspecs);
+ factory->setBufferSize(buffersize);
+ return new AUD_Device(factory->openDevice());
+ }
+ }
+ catch(Exception&)
+ {
+ }
+ return nullptr;
+}
+
+AUD_API void AUD_Device_lock(AUD_Device* device)
+{
+ auto dev = device ? *device : DeviceManager::getDevice();
+ dev->lock();
+}
+
+AUD_API AUD_Handle* AUD_Device_play(AUD_Device* device, AUD_Sound* sound, int keep)
+{
+ assert(sound);
+ auto dev = device ? *device : DeviceManager::getDevice();
+
+ try
+ {
+ AUD_Handle handle = dev->play(*sound, keep);
+ if(handle.get())
+ {
+ return new AUD_Handle(handle);
+ }
+ }
+ catch(Exception&)
+ {
+ }
+ return nullptr;
+}
+
+AUD_API void AUD_Device_stopAll(AUD_Device* device)
+{
+ auto dev = device ? *device : DeviceManager::getDevice();
+ dev->stopAll();
+}
+
+AUD_API void AUD_Device_unlock(AUD_Device* device)
+{
+ auto dev = device ? *device : DeviceManager::getDevice();
+ dev->unlock();
+}
+
+AUD_API AUD_Channels AUD_Device_getChannels(AUD_Device* device)
+{
+ auto dev = device ? *device : DeviceManager::getDevice();
+ return static_cast<AUD_Channels>(dev->getSpecs().channels);
+}
+
+AUD_API AUD_DistanceModel AUD_Device_getDistanceModel(AUD_Device* device)
+{
+ auto dev = device ? std::dynamic_pointer_cast<I3DDevice>(*device) : DeviceManager::get3DDevice();
+ return static_cast<AUD_DistanceModel>(dev->getDistanceModel());
+}
+
+AUD_API void AUD_Device_setDistanceModel(AUD_Device* device, AUD_DistanceModel value)
+{
+ auto dev = device ? std::dynamic_pointer_cast<I3DDevice>(*device) : DeviceManager::get3DDevice();
+ dev->setDistanceModel(static_cast<DistanceModel>(value));
+}
+
+AUD_API float AUD_Device_getDopplerFactor(AUD_Device* device)
+{
+ auto dev = device ? std::dynamic_pointer_cast<I3DDevice>(*device) : DeviceManager::get3DDevice();
+ return dev->getDopplerFactor();
+}
+
+AUD_API void AUD_Device_setDopplerFactor(AUD_Device* device, float value)
+{
+ auto dev = device ? std::dynamic_pointer_cast<I3DDevice>(*device) : DeviceManager::get3DDevice();
+ dev->setDopplerFactor(value);
+}
+
+AUD_API AUD_SampleFormat AUD_Device_getFormat(AUD_Device* device)
+{
+ auto dev = device ? *device : DeviceManager::getDevice();
+ return static_cast<AUD_SampleFormat>(dev->getSpecs().format);
+}
+
+AUD_API void AUD_Device_getListenerLocation(AUD_Device* device, float value[3])
+{
+ auto dev = device ? std::dynamic_pointer_cast<I3DDevice>(*device) : DeviceManager::get3DDevice();
+ Vector3 v = dev->getListenerLocation();
+ value[0] = v.x();
+ value[1] = v.y();
+ value[2] = v.z();
+}
+
+AUD_API void AUD_Device_setListenerLocation(AUD_Device* device, const float value[3])
+{
+ auto dev = device ? std::dynamic_pointer_cast<I3DDevice>(*device) : DeviceManager::get3DDevice();
+ Vector3 v(value[0], value[1], value[2]);
+ dev->setListenerLocation(v);
+}
+
+AUD_API void AUD_Device_getListenerOrientation(AUD_Device* device, float value[4])
+{
+ auto dev = device ? std::dynamic_pointer_cast<I3DDevice>(*device) : DeviceManager::get3DDevice();
+ Quaternion v = dev->getListenerOrientation();
+ value[0] = v.x();
+ value[1] = v.y();
+ value[2] = v.z();
+ value[3] = v.w();
+}
+
+AUD_API void AUD_Device_setListenerOrientation(AUD_Device* device, const float value[4])
+{
+ auto dev = device ? std::dynamic_pointer_cast<I3DDevice>(*device) : DeviceManager::get3DDevice();
+ Quaternion v(value[3], value[0], value[1], value[2]);
+ dev->setListenerOrientation(v);
+}
+
+AUD_API void AUD_Device_getListenerVelocity(AUD_Device* device, float value[3])
+{
+ auto dev = device ? std::dynamic_pointer_cast<I3DDevice>(*device) : DeviceManager::get3DDevice();
+ Vector3 v = dev->getListenerVelocity();
+ value[0] = v.x();
+ value[1] = v.y();
+ value[2] = v.z();
+}
+
+AUD_API void AUD_Device_setListenerVelocity(AUD_Device* device, const float value[3])
+{
+ auto dev = device ? std::dynamic_pointer_cast<I3DDevice>(*device) : DeviceManager::get3DDevice();
+ Vector3 v(value[0], value[1], value[2]);
+ dev->setListenerVelocity(v);
+}
+
+AUD_API double AUD_Device_getRate(AUD_Device* device)
+{
+ auto dev = device ? *device : DeviceManager::getDevice();
+ return dev->getSpecs().rate;
+}
+
+AUD_API float AUD_Device_getSpeedOfSound(AUD_Device* device)
+{
+ auto dev = device ? std::dynamic_pointer_cast<I3DDevice>(*device) : DeviceManager::get3DDevice();
+ return dev->getSpeedOfSound();
+}
+
+AUD_API void AUD_Device_setSpeedOfSound(AUD_Device* device, float value)
+{
+ auto dev = device ? std::dynamic_pointer_cast<I3DDevice>(*device) : DeviceManager::get3DDevice();
+ dev->setSpeedOfSound(value);
+}
+
+AUD_API float AUD_Device_getVolume(AUD_Device* device)
+{
+ auto dev = device ? *device : DeviceManager::getDevice();
+ return dev->getVolume();
+}
+
+AUD_API void AUD_Device_setVolume(AUD_Device* device, float value)
+{
+ auto dev = device ? *device : DeviceManager::getDevice();
+ dev->setVolume(value);
+}
+
+AUD_API int AUD_Device_read(AUD_Device* device, unsigned char* buffer, int length)
+{
+ assert(device);
+ assert(buffer);
+
+ auto readDevice = std::dynamic_pointer_cast<ReadDevice>(*device);
+ if(!readDevice)
+ return false;
+
+ try
+ {
+ return readDevice->read(buffer, length);
+ }
+ catch(Exception&)
+ {
+ return false;
+ }
+}
+
+AUD_API void AUD_Device_free(AUD_Device* device)
+{
+ assert(device);
+
+ try
+ {
+ delete device;
+ }
+ catch(Exception&)
+ {
+ }
+}
+
+AUD_API AUD_Device* AUD_Device_getCurrent()
+{
+ auto device = DeviceManager::getDevice();
+
+ if(!device)
+ return nullptr;
+
+ return new AUD_Device(device);
+}
+
+AUD_API void AUD_seekSynchronizer(AUD_Handle* handle, float time)
+{
+ auto synchronizer = DeviceManager::getDevice()->getSynchronizer();
+ if(synchronizer)
+ synchronizer->seek(*reinterpret_cast<std::shared_ptr<IHandle>*>(handle), time);
+}
+
+AUD_API float AUD_getSynchronizerPosition(AUD_Handle* handle)
+{
+ auto synchronizer = DeviceManager::getDevice()->getSynchronizer();
+ if(synchronizer)
+ return synchronizer->getPosition(*reinterpret_cast<std::shared_ptr<IHandle>*>(handle));
+ return (*reinterpret_cast<std::shared_ptr<IHandle>*>(handle))->getPosition();
+}
+
+AUD_API void AUD_playSynchronizer()
+{
+ auto synchronizer = DeviceManager::getDevice()->getSynchronizer();
+ if(synchronizer)
+ synchronizer->play();
+}
+
+AUD_API void AUD_stopSynchronizer()
+{
+ auto synchronizer = DeviceManager::getDevice()->getSynchronizer();
+ if(synchronizer)
+ synchronizer->stop();
+}
+
+AUD_API void AUD_setSynchronizerCallback(AUD_syncFunction function, void* data)
+{
+ auto synchronizer = DeviceManager::getDevice()->getSynchronizer();
+ if(synchronizer)
+ synchronizer->setSyncCallback(function, data);
+}
+
+AUD_API int AUD_isSynchronizerPlaying()
+{
+ auto synchronizer = DeviceManager::getDevice()->getSynchronizer();
+ if(synchronizer)
+ return synchronizer->isPlaying();
+ return false;
+}
+
diff --git a/extern/audaspace/bindings/C/AUD_Device.h b/extern/audaspace/bindings/C/AUD_Device.h
new file mode 100644
index 00000000000..0dfa21f0660
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_Device.h
@@ -0,0 +1,258 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+#include "AUD_Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Possible distance models for the 3D device.
+typedef enum
+{
+ AUD_DISTANCE_MODEL_INVALID = 0,
+ AUD_DISTANCE_MODEL_INVERSE,
+ AUD_DISTANCE_MODEL_INVERSE_CLAMPED,
+ AUD_DISTANCE_MODEL_LINEAR,
+ AUD_DISTANCE_MODEL_LINEAR_CLAMPED,
+ AUD_DISTANCE_MODEL_EXPONENT,
+ AUD_DISTANCE_MODEL_EXPONENT_CLAMPED
+} AUD_DistanceModel;
+
+typedef void (*AUD_syncFunction)(void*, int, float);
+
+/**
+ * Opens a new sound device.
+ * \param type The name of the device.
+ * Can be NULL to open the default device with default settings or return the handle to the already opened one.
+ * Can be "" to open the a default factory device with given settings.
+ * Can be "read" to open a readable device.
+ * \param specs Specification of the device parameters.
+ * \param buffersize Size of the mixing buffer.
+ * \param name Custom name of the device.
+ * \return A handle to the opened device or NULL on failure.
+ */
+extern AUD_API AUD_Device* AUD_Device_open(const char* type, AUD_DeviceSpecs specs, int buffersize, const char* name);
+
+/**
+ * Locks the playback device.
+ */
+extern AUD_API void AUD_Device_lock(AUD_Device* device);
+
+/**
+ * Plays back a sound file.
+ * \param sound The handle of the sound file.
+ * \param keep When keep is true the sound source will not be deleted but set to
+ * paused when its end has been reached.
+ * \return A handle to the played back sound.
+ */
+extern AUD_API AUD_Handle* AUD_Device_play(AUD_Device* device, AUD_Sound* sound, int keep);
+
+/**
+ * Stops all sounds playing.
+ */
+extern AUD_API void AUD_Device_stopAll(AUD_Device* device);
+
+/**
+ * Unlocks the device.
+ */
+extern AUD_API void AUD_Device_unlock(AUD_Device* device);
+
+/**
+ * Retrieves the channels of a device.
+ * param device The device to get the channels from.
+ * return The channels of the device.
+ */
+extern AUD_API AUD_Channels AUD_Device_getChannels(AUD_Device* device);
+
+/**
+ * Retrieves the distance model of a device.
+ * param device The device to get the distance model from.
+ * return The distance model of the device.
+ */
+extern AUD_API AUD_DistanceModel AUD_Device_getDistanceModel(AUD_Device* device);
+
+/**
+ * Sets the distance model of a device.
+ * param device The device to set the distance model from.
+ * param value The new distance model to set.
+ */
+extern AUD_API void AUD_Device_setDistanceModel(AUD_Device* device, AUD_DistanceModel value);
+
+/**
+ * Retrieves the doppler factor of a device.
+ * param device The device to get the doppler factor from.
+ * return The doppler factor of the device.
+ */
+extern AUD_API float AUD_Device_getDopplerFactor(AUD_Device* device);
+
+/**
+ * Sets the doppler factor of a device.
+ * param device The device to set the doppler factor from.
+ * param value The new doppler factor to set.
+ */
+extern AUD_API void AUD_Device_setDopplerFactor(AUD_Device* device, float value);
+
+/**
+ * Retrieves the format of a device.
+ * param device The device to get the format from.
+ * return The format of the device.
+ */
+extern AUD_API AUD_SampleFormat AUD_Device_getFormat(AUD_Device* device);
+
+/**
+ * Retrieves the listener location of a device.
+ * param device The device to get the listener location from.
+ * return The listener location of the device.
+ */
+extern AUD_API void AUD_Device_getListenerLocation(AUD_Device* device, float value[3]);
+
+/**
+ * Sets the listener location of a device.
+ * param device The device to set the listener location from.
+ * param value The new listener location to set.
+ */
+extern AUD_API void AUD_Device_setListenerLocation(AUD_Device* device, const float value[3]);
+
+/**
+ * Retrieves the listener orientation of a device.
+ * param device The device to get the listener orientation from.
+ * return The listener orientation of the device.
+ */
+extern AUD_API void AUD_Device_getListenerOrientation(AUD_Device* device, float value[4]);
+
+/**
+ * Sets the listener orientation of a device.
+ * param device The device to set the listener orientation from.
+ * param value The new listener orientation to set.
+ */
+extern AUD_API void AUD_Device_setListenerOrientation(AUD_Device* device, const float value[4]);
+
+/**
+ * Retrieves the listener velocity of a device.
+ * param device The device to get the listener velocity from.
+ * return The listener velocity of the device.
+ */
+extern AUD_API void AUD_Device_getListenerVelocity(AUD_Device* device, float value[3]);
+
+/**
+ * Sets the listener velocity of a device.
+ * param device The device to set the listener velocity from.
+ * param value The new listener velocity to set.
+ */
+extern AUD_API void AUD_Device_setListenerVelocity(AUD_Device* device, const float value[3]);
+
+/**
+ * Retrieves the rate of a device.
+ * param device The device to get the rate from.
+ * return The rate of the device.
+ */
+extern AUD_API double AUD_Device_getRate(AUD_Device* device);
+
+/**
+ * Retrieves the speed of sound of a device.
+ * param device The device to get the speed of sound from.
+ * return The speed of sound of the device.
+ */
+extern AUD_API float AUD_Device_getSpeedOfSound(AUD_Device* device);
+
+/**
+ * Sets the speed of sound of a device.
+ * param device The device to set the speed of sound from.
+ * param value The new speed of sound to set.
+ */
+extern AUD_API void AUD_Device_setSpeedOfSound(AUD_Device* device, float value);
+
+/**
+ * Retrieves the volume of a device.
+ * param device The device to get the volume from.
+ * return The volume of the device.
+ */
+extern AUD_API float AUD_Device_getVolume(AUD_Device* device);
+
+/**
+ * Sets the volume of a device.
+ * param device The device to set the volume from.
+ * param value The new volume to set.
+ */
+extern AUD_API void AUD_Device_setVolume(AUD_Device* device, float value);
+
+/**
+ * Reads the next samples into the supplied buffer.
+ * \param device The readable device.
+ * \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.
+ */
+extern AUD_API int AUD_Device_read(AUD_Device* device, unsigned char* buffer, int length);
+
+/**
+ * Closes a device. Handle becomes invalid afterwards.
+ * \param device The device to close.
+ */
+extern AUD_API void AUD_Device_free(AUD_Device* device);
+
+/**
+ * Retrieves the current device of the DeviceManager.
+ * \return A pointer to the current device, which needs to be freed with
+ * AUD_Device_free.
+ */
+extern AUD_API AUD_Device* AUD_Device_getCurrent();
+
+/**
+ * Seeks sequenced sound scene playback.
+ * \param handle Playback handle.
+ * \param time Time in seconds to seek to.
+ */
+extern AUD_API void AUD_seekSynchronizer(AUD_Handle* handle, float time);
+
+/**
+ * Returns the current sound scene playback time.
+ * \param handle Playback handle.
+ * \return The playback time in seconds.
+ */
+extern AUD_API float AUD_getSynchronizerPosition(AUD_Handle* handle);
+
+/**
+ * Starts the playback of jack transport if possible.
+ */
+extern AUD_API void AUD_playSynchronizer();
+
+/**
+ * Stops the playback of jack transport if possible.
+ */
+extern AUD_API void AUD_stopSynchronizer();
+
+/**
+ * Sets the sync callback for jack transport.
+ * \param function The callback function.
+ * \param data The data parameter for the callback.
+ */
+extern AUD_API void AUD_setSynchronizerCallback(AUD_syncFunction function, void* data);
+
+/**
+ * Returns whether jack transport is currently playing.
+ * \return Whether jack transport is currently playing.
+ */
+extern AUD_API int AUD_isSynchronizerPlaying();
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/extern/audaspace/bindings/C/AUD_DynamicMusic.cpp b/extern/audaspace/bindings/C/AUD_DynamicMusic.cpp
new file mode 100644
index 00000000000..bb7a129dde3
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_DynamicMusic.cpp
@@ -0,0 +1,144 @@
+/*******************************************************************************
+* Copyright 2015-2016 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#include "Exception.h"
+
+#include <cassert>
+
+using namespace aud;
+
+#define AUD_CAPI_IMPLEMENTATION
+#include "AUD_DynamicMusic.h"
+
+AUD_API AUD_DynamicMusic* AUD_DynamicMusic_create(AUD_Device* device)
+{
+ assert(device);
+
+ try
+ {
+ return new AUD_DynamicMusic(new DynamicMusic(*device));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API void AUD_DynamicMusic_free(AUD_DynamicMusic* player)
+{
+ assert(player);
+ delete player;
+}
+
+AUD_API int AUD_DynamicMusic_addScene(AUD_DynamicMusic* player, AUD_Sound* scene)
+{
+ assert(player);
+ assert(scene);
+
+ return (*player)->addScene(*scene);
+}
+
+AUD_API int AUD_DynamicMusic_setSecene(AUD_DynamicMusic* player, int scene)
+{
+ assert(player);
+
+ return (*player)->changeScene(scene);
+}
+
+AUD_API int AUD_DynamicMusic_getScene(AUD_DynamicMusic* player)
+{
+ assert(player);
+
+ return (*player)->getScene();
+}
+
+AUD_API int AUD_DynamicMusic_addTransition(AUD_DynamicMusic* player, int ini, int end, AUD_Sound* transition)
+{
+ assert(player);
+ assert(transition);
+
+ return (*player)->addTransition(ini, end, *transition);
+}
+
+AUD_API void AUD_DynamicMusic_setFadeTime(AUD_DynamicMusic* player, float seconds)
+{
+ assert(player);
+
+ (*player)->setFadeTime(seconds);
+}
+
+AUD_API float AUD_DynamicMusic_getFadeTime(AUD_DynamicMusic* player)
+{
+ assert(player);
+
+ return (*player)->getFadeTime();
+}
+
+AUD_API int AUD_DynamicMusic_resume(AUD_DynamicMusic* player)
+{
+ assert(player);
+
+ return (*player)->resume();
+}
+
+AUD_API int AUD_DynamicMusic_pause(AUD_DynamicMusic* player)
+{
+ assert(player);
+
+ return (*player)->pause();
+}
+
+AUD_API int AUD_DynamicMusic_seek(AUD_DynamicMusic* player, float position)
+{
+ assert(player);
+
+ return (*player)->seek(position);
+}
+
+AUD_API float AUD_DynamicMusic_getPosition(AUD_DynamicMusic* player)
+{
+ assert(player);
+
+ return (*player)->getPosition();
+}
+
+AUD_API float AUD_DynamicMusic_getVolume(AUD_DynamicMusic* player)
+{
+ assert(player);
+
+ return (*player)->getVolume();
+}
+
+AUD_API int AUD_DynamicMusic_setVolume(AUD_DynamicMusic* player, float volume)
+{
+ assert(player);
+
+ return (*player)->setVolume(volume);
+}
+
+AUD_API AUD_Status AUD_DynamicMusic_getStatus(AUD_DynamicMusic* player)
+{
+ assert(player);
+
+ return static_cast<AUD_Status>((*player)->getStatus());
+}
+
+AUD_API int AUD_DynamicMusic_stop(AUD_DynamicMusic* player)
+{
+ assert(player);
+
+ return (*player)->stop();
+} \ No newline at end of file
diff --git a/extern/audaspace/bindings/C/AUD_DynamicMusic.h b/extern/audaspace/bindings/C/AUD_DynamicMusic.h
new file mode 100644
index 00000000000..c362479591e
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_DynamicMusic.h
@@ -0,0 +1,145 @@
+/*******************************************************************************
+* Copyright 2015-2016 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#pragma once
+
+#include "AUD_Types.h"
+#include "AUD_Handle.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* Creates a new dynamic music player.
+* \param device The device that will be used to play sounds.
+* \return The new DynamicMusic object.
+*/
+extern AUD_API AUD_DynamicMusic* AUD_DynamicMusic_create(AUD_Device* device);
+
+/**
+* Deletes a dynamic music player.
+* \param player The DynamicMusic object to be deleted.
+*/
+extern AUD_API void AUD_DynamicMusic_free(AUD_DynamicMusic* player);
+
+/**
+* Adds a sound scene to a dynamic music player.
+* \param player The DynamicMusic object.
+* \param scene The sound to be added as a scene.
+* \return The index of the new scene.
+*/
+extern AUD_API int AUD_DynamicMusic_addScene(AUD_DynamicMusic* player, AUD_Sound* scene);
+
+/**
+* Changes the current sound scene of a dynamic music player.
+* \param player The DynamicMusic object.
+* \param scene The index of the scene to be played.
+* \return 0 if the target scene doesn't exist.
+*/
+extern AUD_API int AUD_DynamicMusic_setSecene(AUD_DynamicMusic* player, int scene);
+
+/**
+* Retrives the index of the current scene.
+* \param player The DynamicMusic object.
+* \return The index of the current scene.
+*/
+extern AUD_API int AUD_DynamicMusic_getScene(AUD_DynamicMusic* player);
+
+/**
+* Adds a new transition between two scenes.
+* \param player The DynamicMusic object.
+* \param ini The origin scene for the transition.
+* \param end The end scene for the transition.
+* \param transition A sound that will be used as transition between two scenes.
+* \return 0 if the ini or end scenes don't exist.
+*/
+extern AUD_API int AUD_DynamicMusic_addTransition(AUD_DynamicMusic* player, int ini, int end, AUD_Sound* transition);
+
+/**
+* Changes the fade time for the default transitions of a dynamic music player.
+* \param player The DynamicMusic object.
+* \param seconds The amount of secods that the crossfade transition will take.
+*/
+extern AUD_API void AUD_DynamicMusic_setFadeTime(AUD_DynamicMusic* player, float seconds);
+
+/**
+* Retrieves the fade time of a dynamic music player.
+* \param player The DynamicMusic object.
+* \return The fade time of the player.
+*/
+extern AUD_API float AUD_DynamicMusic_getFadeTime(AUD_DynamicMusic* player);
+
+/**
+* Resumes the current scene playback of a dynamic music player if it is paused.
+* \param player The DynamicMusic object.
+* \return 0 if the playback wasn't resumed.
+*/
+extern AUD_API int AUD_DynamicMusic_resume(AUD_DynamicMusic* player);
+
+/**
+* Pauses the current scene of a dynamic music player.
+* \param player The DynamicMusic object.
+* \return 0 if the playback wasn't paused.
+*/
+extern AUD_API int AUD_DynamicMusic_pause(AUD_DynamicMusic* player);
+
+/**
+* Seeks the current playing scene of a dynamic music player.
+* \param player The DynamicMusic object.
+* \param position The new position from which to play back, in seconds.
+* \return 0 if the seeking wasn't possible.
+*/
+extern AUD_API int AUD_DynamicMusic_seek(AUD_DynamicMusic* player, float position);
+
+/**
+* Retrieves the position of the current scene of a dynamic music player.
+* \param player The DynamicMusic object.
+* \return The position of the current playing scene.
+*/
+extern AUD_API float AUD_DynamicMusic_getPosition(AUD_DynamicMusic* player);
+
+/**
+* Retrieves the volume of the current scene of a dynamic music player.
+* \param player The DynamicMusic object.
+* \return The volume of the current playing scene.
+*/
+extern AUD_API float AUD_DynamicMusic_getVolume(AUD_DynamicMusic* player);
+
+/**
+* Changes the volume of the current scene in a dynamic music player.
+* \param player The DynamicMusic object.
+* \param 0 if the volume couldn't be changed.
+*/
+extern AUD_API int AUD_DynamicMusic_setVolume(AUD_DynamicMusic* player, float volume);
+
+/**
+* Retrieves the status of the current scene in a dynamic music player.
+* \param player The DynamicMusic object.
+* \return The Status of the current playing scene.
+*/
+extern AUD_API AUD_Status AUD_DynamicMusic_getStatus(AUD_DynamicMusic* player);
+
+/**
+* Stops the current scene of a dynamic music player.
+* \param player The DynamicMusic object.
+* \return 0 if the playback wasn't stopped.
+*/
+extern AUD_API int AUD_DynamicMusic_stop(AUD_DynamicMusic* player);
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/extern/audaspace/bindings/C/AUD_HRTF.cpp b/extern/audaspace/bindings/C/AUD_HRTF.cpp
new file mode 100644
index 00000000000..002c5d61ddd
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_HRTF.cpp
@@ -0,0 +1,50 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#include "Exception.h"
+
+#include <cassert>
+
+using namespace aud;
+
+#define AUD_CAPI_IMPLEMENTATION
+#include "AUD_HRTF.h"
+
+extern AUD_API AUD_HRTF* AUD_HRTF_create()
+{
+ try
+ {
+ return new AUD_HRTF(new HRTF());
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+extern AUD_API void AUD_HRTF_free(AUD_HRTF* hrtfs)
+{
+ assert(hrtfs);
+ delete hrtfs;
+}
+
+extern AUD_API void AUD_HRTF_addImpulseResponseFromSound(AUD_HRTF* hrtfs, AUD_Sound* sound, float azimuth, float elevation)
+{
+ assert(hrtfs);
+ assert(sound);
+
+ (*hrtfs)->addImpulseResponse(std::make_shared<StreamBuffer>(*sound), azimuth, elevation);
+} \ No newline at end of file
diff --git a/extern/audaspace/bindings/C/AUD_HRTF.h b/extern/audaspace/bindings/C/AUD_HRTF.h
new file mode 100644
index 00000000000..29dda371695
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_HRTF.h
@@ -0,0 +1,48 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#pragma once
+
+#include "AUD_Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* Creates a new HRTF object.
+* \return The new HRTF object.
+*/
+extern AUD_API AUD_HRTF* AUD_HRTF_create();
+
+/**
+* Deletes a HRTF object.
+* \param hrtfs The HRTF object to be deleted.
+*/
+extern AUD_API void AUD_HRTF_free(AUD_HRTF* hrtfs);
+
+/**
+* Adds a new impulse response to an HRTF object.
+* \param hrtfs The HRTF object.
+* \param sound A Sound object representing an HRTF.
+* \param azimuth The azimuth angle of the HRTF.
+* \param elevation The elevation angle of the HRTF.
+*/
+extern AUD_API void AUD_HRTF_addImpulseResponseFromSound(AUD_HRTF* hrtfs, AUD_Sound* sound, float azimuth, float elevation);
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/extern/audaspace/bindings/C/AUD_Handle.cpp b/extern/audaspace/bindings/C/AUD_Handle.cpp
new file mode 100644
index 00000000000..265c7bf08d2
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_Handle.cpp
@@ -0,0 +1,384 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#include "devices/I3DHandle.h"
+#include "Exception.h"
+
+#include <cassert>
+
+using namespace aud;
+
+#define AUD_CAPI_IMPLEMENTATION
+#include "AUD_Handle.h"
+
+AUD_API int AUD_Handle_pause(AUD_Handle* handle)
+{
+ assert(handle);
+ return (*handle)->pause();
+}
+
+AUD_API int AUD_Handle_resume(AUD_Handle* handle)
+{
+ assert(handle);
+ return (*handle)->resume();
+}
+
+AUD_API int AUD_Handle_stop(AUD_Handle* handle)
+{
+ assert(handle);
+ int result = (*handle)->stop();
+ delete handle;
+ return result;
+}
+
+AUD_API float AUD_Handle_getAttenuation(AUD_Handle* handle)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->getAttenuation();
+ return 0.0f;
+}
+
+AUD_API int AUD_Handle_setAttenuation(AUD_Handle* handle, float value)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->setAttenuation(value);
+ return false;
+}
+
+AUD_API float AUD_Handle_getConeAngleInner(AUD_Handle* handle)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->getConeAngleInner();
+ return 0.0f;
+}
+
+AUD_API int AUD_Handle_setConeAngleInner(AUD_Handle* handle, float value)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->setConeAngleInner(value);
+ return false;
+}
+
+AUD_API float AUD_Handle_getConeAngleOuter(AUD_Handle* handle)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->getConeAngleOuter();
+ return 0.0f;
+}
+
+AUD_API int AUD_Handle_setConeAngleOuter(AUD_Handle* handle, float value)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->setConeAngleOuter(value);
+ return false;
+}
+
+AUD_API float AUD_Handle_getConeVolumeOuter(AUD_Handle* handle)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->getConeVolumeOuter();
+ return 0.0f;
+}
+
+AUD_API int AUD_Handle_setConeVolumeOuter(AUD_Handle* handle, float value)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->setConeVolumeOuter(value);
+ return false;
+}
+
+AUD_API float AUD_Handle_getDistanceMaximum(AUD_Handle* handle)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->getDistanceMaximum();
+ return 0.0f;
+}
+
+AUD_API int AUD_Handle_setDistanceMaximum(AUD_Handle* handle, float value)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->setDistanceMaximum(value);
+ return false;
+}
+
+AUD_API float AUD_Handle_getDistanceReference(AUD_Handle* handle)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->getDistanceReference();
+ return 0.0f;
+}
+
+AUD_API int AUD_Handle_setDistanceReference(AUD_Handle* handle, float value)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->setDistanceReference(value);
+ return false;
+}
+
+AUD_API int AUD_Handle_doesKeep(AUD_Handle* handle)
+{
+ assert(handle);
+ return (*handle)->getKeep();
+}
+
+AUD_API int AUD_Handle_setKeep(AUD_Handle* handle, int value)
+{
+ assert(handle);
+ return (*handle)->setKeep(value);
+}
+
+AUD_API int AUD_Handle_getLocation(AUD_Handle* handle, float value[3])
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ {
+ Vector3 v = h->getLocation();
+ value[0] = v.x();
+ value[1] = v.y();
+ value[2] = v.z();
+ return true;
+ }
+ return false;
+}
+
+AUD_API int AUD_Handle_setLocation(AUD_Handle* handle, const float value[3])
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ {
+ Vector3 v = Vector3(value[0], value[1], value[2]);
+ return h->setLocation(v);
+ }
+ return false;
+}
+
+AUD_API int AUD_Handle_getLoopCount(AUD_Handle* handle)
+{
+ assert(handle);
+ return (*handle)->getLoopCount();
+}
+
+AUD_API int AUD_Handle_setLoopCount(AUD_Handle* handle, int value)
+{
+ assert(handle);
+ return (*handle)->setLoopCount(value);
+}
+
+AUD_API int AUD_Handle_getOrientation(AUD_Handle* handle, float value[4])
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ {
+ Quaternion v = h->getOrientation();
+ value[0] = v.x();
+ value[1] = v.y();
+ value[2] = v.z();
+ value[3] = v.w();
+ return true;
+ }
+ return false;
+}
+
+AUD_API int AUD_Handle_setOrientation(AUD_Handle* handle, const float value[4])
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ {
+ Quaternion v(value[3], value[0], value[1], value[2]);
+ return h->setOrientation(v);
+ }
+ return false;
+}
+
+AUD_API float AUD_Handle_getPitch(AUD_Handle* handle)
+{
+ assert(handle);
+ return (*handle)->getPitch();
+}
+
+AUD_API int AUD_Handle_setPitch(AUD_Handle* handle, float value)
+{
+ assert(handle);
+ return (*handle)->setPitch(value);
+}
+
+AUD_API float AUD_Handle_getPosition(AUD_Handle* handle)
+{
+ assert(handle);
+ return (*handle)->getPosition();
+}
+
+AUD_API int AUD_Handle_setPosition(AUD_Handle* handle, float value)
+{
+ assert(handle);
+ return (*handle)->seek(value);
+}
+
+AUD_API int AUD_Handle_isRelative(AUD_Handle* handle)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->isRelative();
+ return true;
+}
+
+AUD_API int AUD_Handle_setRelative(AUD_Handle* handle, int value)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->setRelative(value);
+ return false;
+}
+
+AUD_API AUD_Status AUD_Handle_getStatus(AUD_Handle* handle)
+{
+ assert(handle);
+ return static_cast<AUD_Status>((*handle)->getStatus());
+}
+
+AUD_API int AUD_Handle_getVelocity(AUD_Handle* handle, float value[3])
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ {
+ Vector3 v = h->getVelocity();
+ value[0] = v.x();
+ value[1] = v.y();
+ value[2] = v.z();
+ return true;
+ }
+ return false;
+}
+
+AUD_API int AUD_Handle_setVelocity(AUD_Handle* handle, const float value[3])
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ {
+ Vector3 v = Vector3(value[0], value[1], value[2]);
+ return h->setVelocity(v);
+ }
+ return false;
+}
+
+AUD_API float AUD_Handle_getVolume(AUD_Handle* handle)
+{
+ assert(handle);
+ return (*handle)->getVolume();
+}
+
+AUD_API int AUD_Handle_setVolume(AUD_Handle* handle, float value)
+{
+ assert(handle);
+ return (*handle)->setVolume(value);
+}
+
+AUD_API float AUD_Handle_getVolumeMaximum(AUD_Handle* handle)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->getVolumeMaximum();
+ return 0.0f;
+}
+
+AUD_API int AUD_Handle_setVolumeMaximum(AUD_Handle* handle, float value)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->setVolumeMaximum(value);
+ return false;
+}
+
+AUD_API float AUD_Handle_getVolumeMinimum(AUD_Handle* handle)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->getVolumeMinimum();
+ return 0.0f;
+}
+
+AUD_API int AUD_Handle_setVolumeMinimum(AUD_Handle* handle, float value)
+{
+ assert(handle);
+ std::shared_ptr<I3DHandle> h = std::dynamic_pointer_cast<I3DHandle>(*handle);
+
+ if(h.get())
+ return h->setVolumeMinimum(value);
+ return false;
+}
+
+AUD_API void AUD_Handle_free(AUD_Handle* handle)
+{
+ delete handle;
+}
diff --git a/extern/audaspace/bindings/C/AUD_Handle.h b/extern/audaspace/bindings/C/AUD_Handle.h
new file mode 100644
index 00000000000..27cbd251de5
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_Handle.h
@@ -0,0 +1,308 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+#include "AUD_Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Status of a playback handle.
+typedef enum
+{
+ AUD_STATUS_INVALID = 0, /// Invalid handle. Maybe due to stopping.
+ AUD_STATUS_PLAYING, /// Sound is playing.
+ AUD_STATUS_PAUSED, /// Sound is being paused.
+ AUD_STATUS_STOPPED /// Sound is stopped but kept in the device.
+} AUD_Status;
+
+/**
+ * Pauses a played back sound.
+ * \param handle The handle to the sound.
+ * \return Whether the handle has been playing or not.
+ */
+extern AUD_API int AUD_Handle_pause(AUD_Handle* handle);
+
+/**
+ * Resumes a paused sound.
+ * \param handle The handle to the sound.
+ * \return Whether the handle has been paused or not.
+ */
+extern AUD_API int AUD_Handle_resume(AUD_Handle* handle);
+
+/**
+ * Stops a playing or paused sound.
+ * \param handle The handle to the sound.
+ * \return Whether the handle has been valid or not.
+ */
+extern AUD_API int AUD_Handle_stop(AUD_Handle* handle);
+
+/**
+ * Retrieves the attenuation of a handle.
+ * param handle The handle to get the attenuation from.
+ * return The attenuation of the handle.
+ */
+extern AUD_API float AUD_Handle_getAttenuation(AUD_Handle* handle);
+
+/**
+ * Sets the attenuation of a handle.
+ * param handle The handle to set the attenuation from.
+ * param value The new attenuation to set.
+ */
+extern AUD_API int AUD_Handle_setAttenuation(AUD_Handle* handle, float value);
+
+/**
+ * Retrieves the cone angle inner of a handle.
+ * param handle The handle to get the cone angle inner from.
+ * return The cone angle inner of the handle.
+ */
+extern AUD_API float AUD_Handle_getConeAngleInner(AUD_Handle* handle);
+
+/**
+ * Sets the cone angle inner of a handle.
+ * param handle The handle to set the cone angle inner from.
+ * param value The new cone angle inner to set.
+ */
+extern AUD_API int AUD_Handle_setConeAngleInner(AUD_Handle* handle, float value);
+
+/**
+ * Retrieves the cone angle outer of a handle.
+ * param handle The handle to get the cone angle outer from.
+ * return The cone angle outer of the handle.
+ */
+extern AUD_API float AUD_Handle_getConeAngleOuter(AUD_Handle* handle);
+
+/**
+ * Sets the cone angle outer of a handle.
+ * param handle The handle to set the cone angle outer from.
+ * param value The new cone angle outer to set.
+ */
+extern AUD_API int AUD_Handle_setConeAngleOuter(AUD_Handle* handle, float value);
+
+/**
+ * Retrieves the cone volume outer of a handle.
+ * param handle The handle to get the cone volume outer from.
+ * return The cone volume outer of the handle.
+ */
+extern AUD_API float AUD_Handle_getConeVolumeOuter(AUD_Handle* handle);
+
+/**
+ * Sets the cone volume outer of a handle.
+ * param handle The handle to set the cone volume outer from.
+ * param value The new cone volume outer to set.
+ */
+extern AUD_API int AUD_Handle_setConeVolumeOuter(AUD_Handle* handle, float value);
+
+/**
+ * Retrieves the distance maximum of a handle.
+ * param handle The handle to get the distance maximum from.
+ * return The distance maximum of the handle.
+ */
+extern AUD_API float AUD_Handle_getDistanceMaximum(AUD_Handle* handle);
+
+/**
+ * Sets the distance maximum of a handle.
+ * param handle The handle to set the distance maximum from.
+ * param value The new distance maximum to set.
+ */
+extern AUD_API int AUD_Handle_setDistanceMaximum(AUD_Handle* handle, float value);
+
+/**
+ * Retrieves the distance reference of a handle.
+ * param handle The handle to get the distance reference from.
+ * return The distance reference of the handle.
+ */
+extern AUD_API float AUD_Handle_getDistanceReference(AUD_Handle* handle);
+
+/**
+ * Sets the distance reference of a handle.
+ * param handle The handle to set the distance reference from.
+ * param value The new distance reference to set.
+ */
+extern AUD_API int AUD_Handle_setDistanceReference(AUD_Handle* handle, float value);
+
+/**
+ * Retrieves the keep of a handle.
+ * param handle The handle to get the keep from.
+ * return The keep of the handle.
+ */
+extern AUD_API int AUD_Handle_doesKeep(AUD_Handle* handle);
+
+/**
+ * Sets the keep of a handle.
+ * param handle The handle to set the keep from.
+ * param value The new keep to set.
+ */
+extern AUD_API int AUD_Handle_setKeep(AUD_Handle* handle, int value);
+
+/**
+ * Retrieves the location of a handle.
+ * param handle The handle to get the location from.
+ * return The location of the handle.
+ */
+extern AUD_API int AUD_Handle_getLocation(AUD_Handle* handle, float value[3]);
+
+/**
+ * Sets the location of a handle.
+ * param handle The handle to set the location from.
+ * param value The new location to set.
+ */
+extern AUD_API int AUD_Handle_setLocation(AUD_Handle* handle, const float value[3]);
+
+/**
+ * Retrieves the loop count of a handle.
+ * param handle The handle to get the loop count from.
+ * return The loop count of the handle.
+ */
+extern AUD_API int AUD_Handle_getLoopCount(AUD_Handle* handle);
+
+/**
+ * Sets the loop count of a handle.
+ * param handle The handle to set the loop count from.
+ * param value The new loop count to set.
+ */
+extern AUD_API int AUD_Handle_setLoopCount(AUD_Handle* handle, int value);
+
+/**
+ * Retrieves the orientation of a handle.
+ * param handle The handle to get the orientation from.
+ * return The orientation of the handle.
+ */
+extern AUD_API int AUD_Handle_getOrientation(AUD_Handle* handle, float value[4]);
+
+/**
+ * Sets the orientation of a handle.
+ * param handle The handle to set the orientation from.
+ * param value The new orientation to set.
+ */
+extern AUD_API int AUD_Handle_setOrientation(AUD_Handle* handle, const float value[4]);
+
+/**
+ * Retrieves the pitch of a handle.
+ * param handle The handle to get the pitch from.
+ * return The pitch of the handle.
+ */
+extern AUD_API float AUD_Handle_getPitch(AUD_Handle* handle);
+
+/**
+ * Sets the pitch of a handle.
+ * param handle The handle to set the pitch from.
+ * param value The new pitch to set.
+ */
+extern AUD_API int AUD_Handle_setPitch(AUD_Handle* handle, float value);
+
+/**
+ * Retrieves the position of a handle.
+ * param handle The handle to get the position from.
+ * return The position of the handle.
+ */
+extern AUD_API float AUD_Handle_getPosition(AUD_Handle* handle);
+
+/**
+ * Sets the position of a handle.
+ * param handle The handle to set the position from.
+ * param value The new position to set.
+ */
+extern AUD_API int AUD_Handle_setPosition(AUD_Handle* handle, float value);
+
+/**
+ * Retrieves the relative of a handle.
+ * param handle The handle to get the relative from.
+ * return The relative of the handle.
+ */
+extern AUD_API int AUD_Handle_isRelative(AUD_Handle* handle);
+
+/**
+ * Sets the relative of a handle.
+ * param handle The handle to set the relative from.
+ * param value The new relative to set.
+ */
+extern AUD_API int AUD_Handle_setRelative(AUD_Handle* handle, int value);
+
+/**
+ * Retrieves the status of a handle.
+ * param handle The handle to get the status from.
+ * return The status of the handle.
+ */
+extern AUD_API AUD_Status AUD_Handle_getStatus(AUD_Handle* handle);
+
+/**
+ * Retrieves the velocity of a handle.
+ * param handle The handle to get the velocity from.
+ * return The velocity of the handle.
+ */
+extern AUD_API int AUD_Handle_getVelocity(AUD_Handle* handle, float value[3]);
+
+/**
+ * Sets the velocity of a handle.
+ * param handle The handle to set the velocity from.
+ * param value The new velocity to set.
+ */
+extern AUD_API int AUD_Handle_setVelocity(AUD_Handle* handle, const float value[3]);
+
+/**
+ * Retrieves the volume of a handle.
+ * param handle The handle to get the volume from.
+ * return The volume of the handle.
+ */
+extern AUD_API float AUD_Handle_getVolume(AUD_Handle* handle);
+
+/**
+ * Sets the volume of a handle.
+ * param handle The handle to set the volume from.
+ * param value The new volume to set.
+ */
+extern AUD_API int AUD_Handle_setVolume(AUD_Handle* handle, float value);
+
+/**
+ * Retrieves the volume maximum of a handle.
+ * param handle The handle to get the volume maximum from.
+ * return The volume maximum of the handle.
+ */
+extern AUD_API float AUD_Handle_getVolumeMaximum(AUD_Handle* handle);
+
+/**
+ * Sets the volume maximum of a handle.
+ * param handle The handle to set the volume maximum from.
+ * param value The new volume maximum to set.
+ */
+extern AUD_API int AUD_Handle_setVolumeMaximum(AUD_Handle* handle, float value);
+
+/**
+ * Retrieves the volume minimum of a handle.
+ * param handle The handle to get the volume minimum from.
+ * return The volume minimum of the handle.
+ */
+extern AUD_API float AUD_Handle_getVolumeMinimum(AUD_Handle* handle);
+
+/**
+ * Sets the volume minimum of a handle.
+ * param handle The handle to set the volume minimum from.
+ * param value The new volume minimum to set.
+ */
+extern AUD_API int AUD_Handle_setVolumeMinimum(AUD_Handle* handle, float value);
+
+/**
+ * Frees a handle.
+ * \param channel Handle to free.
+ */
+extern AUD_API void AUD_Handle_free(AUD_Handle* channel);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/extern/audaspace/bindings/C/AUD_ImpulseResponse.cpp b/extern/audaspace/bindings/C/AUD_ImpulseResponse.cpp
new file mode 100644
index 00000000000..f3c28d4d660
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_ImpulseResponse.cpp
@@ -0,0 +1,44 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#include "Exception.h"
+
+#include <cassert>
+
+using namespace aud;
+
+#define AUD_CAPI_IMPLEMENTATION
+#include "AUD_ImpulseResponse.h"
+
+AUD_API AUD_ImpulseResponse* AUD_ImpulseResponse_create(AUD_Sound* sound)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_ImpulseResponse(new ImpulseResponse(std::make_shared<StreamBuffer>(*sound)));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API void AUD_ImpulseResponse_free(AUD_ImpulseResponse* filter)
+{
+ assert(filter);
+ delete filter;
+} \ No newline at end of file
diff --git a/extern/audaspace/bindings/C/AUD_ImpulseResponse.h b/extern/audaspace/bindings/C/AUD_ImpulseResponse.h
new file mode 100644
index 00000000000..dad2e87e899
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_ImpulseResponse.h
@@ -0,0 +1,40 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#pragma once
+
+#include "AUD_Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* Creates a new ImpulseResponse object.
+* \param sound A Sound object representing a impulse response.
+* \return The new ImpulseResponse object.
+*/
+extern AUD_API AUD_ImpulseResponse* AUD_ImpulseResponse_create(AUD_Sound* sound);
+
+/**
+* Deletes a ImpulseResponse object.
+* \param threadPool The ImpulseResponse object to be deleted.
+*/
+extern AUD_API void AUD_ImpulseResponse_free(AUD_ImpulseResponse* filter);
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/extern/audaspace/bindings/C/AUD_PlaybackManager.cpp b/extern/audaspace/bindings/C/AUD_PlaybackManager.cpp
new file mode 100644
index 00000000000..69ecb0987e1
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_PlaybackManager.cpp
@@ -0,0 +1,94 @@
+/*******************************************************************************
+* Copyright 2015-2016 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#include "Exception.h"
+
+#include <cassert>
+
+using namespace aud;
+
+#define AUD_CAPI_IMPLEMENTATION
+#include "AUD_PlaybackManager.h"
+
+AUD_API AUD_PlaybackManager* AUD_PlaybackManager_create(AUD_Device* device)
+{
+ assert(device);
+
+ try
+ {
+ return new AUD_PlaybackManager(new PlaybackManager(*device));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API void AUD_PlaybackManager_free(AUD_PlaybackManager* manager)
+{
+ assert(manager);
+ delete manager;
+}
+
+AUD_API void AUD_PlaybackManager_play(AUD_PlaybackManager* manager, AUD_Sound* sound, unsigned int catKey)
+{
+ assert(manager);
+ assert(sound);
+
+ (*manager)->play(*sound, catKey);
+}
+
+AUD_API int AUD_PlaybackManager_resume(AUD_PlaybackManager* manager, unsigned int catKey)
+{
+ assert(manager);
+ return (*manager)->resume(catKey);
+}
+
+AUD_API int AUD_PlaybackManager_pause(AUD_PlaybackManager* manager, unsigned int catKey)
+{
+ assert(manager);
+ return (*manager)->pause(catKey);
+}
+
+AUD_API unsigned int AUD_PlaybackManager_addCategory(AUD_PlaybackManager* manager, float volume)
+{
+ assert(manager);
+ return (*manager)->addCategory(volume);
+}
+
+AUD_API float AUD_PlaybackManager_getVolume(AUD_PlaybackManager* manager, unsigned int catKey)
+{
+ assert(manager);
+ return (*manager)->getVolume(catKey);
+}
+
+AUD_API int AUD_PlaybackManager_setVolume(AUD_PlaybackManager* manager, float volume, unsigned int catKey)
+{
+ assert(manager);
+ return (*manager)->setVolume(volume, catKey);
+}
+
+AUD_API int AUD_PlaybackManager_stop(AUD_PlaybackManager* manager, unsigned int catKey)
+{
+ assert(manager);
+ return (*manager)->stop(catKey);
+}
+
+AUD_API void AUD_PlaybackManager_clean(AUD_PlaybackManager* manager)
+{
+ assert(manager);
+ (*manager)->clean();
+}
diff --git a/extern/audaspace/bindings/C/AUD_PlaybackManager.h b/extern/audaspace/bindings/C/AUD_PlaybackManager.h
new file mode 100644
index 00000000000..0fa8171599d
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_PlaybackManager.h
@@ -0,0 +1,103 @@
+/*******************************************************************************
+* Copyright 2015-2016 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#pragma once
+
+#include "AUD_Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* Creates a new PlaybackManager object.
+* \param device The device that will be used to play sounds.
+* \return The new PlaybackManager object.
+*/
+extern AUD_API AUD_PlaybackManager* AUD_PlaybackManager_create(AUD_Device* device);
+
+/**
+* Deletes a PlaybackManager object.
+* \param manager The PlaybackManager object to be deleted.
+*/
+extern AUD_API void AUD_PlaybackManager_free(AUD_PlaybackManager* manager);
+
+/**
+* Plays a sound through the playback manager, adding it into a category.
+* \param manager The PlaybackManager object.
+* \param sound The sound to be played.
+* \param catKey The key of the category into which the sound will be added. If it doesn't exist a new one will be creatd.
+*/
+extern AUD_API void AUD_PlaybackManager_play(AUD_PlaybackManager* manager, AUD_Sound* sound, unsigned int catKey);
+
+/**
+* Resumes the playback of all the paused sounds assigned to a category of a playback manager.
+* \param manager The PlaybackManager object.
+* \param catKey The key of the category.
+* \return 0 if the category doesn't exist.
+*/
+extern AUD_API int AUD_PlaybackManager_resume(AUD_PlaybackManager* manager, unsigned int catKey);
+
+/**
+* Pauses all the sounds assigned to a category of a playback manager.
+* \param manager The PlaybackManager object.
+* \param catKey The key of the category.
+* \return 0 if the category doesn't exist.
+*/
+extern AUD_API int AUD_PlaybackManager_pause(AUD_PlaybackManager* manager, unsigned int catKey);
+
+/**
+* Adds a new category with a custom volume.
+* \param manager The PlaybackManager object.
+* \param volume The volume value.
+* \return The key of the new category.
+*/
+extern AUD_API unsigned int AUD_PlaybackManager_addCategory(AUD_PlaybackManager* manager, float volume);
+
+/**
+* Retrieves the volume of a category of a playback manager.
+* \param manager The PlaybackManager object.
+* \param catKey The key of the category.
+* \return The volume of the category.
+*/
+extern AUD_API float AUD_PlaybackManager_getVolume(AUD_PlaybackManager* manager, unsigned int catKey);
+
+/**
+* Changes the voulume of a category of a playback manager.
+* \param manager The PlaybackManager object.
+* \param volume The new volume of the category.
+* \param catKey The key of the category.
+* \return 0 if the category doesn't exist.
+*/
+extern AUD_API int AUD_PlaybackManager_setVolume(AUD_PlaybackManager* manager, float volume, unsigned int catKey);
+
+/**
+* Stops all the sounds assigned to a category of a playback manager.
+* \param manager The PlaybackManager object.
+* \param catKey The key of the category.
+* \return 0 if the category doesn't exist.
+*/
+extern AUD_API int AUD_PlaybackManager_stop(AUD_PlaybackManager* manager, unsigned int catKey);
+
+/**
+* Cleans all the invalid handles in a playback manager
+* \param manager The PlaybackManager object.
+*/
+extern AUD_API void AUD_PlaybackManager_clean(AUD_PlaybackManager* manager);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/extern/audaspace/bindings/C/AUD_Sequence.cpp b/extern/audaspace/bindings/C/AUD_Sequence.cpp
new file mode 100644
index 00000000000..d278cb148a1
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_Sequence.cpp
@@ -0,0 +1,315 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#include "devices/I3DDevice.h"
+#include "devices/DeviceManager.h"
+#include "sequence/Sequence.h"
+#include "Exception.h"
+
+#include <cassert>
+
+using namespace aud;
+
+#define AUD_CAPI_IMPLEMENTATION
+#include "AUD_Sequence.h"
+
+AUD_API AUD_Sound* AUD_Sequence_create(float fps, int muted)
+{
+ // specs are changed at a later point!
+ Specs specs;
+ specs.channels = CHANNELS_STEREO;
+ specs.rate = RATE_48000;
+ AUD_Sound* sequence = new AUD_Sound(std::shared_ptr<Sequence>(new Sequence(specs, fps, muted)));
+ return sequence;
+}
+
+AUD_API void AUD_Sequence_free(AUD_Sound* sequence)
+{
+ delete sequence;
+}
+
+AUD_API AUD_SequenceEntry* AUD_Sequence_add(AUD_Sound* sequence, AUD_Sound* sound, float begin, float end, float skip)
+{
+ if(!sound)
+ return new AUD_SequenceEntry(((Sequence *)sequence->get())->add(AUD_Sound(), begin, end, skip));
+ return new AUD_SequenceEntry(((Sequence *)sequence->get())->add(*sound, begin, end, skip));
+}
+
+AUD_API void AUD_Sequence_remove(AUD_Sound* sequence, AUD_SequenceEntry* entry)
+{
+ dynamic_cast<Sequence *>(sequence->get())->remove(*entry);
+ delete entry;
+}
+
+AUD_API void AUD_Sequence_setAnimationData(AUD_Sound* sequence, AUD_AnimateablePropertyType type, int frame, float* data, char animated)
+{
+ AnimateableProperty* prop = dynamic_cast<Sequence *>(sequence->get())->getAnimProperty(static_cast<AnimateablePropertyType>(type));
+ if(animated)
+ {
+ if(frame >= 0)
+ {
+ prop->write(data, frame, 1);
+ }
+ }
+ else
+ {
+ prop->write(data);
+ }
+}
+
+AUD_API AUD_DistanceModel AUD_Sequence_getDistanceModel(AUD_Sound* sequence)
+{
+ assert(sequence);
+ return static_cast<AUD_DistanceModel>(dynamic_cast<Sequence *>(sequence->get())->getDistanceModel());
+}
+
+AUD_API void AUD_Sequence_setDistanceModel(AUD_Sound* sequence, AUD_DistanceModel value)
+{
+ assert(sequence);
+ dynamic_cast<Sequence *>(sequence->get())->setDistanceModel(static_cast<DistanceModel>(value));
+}
+
+AUD_API float AUD_Sequence_getDopplerFactor(AUD_Sound* sequence)
+{
+ assert(sequence);
+ return dynamic_cast<Sequence *>(sequence->get())->getDopplerFactor();
+}
+
+AUD_API void AUD_Sequence_setDopplerFactor(AUD_Sound* sequence, float value)
+{
+ assert(sequence);
+ dynamic_cast<Sequence *>(sequence->get())->setDopplerFactor(value);
+}
+
+AUD_API float AUD_Sequence_getFPS(AUD_Sound* sequence)
+{
+ assert(sequence);
+ return dynamic_cast<Sequence *>(sequence->get())->getFPS();
+}
+
+AUD_API void AUD_Sequence_setFPS(AUD_Sound* sequence, float value)
+{
+ assert(sequence);
+ dynamic_cast<Sequence *>(sequence->get())->setFPS(value);
+}
+
+AUD_API int AUD_Sequence_isMuted(AUD_Sound* sequence)
+{
+ assert(sequence);
+ return dynamic_cast<Sequence *>(sequence->get())->isMuted();
+}
+
+AUD_API void AUD_Sequence_setMuted(AUD_Sound* sequence, int value)
+{
+ assert(sequence);
+ dynamic_cast<Sequence *>(sequence->get())->mute(value);
+}
+
+static inline AUD_Specs convSpecToC(aud::Specs specs)
+{
+ AUD_Specs s;
+ s.channels = static_cast<AUD_Channels>(specs.channels);
+ s.rate = static_cast<AUD_SampleRate>(specs.rate);
+ return s;
+}
+
+static inline aud::Specs convCToSpec(AUD_Specs specs)
+{
+ aud::Specs s;
+ s.channels = static_cast<Channels>(specs.channels);
+ s.rate = static_cast<SampleRate>(specs.rate);
+ return s;
+}
+
+AUD_API AUD_Specs AUD_Sequence_getSpecs(AUD_Sound* sequence)
+{
+ assert(sequence);
+ return convSpecToC(dynamic_cast<Sequence *>(sequence->get())->getSpecs());
+}
+
+AUD_API void AUD_Sequence_setSpecs(AUD_Sound* sequence, AUD_Specs value)
+{
+ assert(sequence);
+ dynamic_cast<Sequence *>(sequence->get())->setSpecs(convCToSpec(value));
+}
+
+AUD_API float AUD_Sequence_getSpeedOfSound(AUD_Sound* sequence)
+{
+ assert(sequence);
+ return dynamic_cast<Sequence *>(sequence->get())->getSpeedOfSound();
+}
+
+AUD_API void AUD_Sequence_setSpeedOfSound(AUD_Sound* sequence, float value)
+{
+ assert(sequence);
+ dynamic_cast<Sequence *>(sequence->get())->setSpeedOfSound(value);
+}
+
+
+
+AUD_API void AUD_SequenceEntry_move(AUD_SequenceEntry* entry, float begin, float end, float skip)
+{
+ (*entry)->move(begin, end, skip);
+}
+
+AUD_API void AUD_SequenceEntry_setAnimationData(AUD_SequenceEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated)
+{
+ AnimateableProperty* prop = (*entry)->getAnimProperty(static_cast<AnimateablePropertyType>(type));
+ if(animated)
+ {
+ if(frame >= 0)
+ prop->write(data, frame, 1);
+ }
+ else
+ {
+ prop->write(data);
+ }
+}
+
+AUD_API float AUD_SequenceEntry_getAttenuation(AUD_SequenceEntry* sequence_entry)
+{
+ assert(sequence_entry);
+ return (*sequence_entry)->getAttenuation();
+}
+
+AUD_API void AUD_SequenceEntry_setAttenuation(AUD_SequenceEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setAttenuation(value);
+}
+
+AUD_API float AUD_SequenceEntry_getConeAngleInner(AUD_SequenceEntry* sequence_entry)
+{
+ assert(sequence_entry);
+ return (*sequence_entry)->getConeAngleInner();
+}
+
+AUD_API void AUD_SequenceEntry_setConeAngleInner(AUD_SequenceEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setConeAngleInner(value);
+}
+
+AUD_API float AUD_SequenceEntry_getConeAngleOuter(AUD_SequenceEntry* sequence_entry)
+{
+ assert(sequence_entry);
+ return (*sequence_entry)->getConeAngleOuter();
+}
+
+AUD_API void AUD_SequenceEntry_setConeAngleOuter(AUD_SequenceEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setConeAngleOuter(value);
+}
+
+AUD_API float AUD_SequenceEntry_getConeVolumeOuter(AUD_SequenceEntry* sequence_entry)
+{
+ assert(sequence_entry);
+ return (*sequence_entry)->getConeVolumeOuter();
+}
+
+AUD_API void AUD_SequenceEntry_setConeVolumeOuter(AUD_SequenceEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setConeVolumeOuter(value);
+}
+
+AUD_API float AUD_SequenceEntry_getDistanceMaximum(AUD_SequenceEntry* sequence_entry)
+{
+ assert(sequence_entry);
+ return (*sequence_entry)->getDistanceMaximum();
+}
+
+AUD_API void AUD_SequenceEntry_setDistanceMaximum(AUD_SequenceEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setDistanceMaximum(value);
+}
+
+AUD_API float AUD_SequenceEntry_getDistanceReference(AUD_SequenceEntry* sequence_entry)
+{
+ assert(sequence_entry);
+ return (*sequence_entry)->getDistanceReference();
+}
+
+AUD_API void AUD_SequenceEntry_setDistanceReference(AUD_SequenceEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setDistanceReference(value);
+}
+
+AUD_API int AUD_SequenceEntry_isMuted(AUD_SequenceEntry* sequence_entry)
+{
+ assert(sequence_entry);
+ return (*sequence_entry)->isMuted();
+}
+
+AUD_API void AUD_SequenceEntry_setMuted(AUD_SequenceEntry* sequence_entry, int value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->mute(value);
+}
+
+AUD_API int AUD_SequenceEntry_isRelative(AUD_SequenceEntry* sequence_entry)
+{
+ assert(sequence_entry);
+ return (*sequence_entry)->isRelative();
+}
+
+AUD_API void AUD_SequenceEntry_setRelative(AUD_SequenceEntry* sequence_entry, int value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setRelative(value);
+}
+
+AUD_API AUD_Sound* AUD_SequenceEntry_getSound(AUD_SequenceEntry* sequence_entry)
+{
+ assert(sequence_entry);
+ return new std::shared_ptr<ISound>((*sequence_entry)->getSound());
+}
+
+AUD_API void AUD_SequenceEntry_setSound(AUD_SequenceEntry* sequence_entry, AUD_Sound* value)
+{
+ assert(sequence_entry);
+ if(value)
+ (*sequence_entry)->setSound(*value);
+ else
+ (*sequence_entry)->setSound(AUD_Sound());
+}
+
+AUD_API float AUD_SequenceEntry_getVolumeMaximum(AUD_SequenceEntry* sequence_entry)
+{
+ assert(sequence_entry);
+ return (*sequence_entry)->getVolumeMaximum();
+}
+
+AUD_API void AUD_SequenceEntry_setVolumeMaximum(AUD_SequenceEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setVolumeMaximum(value);
+}
+
+AUD_API float AUD_SequenceEntry_getVolumeMinimum(AUD_SequenceEntry* sequence_entry)
+{
+ assert(sequence_entry);
+ return (*sequence_entry)->getVolumeMinimum();
+}
+
+AUD_API void AUD_SequenceEntry_setVolumeMinimum(AUD_SequenceEntry* sequence_entry, float value)
+{
+ assert(sequence_entry);
+ (*sequence_entry)->setVolumeMinimum(value);
+}
diff --git a/extern/audaspace/bindings/C/AUD_Sequence.h b/extern/audaspace/bindings/C/AUD_Sequence.h
new file mode 100644
index 00000000000..668960c7d50
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_Sequence.h
@@ -0,0 +1,338 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+#include "AUD_Device.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Possible animatable properties for Sequence Factories and Entries.
+typedef enum
+{
+ AUD_AP_VOLUME,
+ AUD_AP_PANNING,
+ AUD_AP_PITCH,
+ AUD_AP_LOCATION,
+ AUD_AP_ORIENTATION
+} AUD_AnimateablePropertyType;
+
+/**
+ * Creates a new sequenced sound scene.
+ * \param fps The FPS of the scene.
+ * \param muted Whether the scene is muted.
+ * \return The new sound scene.
+ */
+extern AUD_API AUD_Sound* AUD_Sequence_create(float fps, int muted);
+
+/**
+ * Deletes a sound scene.
+ * \param sequence The sound scene.
+ */
+extern AUD_API void AUD_Sequence_free(AUD_Sound* sequence);
+
+/**
+ * Adds a new entry to the scene.
+ * \param sequence The sound scene.
+ * \param sound The sound this entry should play.
+ * \param begin The start time.
+ * \param end The end time or a negative value if determined by the sound.
+ * \param skip How much seconds should be skipped at the beginning.
+ * \return The entry added.
+ */
+extern AUD_API AUD_SequenceEntry* AUD_Sequence_add(AUD_Sound* sequence, AUD_Sound* sound, float begin, float end, float skip);
+
+/**
+ * Removes an entry from the scene.
+ * \param sequence The sound scene.
+ * \param entry The entry to remove.
+ */
+extern AUD_API void AUD_Sequence_remove(AUD_Sound* sequence, AUD_SequenceEntry* entry);
+
+/**
+ * Writes animation data to a sequence.
+ * \param sequence The sound scene.
+ * \param type The type of animation data.
+ * \param frame The frame this data is for.
+ * \param data The data to write.
+ * \param animated Whether the attribute is animated.
+ */
+extern AUD_API void AUD_Sequence_setAnimationData(AUD_Sound* sequence, AUD_AnimateablePropertyType type, int frame, float* data, char animated);
+
+/**
+ * Retrieves the distance model of a sequence.
+ * param sequence The sequence to get the distance model from.
+ * return The distance model of the sequence.
+ */
+extern AUD_API AUD_DistanceModel AUD_Sequence_getDistanceModel(AUD_Sound* sequence);
+
+/**
+ * Sets the distance model of a sequence.
+ * param sequence The sequence to set the distance model from.
+ * param value The new distance model to set.
+ */
+extern AUD_API void AUD_Sequence_setDistanceModel(AUD_Sound* sequence, AUD_DistanceModel value);
+
+/**
+ * Retrieves the doppler factor of a sequence.
+ * param sequence The sequence to get the doppler factor from.
+ * return The doppler factor of the sequence.
+ */
+extern AUD_API float AUD_Sequence_getDopplerFactor(AUD_Sound* sequence);
+
+/**
+ * Sets the doppler factor of a sequence.
+ * param sequence The sequence to set the doppler factor from.
+ * param value The new doppler factor to set.
+ */
+extern AUD_API void AUD_Sequence_setDopplerFactor(AUD_Sound* sequence, float value);
+
+/**
+ * Retrieves the fps of a sequence.
+ * param sequence The sequence to get the fps from.
+ * return The fps of the sequence.
+ */
+extern AUD_API float AUD_Sequence_getFPS(AUD_Sound* sequence);
+
+/**
+ * Sets the fps of a sequence.
+ * param sequence The sequence to set the fps from.
+ * param value The new fps to set.
+ */
+extern AUD_API void AUD_Sequence_setFPS(AUD_Sound* sequence, float value);
+
+/**
+ * Retrieves the muted of a sequence.
+ * param sequence The sequence to get the muted from.
+ * return The muted of the sequence.
+ */
+extern AUD_API int AUD_Sequence_isMuted(AUD_Sound* sequence);
+
+/**
+ * Sets the muted of a sequence.
+ * param sequence The sequence to set the muted from.
+ * param value The new muted to set.
+ */
+extern AUD_API void AUD_Sequence_setMuted(AUD_Sound* sequence, int value);
+
+/**
+ * Retrieves the specs of a sequence.
+ * param sequence The sequence to get the specs from.
+ * return The specs of the sequence.
+ */
+extern AUD_API AUD_Specs AUD_Sequence_getSpecs(AUD_Sound* sequence);
+
+/**
+ * Sets the specs of a sequence.
+ * param sequence The sequence to set the specs from.
+ * param value The new specs to set.
+ */
+extern AUD_API void AUD_Sequence_setSpecs(AUD_Sound* sequence, AUD_Specs value);
+
+/**
+ * Retrieves the speed of sound of a sequence.
+ * param sequence The sequence to get the speed of sound from.
+ * return The speed of sound of the sequence.
+ */
+extern AUD_API float AUD_Sequence_getSpeedOfSound(AUD_Sound* sequence);
+
+/**
+ * Sets the speed of sound of a sequence.
+ * param sequence The sequence to set the speed of sound from.
+ * param value The new speed of sound to set.
+ */
+extern AUD_API void AUD_Sequence_setSpeedOfSound(AUD_Sound* sequence, float value);
+
+
+
+/**
+ * Moves the entry.
+ * \param entry The sequenced entry.
+ * \param begin The new start time.
+ * \param end The new end time or a negative value if unknown.
+ * \param skip How many seconds to skip at the beginning.
+ */
+extern AUD_API void AUD_SequenceEntry_move(AUD_SequenceEntry* entry, float begin, float end, float skip);
+
+/**
+ * Writes animation data to a sequenced entry.
+ * \param entry The sequenced entry.
+ * \param type The type of animation data.
+ * \param frame The frame this data is for.
+ * \param data The data to write.
+ * \param animated Whether the attribute is animated.
+ */
+extern AUD_API void AUD_SequenceEntry_setAnimationData(AUD_SequenceEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated);
+
+/**
+ * Retrieves the attenuation of a sequence_entry.
+ * param sequence_entry The sequence_entry to get the attenuation from.
+ * return The attenuation of the sequence_entry.
+ */
+extern AUD_API float AUD_SequenceEntry_getAttenuation(AUD_SequenceEntry* sequence_entry);
+
+/**
+ * Sets the attenuation of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the attenuation from.
+ * param value The new attenuation to set.
+ */
+extern AUD_API void AUD_SequenceEntry_setAttenuation(AUD_SequenceEntry* sequence_entry, float value);
+
+/**
+ * Retrieves the cone angle inner of a sequence_entry.
+ * param sequence_entry The sequence_entry to get the cone angle inner from.
+ * return The cone angle inner of the sequence_entry.
+ */
+extern AUD_API float AUD_SequenceEntry_getConeAngleInner(AUD_SequenceEntry* sequence_entry);
+
+/**
+ * Sets the cone angle inner of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the cone angle inner from.
+ * param value The new cone angle inner to set.
+ */
+extern AUD_API void AUD_SequenceEntry_setConeAngleInner(AUD_SequenceEntry* sequence_entry, float value);
+
+/**
+ * Retrieves the cone angle outer of a sequence_entry.
+ * param sequence_entry The sequence_entry to get the cone angle outer from.
+ * return The cone angle outer of the sequence_entry.
+ */
+extern AUD_API float AUD_SequenceEntry_getConeAngleOuter(AUD_SequenceEntry* sequence_entry);
+
+/**
+ * Sets the cone angle outer of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the cone angle outer from.
+ * param value The new cone angle outer to set.
+ */
+extern AUD_API void AUD_SequenceEntry_setConeAngleOuter(AUD_SequenceEntry* sequence_entry, float value);
+
+/**
+ * Retrieves the cone volume outer of a sequence_entry.
+ * param sequence_entry The sequence_entry to get the cone volume outer from.
+ * return The cone volume outer of the sequence_entry.
+ */
+extern AUD_API float AUD_SequenceEntry_getConeVolumeOuter(AUD_SequenceEntry* sequence_entry);
+
+/**
+ * Sets the cone volume outer of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the cone volume outer from.
+ * param value The new cone volume outer to set.
+ */
+extern AUD_API void AUD_SequenceEntry_setConeVolumeOuter(AUD_SequenceEntry* sequence_entry, float value);
+
+/**
+ * Retrieves the distance maximum of a sequence_entry.
+ * param sequence_entry The sequence_entry to get the distance maximum from.
+ * return The distance maximum of the sequence_entry.
+ */
+extern AUD_API float AUD_SequenceEntry_getDistanceMaximum(AUD_SequenceEntry* sequence_entry);
+
+/**
+ * Sets the distance maximum of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the distance maximum from.
+ * param value The new distance maximum to set.
+ */
+extern AUD_API void AUD_SequenceEntry_setDistanceMaximum(AUD_SequenceEntry* sequence_entry, float value);
+
+/**
+ * Retrieves the distance reference of a sequence_entry.
+ * param sequence_entry The sequence_entry to get the distance reference from.
+ * return The distance reference of the sequence_entry.
+ */
+extern AUD_API float AUD_SequenceEntry_getDistanceReference(AUD_SequenceEntry* sequence_entry);
+
+/**
+ * Sets the distance reference of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the distance reference from.
+ * param value The new distance reference to set.
+ */
+extern AUD_API void AUD_SequenceEntry_setDistanceReference(AUD_SequenceEntry* sequence_entry, float value);
+
+/**
+ * Retrieves the muted of a sequence_entry.
+ * param sequence_entry The sequence_entry to get the muted from.
+ * return The muted of the sequence_entry.
+ */
+extern AUD_API int AUD_SequenceEntry_isMuted(AUD_SequenceEntry* sequence_entry);
+
+/**
+ * Sets the muted of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the muted from.
+ * param value The new muted to set.
+ */
+extern AUD_API void AUD_SequenceEntry_setMuted(AUD_SequenceEntry* sequence_entry, int value);
+
+/**
+ * Retrieves the relative of a sequence_entry.
+ * param sequence_entry The sequence_entry to get the relative from.
+ * return The relative of the sequence_entry.
+ */
+extern AUD_API int AUD_SequenceEntry_isRelative(AUD_SequenceEntry* sequence_entry);
+
+/**
+ * Sets the relative of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the relative from.
+ * param value The new relative to set.
+ */
+extern AUD_API void AUD_SequenceEntry_setRelative(AUD_SequenceEntry* sequence_entry, int value);
+
+/**
+ * Retrieves the sound of a sequence_entry.
+ * param sequence_entry The sequence_entry to get the sound from.
+ * return The sound of the sequence_entry.
+ */
+extern AUD_API AUD_Sound* AUD_SequenceEntry_getSound(AUD_SequenceEntry* sequence_entry);
+
+/**
+ * Sets the sound of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the sound from.
+ * param value The new sound to set.
+ */
+extern AUD_API void AUD_SequenceEntry_setSound(AUD_SequenceEntry* sequence_entry, AUD_Sound* value);
+
+/**
+ * Retrieves the volume maximum of a sequence_entry.
+ * param sequence_entry The sequence_entry to get the volume maximum from.
+ * return The volume maximum of the sequence_entry.
+ */
+extern AUD_API float AUD_SequenceEntry_getVolumeMaximum(AUD_SequenceEntry* sequence_entry);
+
+/**
+ * Sets the volume maximum of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the volume maximum from.
+ * param value The new volume maximum to set.
+ */
+extern AUD_API void AUD_SequenceEntry_setVolumeMaximum(AUD_SequenceEntry* sequence_entry, float value);
+
+/**
+ * Retrieves the volume minimum of a sequence_entry.
+ * param sequence_entry The sequence_entry to get the volume minimum from.
+ * return The volume minimum of the sequence_entry.
+ */
+extern AUD_API float AUD_SequenceEntry_getVolumeMinimum(AUD_SequenceEntry* sequence_entry);
+
+/**
+ * Sets the volume minimum of a sequence_entry.
+ * param sequence_entry The sequence_entry to set the volume minimum from.
+ * param value The new volume minimum to set.
+ */
+extern AUD_API void AUD_SequenceEntry_setVolumeMinimum(AUD_SequenceEntry* sequence_entry, float value);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/extern/audaspace/bindings/C/AUD_Sound.cpp b/extern/audaspace/bindings/C/AUD_Sound.cpp
new file mode 100644
index 00000000000..30860acde62
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_Sound.cpp
@@ -0,0 +1,709 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#include "generator/Sawtooth.h"
+#include "generator/Sine.h"
+#include "generator/Silence.h"
+#include "generator/Square.h"
+#include "generator/Triangle.h"
+#include "file/File.h"
+#include "file/FileWriter.h"
+#include "util/StreamBuffer.h"
+#include "fx/Accumulator.h"
+#include "fx/ADSR.h"
+#include "fx/Delay.h"
+#include "fx/Envelope.h"
+#include "fx/Fader.h"
+#include "fx/Highpass.h"
+#include "fx/IIRFilter.h"
+#include "fx/Limiter.h"
+#include "fx/Loop.h"
+#include "fx/Lowpass.h"
+#include "fx/Pitch.h"
+#include "fx/Reverse.h"
+#include "fx/Sum.h"
+#include "fx/Threshold.h"
+#include "fx/Volume.h"
+#include "fx/SoundList.h"
+#include "fx/MutableSound.h"
+#include "sequence/Double.h"
+#include "sequence/Superpose.h"
+#include "sequence/PingPong.h"
+#include "respec/LinearResample.h"
+#include "respec/JOSResample.h"
+#include "respec/JOSResampleReader.h"
+#include "respec/ChannelMapper.h"
+#include "respec/ChannelMapperReader.h"
+#include "util/Buffer.h"
+#include "Exception.h"
+
+#ifdef WITH_CONVOLUTION
+#include "fx/BinauralSound.h"
+#include "fx/ConvolverSound.h"
+#endif
+
+#include <cassert>
+#include <cstring>
+
+using namespace aud;
+
+#define AUD_CAPI_IMPLEMENTATION
+#include "AUD_Sound.h"
+
+static inline AUD_Specs convSpecToC(aud::Specs specs)
+{
+ AUD_Specs s;
+ s.channels = static_cast<AUD_Channels>(specs.channels);
+ s.rate = static_cast<AUD_SampleRate>(specs.rate);
+ return s;
+}
+
+static inline aud::Specs convCToSpec(AUD_Specs specs)
+{
+ aud::Specs s;
+ s.channels = static_cast<Channels>(specs.channels);
+ s.rate = static_cast<SampleRate>(specs.rate);
+ return s;
+}
+
+AUD_API AUD_Specs AUD_Sound_getSpecs(AUD_Sound* sound)
+{
+ assert(sound);
+
+ return convSpecToC((*sound)->createReader()->getSpecs());
+}
+
+AUD_API int AUD_Sound_getLength(AUD_Sound* sound)
+{
+ assert(sound);
+
+ return (*sound)->createReader()->getLength();
+}
+
+AUD_API sample_t* AUD_Sound_data(AUD_Sound* sound, int* length, AUD_Specs* specs)
+{
+ assert(sound);
+ assert(length);
+ assert(specs);
+
+ auto stream_buffer = std::dynamic_pointer_cast<StreamBuffer>(*sound);
+ if(!stream_buffer)
+ stream_buffer = std::make_shared<StreamBuffer>(*sound);
+ *specs = convSpecToC(stream_buffer->getSpecs());
+ auto buffer = stream_buffer->getBuffer();
+
+ *length = buffer->getSize() / AUD_SAMPLE_SIZE((*specs));
+
+ sample_t* data = new sample_t[buffer->getSize()];
+
+ std::memcpy(data, buffer->getBuffer(), buffer->getSize());
+
+ return data;
+}
+
+AUD_API void AUD_Sound_freeData(sample_t* data)
+{
+ delete[] data;
+}
+
+AUD_API const char* AUD_Sound_write(AUD_Sound* sound, const char* filename, AUD_SampleRate rate, AUD_Channels channels, AUD_SampleFormat format, AUD_Container container, AUD_Codec codec, int bitrate, int buffersize)
+{
+ assert(sound);
+ assert(filename);
+
+ try
+ {
+ std::shared_ptr<IReader> reader = (*sound)->createReader();
+
+ DeviceSpecs specs;
+ specs.specs = reader->getSpecs();
+
+ if((rate != RATE_INVALID) && (specs.rate != rate))
+ {
+ specs.rate = rate;
+ reader = std::make_shared<JOSResampleReader>(reader, rate);
+ }
+
+ if((channels != AUD_CHANNELS_INVALID) && (specs.channels != static_cast<Channels>(channels)))
+ {
+ specs.channels = static_cast<Channels>(channels);
+ reader = std::make_shared<ChannelMapperReader>(reader, specs.channels);
+ }
+
+ if(format == AUD_FORMAT_INVALID)
+ format = AUD_FORMAT_S16;
+ specs.format = static_cast<SampleFormat>(format);
+
+ const char* invalid_container_error = "Container could not be determined from filename.";
+
+ if(container == AUD_CONTAINER_INVALID)
+ {
+ std::string path = filename;
+
+ if(path.length() < 4)
+ return invalid_container_error;
+
+ std::string extension = path.substr(path.length() - 4);
+
+ if(extension == ".ac3")
+ container = AUD_CONTAINER_AC3;
+ else if(extension == "flac")
+ container = AUD_CONTAINER_FLAC;
+ else if(extension == ".mkv")
+ container = AUD_CONTAINER_MATROSKA;
+ else if(extension == ".mp2")
+ container = AUD_CONTAINER_MP2;
+ else if(extension == ".mp3")
+ container = AUD_CONTAINER_MP3;
+ else if(extension == ".ogg")
+ container = AUD_CONTAINER_OGG;
+ else if(extension == ".wav")
+ container = AUD_CONTAINER_WAV;
+ else
+ return invalid_container_error;
+ }
+
+ if(codec == AUD_CODEC_INVALID)
+ {
+ switch(container)
+ {
+ case AUD_CONTAINER_AC3:
+ codec = AUD_CODEC_AC3;
+ break;
+ case AUD_CONTAINER_FLAC:
+ codec = AUD_CODEC_FLAC;
+ break;
+ case AUD_CONTAINER_MATROSKA:
+ codec = AUD_CODEC_OPUS;
+ break;
+ case AUD_CONTAINER_MP2:
+ codec = AUD_CODEC_MP2;
+ break;
+ case AUD_CONTAINER_MP3:
+ codec = AUD_CODEC_MP3;
+ break;
+ case AUD_CONTAINER_OGG:
+ codec = AUD_CODEC_VORBIS;
+ break;
+ case AUD_CONTAINER_WAV:
+ codec = AUD_CODEC_PCM;
+ break;
+ default:
+ return "Unknown container, cannot select default codec.";
+ }
+ }
+
+ if(buffersize <= 0)
+ buffersize = AUD_DEFAULT_BUFFER_SIZE;
+
+ std::shared_ptr<IWriter> writer = FileWriter::createWriter(filename, specs, static_cast<Container>(container), static_cast<Codec>(codec), bitrate);
+ FileWriter::writeReader(reader, writer, 0, buffersize);
+ }
+ catch(Exception& e)
+ {
+ return "An exception occured while writing.";
+ }
+
+ return nullptr;
+}
+
+AUD_API AUD_Sound* AUD_Sound_buffer(sample_t* data, int length, AUD_Specs specs)
+{
+ assert(data);
+
+ if(length <= 0 || specs.rate <= 0 || specs.channels <= 0)
+ {
+ return nullptr;
+ }
+
+ int size = length * AUD_SAMPLE_SIZE(specs);
+
+ std::shared_ptr<Buffer> buffer = std::make_shared<Buffer>(size);
+
+ std::memcpy(buffer->getBuffer(), data, size);
+
+ try
+ {
+ return new AUD_Sound(new StreamBuffer(buffer, convCToSpec(specs)));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_bufferFile(unsigned char* buffer, int size)
+{
+ assert(buffer);
+ return new AUD_Sound(new File(buffer, size));
+}
+
+AUD_API AUD_Sound* AUD_Sound_cache(AUD_Sound* sound)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new StreamBuffer(*sound));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_file(const char* filename)
+{
+ assert(filename);
+ return new AUD_Sound(new File(filename));
+}
+
+AUD_API AUD_Sound* AUD_Sound_sawtooth(float frequency, AUD_SampleRate rate)
+{
+ return new AUD_Sound(new Sawtooth(frequency, rate));
+}
+
+AUD_API AUD_Sound*AUD_Sound_silence()
+{
+ return new AUD_Sound(new Silence());
+}
+
+AUD_API AUD_Sound* AUD_Sound_sine(float frequency, AUD_SampleRate rate)
+{
+ return new AUD_Sound(new Sine(frequency, rate));
+}
+
+AUD_API AUD_Sound* AUD_Sound_square(float frequency, AUD_SampleRate rate)
+{
+ return new AUD_Sound(new Square(frequency, rate));
+}
+
+AUD_API AUD_Sound* AUD_Sound_triangle(float frequency, AUD_SampleRate rate)
+{
+ return new AUD_Sound(new Triangle(frequency, rate));
+}
+
+AUD_API AUD_Sound* AUD_Sound_accumulate(AUD_Sound* sound, int additive)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Accumulator(*sound, additive));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_ADSR(AUD_Sound* sound, float attack, float decay, float sustain, float release)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new ADSR(*sound, attack, decay, sustain, release));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_delay(AUD_Sound* sound, float delay)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Delay(*sound, delay));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_envelope(AUD_Sound* sound, float attack, float release, float threshold, float arthreshold)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Envelope(*sound, attack, release, threshold, arthreshold));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_fadein(AUD_Sound* sound, float start, float length)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Fader(*sound, FADE_IN, start, length));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_fadeout(AUD_Sound* sound, float start, float length)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Fader(*sound, FADE_OUT, start, length));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_filter(AUD_Sound* sound, float* b, int b_length, float* a, int a_length)
+{
+ assert(sound);
+
+ try
+ {
+ std::vector<float> a_coeff, b_coeff;
+
+ if(b)
+ for(int i = 0; i < b_length; i++)
+ b_coeff.push_back(b[i]);
+
+ if(a)
+ {
+ for(int i = 0; i < a_length; i++)
+ a_coeff.push_back(a[i]);
+
+ if(*a == 0.0f)
+ a_coeff[0] = 1.0f;
+ }
+
+ return new AUD_Sound(new IIRFilter(*sound, b_coeff, a_coeff));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_highpass(AUD_Sound* sound, float frequency, float Q)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Highpass(*sound, frequency, Q));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_limit(AUD_Sound* sound, float start, float end)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Limiter(*sound, start, end));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_loop(AUD_Sound* sound, int count)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Loop(*sound, count));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_lowpass(AUD_Sound* sound, float frequency, float Q)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Lowpass(*sound, frequency, Q));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_pitch(AUD_Sound* sound, float factor)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Pitch(*sound, factor));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_rechannel(AUD_Sound* sound, AUD_Channels channels)
+{
+ assert(sound);
+
+ try
+ {
+ DeviceSpecs specs;
+ specs.channels = static_cast<Channels>(channels);
+ specs.rate = RATE_INVALID;
+ specs.format = FORMAT_INVALID;
+ return new AUD_Sound(new ChannelMapper(*sound, specs));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_resample(AUD_Sound* sound, AUD_SampleRate rate, bool high_quality)
+{
+ assert(sound);
+
+ try
+ {
+ DeviceSpecs specs;
+ specs.channels = CHANNELS_INVALID;
+ specs.rate = rate;
+ specs.format = FORMAT_INVALID;
+ if(high_quality)
+ return new AUD_Sound(new JOSResample(*sound, specs));
+ else
+ return new AUD_Sound(new LinearResample(*sound, specs));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_reverse(AUD_Sound* sound)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Reverse(*sound));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_sum(AUD_Sound* sound)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Sum(*sound));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_threshold(AUD_Sound* sound, float threshold)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Threshold(*sound, threshold));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_volume(AUD_Sound* sound, float volume)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new Volume(*sound, volume));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_join(AUD_Sound* first, AUD_Sound* second)
+{
+ assert(first);
+ assert(second);
+
+ try
+ {
+ return new AUD_Sound(new Double(*first, *second));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_mix(AUD_Sound* first, AUD_Sound* second)
+{
+ assert(first);
+ assert(second);
+
+ try
+ {
+ return new AUD_Sound(new Superpose(*first, *second));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_pingpong(AUD_Sound* sound)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new PingPong(*sound));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API void AUD_Sound_free(AUD_Sound* sound)
+{
+ assert(sound);
+ delete sound;
+}
+
+AUD_API AUD_Sound* AUD_Sound_copy(AUD_Sound* sound)
+{
+ return new std::shared_ptr<ISound>(*sound);
+}
+
+AUD_API AUD_Sound* AUD_Sound_list(int random)
+{
+ try
+ {
+ return new AUD_Sound(new SoundList(random));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API int AUD_SoundList_addSound(AUD_Sound* list, AUD_Sound* sound)
+{
+ assert(sound);
+ assert(list);
+
+ std::shared_ptr<SoundList> s = std::dynamic_pointer_cast<SoundList>(*list);
+ if(s.get())
+ {
+ s->addSound(*sound);
+ return 1;
+ }
+ else
+ return 0;
+
+}
+
+AUD_API AUD_Sound* AUD_Sound_mutable(AUD_Sound* sound)
+{
+ assert(sound);
+
+ try
+ {
+ return new AUD_Sound(new MutableSound(*sound));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+#ifdef WITH_CONVOLUTION
+
+AUD_API AUD_Sound* AUD_Sound_Convolver(AUD_Sound* sound, AUD_ImpulseResponse* filter, AUD_ThreadPool* threadPool)
+{
+ assert(sound);
+ assert(filter);
+ assert(threadPool);
+
+ try
+ {
+ return new AUD_Sound(new ConvolverSound(*sound, *filter, *threadPool));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API AUD_Sound* AUD_Sound_Binaural(AUD_Sound* sound, AUD_HRTF* hrtfs, AUD_Source* source, AUD_ThreadPool* threadPool)
+{
+ assert(sound);
+ assert(hrtfs);
+ assert(source);
+ assert(threadPool);
+
+ try
+ {
+ return new AUD_Sound(new BinauralSound(*sound, *hrtfs, *source, *threadPool));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+#endif
diff --git a/extern/audaspace/bindings/C/AUD_Sound.h b/extern/audaspace/bindings/C/AUD_Sound.h
new file mode 100644
index 00000000000..b18e3c3a8eb
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_Sound.h
@@ -0,0 +1,370 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+#include "AUD_Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Retrieves the sample specification of the sound.
+ * \param sound The sound to retrieve from.
+ * \return The sample specification of the sound.
+ * \note This function creates a reader from the sound and deletes it again.
+ */
+extern AUD_API AUD_Specs AUD_Sound_getSpecs(AUD_Sound* sound);
+
+/**
+ * Retrieves the approximate length of the sound.
+ * \param sound The sound to retrieve from.
+ * \return The length of the sound in samples.
+ * \note This function creates a reader from the sound and deletes it again.
+ */
+extern AUD_API int AUD_getLength(AUD_Sound* sound);
+
+/**
+ * Reads a sound's samples into memory.
+ * \param sound The sound to read.
+ * \param length Pointer to store the length of memory read.
+ * \param specs Pointer to store the data's sample specification.
+ * \return A pointer to the sample data.
+ * \warning The data has to be freed with AUD_Sound_freeData.
+ */
+extern AUD_API sample_t* AUD_Sound_data(AUD_Sound* sound, int* length, AUD_Specs* specs);
+
+/**
+ * Frees a buffer previously allocated with AUD_Sound_data.
+ * \param data The buffer to be freed.
+ */
+extern AUD_API void AUD_Sound_freeData(sample_t* data);
+
+/**
+ * Writes the sound to a file.
+ * \param sound The sound to write.
+ * \param filename The path to write to..
+ * \param rate The sample rate to write with.
+ * \param channels The number of channels to write with.
+ * \param format The sample format to write with.
+ * \param container The container format for the file.
+ * \param codec The codec to use in the file.
+ * \param bitrate The bitrate to write with.
+ * \param buffersize The size of the writing buffer.
+ * \return A nullptr or an error message in case of error.
+ * \note Most parameters can be set to zero for default values.
+ */
+extern AUD_API const char* AUD_Sound_write(AUD_Sound* sound, const char* filename, AUD_SampleRate rate, AUD_Channels channels, AUD_SampleFormat format, AUD_Container container, AUD_Codec codec, int bitrate, int buffersize);
+
+/**
+ * Creates a sound from a data buffer.
+ * \param data The data as interleaved samples.
+ * \param length The data's length in samples.
+ * \param specs The data's sample specification.
+ * \return A handle of the sound.
+ * \note The data gets copied to an internal memory buffer.
+ * The pointer does not need to stay valid for the lifetime of the object.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_buffer(sample_t* data, int length, AUD_Specs specs);
+
+/**
+ * Loads a sound file from a memory buffer.
+ * \param buffer The buffer which contains the sound file.
+ * \param size The size of the buffer.
+ * \return A handle of the sound file.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_bufferFile(unsigned char* buffer, int size);
+
+/**
+ * Caches a sound into a memory buffer.
+ * \param sound The sound to cache.
+ * \return A handle of the cached sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_cache(AUD_Sound* sound);
+
+/**
+ * Loads a sound file.
+ * \param filename The filename of the sound file.
+ * \return A handle of the sound file.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_file(const char* filename);
+
+/**
+ * Creates a sawtooth sound.
+ * \param frequency The frequency of the generated sawtooth sound.
+ * \param rate The sample rate of the sawtooth sound.
+ * \return A handle of the sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_sawtooth(float frequency, AUD_SampleRate rate);
+
+/**
+ * Creates a quiet sound.
+ * \return A handle of the sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_silence();
+
+/**
+ * Creates a sine sound.
+ * \param frequency The frequency of the generated sine sound.
+ * \param rate The sample rate of the sine sound.
+ * \return A handle of the sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_sine(float frequency, AUD_SampleRate rate);
+
+/**
+ * Creates a square sound.
+ * \param frequency The frequency of the generated square sound.
+ * \param rate The sample rate of the square sound.
+ * \return A handle of the sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_square(float frequency, AUD_SampleRate rate);
+
+/**
+ * Creates a triangle sound.
+ * \param frequency The frequency of the generated triangle sound.
+ * \param rate The sample rate of the triangle sound.
+ * \return A handle of the sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_triangle(float frequency, AUD_SampleRate rate);
+
+/**
+ * Accumulates a sound by summing over positive input differences thus generating a monotonic sigal.
+ * If additivity is set to true negative input differences get added too, but positive ones with a factor of two.
+ * Note that with additivity the signal is not monotonic anymore.
+ * \param sound The sound to accumulate.
+ * \param additive Whether the accumulation should be additive or not.
+ * \return A handle of the accumulated sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_accumulate(AUD_Sound* sound, int additive);
+
+/**
+ * Attack-Decay-Sustain-Release envelopes the volume of a sound.
+ * Note: there is currently no way to trigger the release with this API.
+ * \param sound The sound to filter.
+ * \param attack The attack time in seconds.
+ * \param decay The decay time in seconds.
+ * \param sustain The sustain level.
+ * \param release The release time in seconds.
+ * \return A handle of the filtered sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_ADSR(AUD_Sound* sound, float attack, float decay, float sustain, float release);
+
+/**
+ * Delays a sound.
+ * \param sound The sound to dealy.
+ * \param delay The delay in seconds.
+ * \return A handle of the delayed sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_delay(AUD_Sound* sound, float delay);
+
+/**
+ * Envelopes a sound.
+ * \param sound The sound to envelope.
+ * \param attack The attack factor.
+ * \param release The release factor.
+ * \param threshold The general threshold value.
+ * \param arthreshold The attack/release threshold value.
+ * \return A handle of the enveloped sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_envelope(AUD_Sound* sound, float attack, float release, float threshold, float arthreshold);
+
+/**
+ * Fade in a sound.
+ * \param sound The sound to be fade in.
+ * \param start The time when the fading should start in seconds.
+ * \param length The duration of the fade in seconds.
+ * \return A handle of the faded sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_fadein(AUD_Sound* sound, float start, float length);
+
+/**
+ * Fade out a sound.
+ * \param sound The sound to be fade out.
+ * \param start The time when the fading should start in seconds.
+ * \param length The duration of the fade in seconds.
+ * \return A handle of the faded sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_fadeout(AUD_Sound* sound, float start, float length);
+
+/**
+ * Filter a sound.
+ * \param sound The sound to be filtered.
+ * \param b The nominator filter coefficients, may be NULL.
+ * \param b_length The length of the b array.
+ * \param a The denominator filter coefficients, may be NULL.
+ * \param a_length The length of the a array.
+ * \return A handle of the filtered sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_filter(AUD_Sound* sound, float* b, int b_length, float* a, int a_length);
+
+/**
+ * Highpass filters a sound.
+ * \param sound The sound to filter.
+ * \param frequency The filter cut-off frequency.
+ * \param Q The filter quality. If usunsure which value to use, pass 1.0f.
+ * \return A handle of the filtered sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_highpass(AUD_Sound* sound, float frequency, float Q);
+
+/**
+ * Limits a sound.
+ * \param sound The sound to limit.
+ * \param start The start time in seconds.
+ * \param end The stop time in seconds.
+ * \return A handle of the limited sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_limit(AUD_Sound* sound, float start, float end);
+
+/**
+ * Loops a sound.
+ * \param sound The sound to loop.
+ * \param count How often the sound should be looped. Negative values mean endlessly.
+ * \return A handle of the looped sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_loop(AUD_Sound* sound, int count);
+
+/**
+ * Lowpass filters a sound.
+ * \param sound The sound to filter.
+ * \param frequency The filter cut-off frequency.
+ * \param Q The filter quality. If usunsure which value to use, pass 1.0f.
+ * \return A handle of the filtered sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_lowpass(AUD_Sound* sound, float frequency, float Q);
+
+/**
+ * Changes the pitch of a sound.
+ * \param sound The sound to change.
+ * \param factor The factor to change the pitch with.
+ * \return A handle of the pitched sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_pitch(AUD_Sound* sound, float factor);
+
+/**
+ * Rechannels the sound.
+ * \param sound The sound to rechannel.
+ * \param channels The new channel configuration.
+ * \return The rechanneled sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_rechannel(AUD_Sound* sound, AUD_Channels channels);
+
+/**
+ * Resamples the sound.
+ * \param sound The sound to resample.
+ * \param rate The new sample rate.
+ * \param high_quality When true use a higher quality but slower resampler.
+ * \return The resampled sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_resample(AUD_Sound* sound, AUD_SampleRate rate, bool high_quality);
+
+/**
+ * Reverses a sound. Make sure the sound source can be reversed.
+ * \param sound The sound to reverse.
+ * \return A handle of the reversed sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_reverse(AUD_Sound* sound);
+
+/**
+ * Sums the samples of a sound.
+ * \param sound The sound to sum.
+ * \return A handle of the summed sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_sum(AUD_Sound* sound);
+
+/**
+ * Turns a sound into a square wave by thresholding.
+ * \param sound The sound to threshold.
+ * \param threshold Threshold value over which an amplitude counts non-zero.
+ * \return A handle of the thresholded sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_threshold(AUD_Sound* sound, float threshold);
+
+/**
+ * Changes the volume of a sound.
+ * \param sound The sound to change.
+ * \param volume The new volume of the sound. Should be in the range 0 to 1. Use higher values with caution.
+ * \return A handle of the amplified sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_volume(AUD_Sound* sound, float volume);
+
+/**
+ * Joins two sound, which means playing them one after the other.
+ * \param first The first sound.
+ * \param second The second sound.
+ * \return A handle of the joined sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_join(AUD_Sound* first, AUD_Sound* second);
+
+/**
+ * Mixes two sound, which means superposing the sound samples.
+ * \param first The first sound.
+ * \param second The second sound.
+ * \return A handle of the mixed sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_mix(AUD_Sound* first, AUD_Sound* second);
+
+/**
+ * Ping pongs a sound.
+ * \param sound The sound to ping pong.
+ * \return A handle of the ping pong sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_pingpong(AUD_Sound* sound);
+
+/**
+ * Unloads a sound of any type.
+ * \param sound The handle of the sound.
+ */
+extern AUD_API void AUD_Sound_free(AUD_Sound* sound);
+
+/**
+ * Copies a sound.
+ * \param sound Sound to copy.
+ * \return Copied sound.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_copy(AUD_Sound* sound);
+
+/**
+ * Creates an empty sound list that can contain several sounds.
+ * \param random A flag that indicates how the list will be played: Randomly or sequentially.
+ * if 0 the playback will be sequential, if not 0 the playback will be random.
+ * \return A handle of the sound list.
+ */
+extern AUD_API AUD_Sound* AUD_Sound_list(int random);
+
+/**
+* Adds a new sound to a sound list.
+ * \param list The sound list in which the sound will be added.
+ * \param sound The sound that will be added to the list.
+ * \return 0 if the sound couldn't be added (the list parameter isn't a sound list).
+*/
+extern AUD_API int AUD_SoundList_addSound(AUD_Sound* list, AUD_Sound* sound);
+
+/**
+ * Creates a sound that will be restarted when sought backwards. If the original sound is a sound list, the playing sound can change.
+ * \param sound The handle of the sound.
+ * \return A handle of the mutable sound.
+*/
+extern AUD_API AUD_Sound* AUD_Sound_mutable(AUD_Sound* sound);
+
+#ifdef WITH_CONVOLUTION
+ extern AUD_API AUD_Sound* AUD_Sound_Convolver(AUD_Sound* sound, AUD_ImpulseResponse* filter, AUD_ThreadPool* threadPool);
+ extern AUD_API AUD_Sound* AUD_Sound_Binaural(AUD_Sound* sound, AUD_HRTF* hrtfs, AUD_Source* source, AUD_ThreadPool* threadPool);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/extern/audaspace/bindings/C/AUD_Source.cpp b/extern/audaspace/bindings/C/AUD_Source.cpp
new file mode 100644
index 00000000000..c4bf6fea6a1
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_Source.cpp
@@ -0,0 +1,84 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#include "Exception.h"
+
+#include <cassert>
+
+using namespace aud;
+
+#define AUD_CAPI_IMPLEMENTATION
+#include "AUD_Source.h"
+
+extern AUD_API AUD_Source* AUD_Source_create(float azimuth, float elevation, float distance)
+{
+ try
+ {
+ return new AUD_Source(new Source(azimuth, elevation, distance));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+extern AUD_API void AUD_Source_free(AUD_Source* source)
+{
+ assert(source);
+ delete source;
+}
+
+extern AUD_API float AUD_Source_getAzimuth(AUD_Source* source)
+{
+ assert(source);
+
+ return (*source)->getAzimuth();
+}
+
+extern AUD_API float AUD_Source_getElevation(AUD_Source* source)
+{
+ assert(source);
+
+ return (*source)->getElevation();
+}
+
+extern AUD_API float AUD_Source_getDistance(AUD_Source* source)
+{
+ assert(source);
+
+ return (*source)->getDistance();
+}
+
+extern AUD_API void AUD_Source_setAzimuth(AUD_Source* source, float azimuth)
+{
+ assert(source);
+
+ (*source)->setAzimuth(azimuth);
+}
+
+extern AUD_API void AUD_Source_setElevation(AUD_Source* source, float elevation)
+{
+ assert(source);
+
+ (*source)->setElevation(elevation);
+}
+
+extern AUD_API void AUD_Source_setDistance(AUD_Source* source, float distance)
+{
+ assert(source);
+
+ (*source)->setDistance(distance);
+} \ No newline at end of file
diff --git a/extern/audaspace/bindings/C/AUD_Source.h b/extern/audaspace/bindings/C/AUD_Source.h
new file mode 100644
index 00000000000..6ff045ec848
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_Source.h
@@ -0,0 +1,84 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#pragma once
+
+#include "AUD_Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* Creates a new Source object.
+* \param azimuth The azimuth angle.
+* \param elevation The elevation angle.
+* \param elevation The distance value. [0,1]
+* \return The new Source object.
+*/
+extern AUD_API AUD_Source* AUD_Source_create(float azimuth, float elevation, float distance);
+
+/**
+* Deletes a Source object.
+* \param source The Source object to be deleted.
+*/
+extern AUD_API void AUD_Source_free(AUD_Source* source);
+
+/**
+* Retrieves the azimuth angle of a Source object.
+* \param source The Source object.
+* \return The azimuth angle.
+*/
+extern AUD_API float AUD_Source_getAzimuth(AUD_Source* source);
+
+/**
+* Retrieves the elevation angle oa a Source object.
+* \param source The Source object.
+* \return The elevation angle.
+*/
+extern AUD_API float AUD_Source_getElevation(AUD_Source* source);
+
+/**
+* Retrieves the distance of a Source object. [0,1]
+* \param source The Source object.
+* \return The distance.
+*/
+extern AUD_API float AUD_Source_getDistance(AUD_Source* distance);
+
+/**
+* Changes the azimuth angle of a Source object.
+* \param source The Source object.
+* \param azimuth The azimuth angle.
+*/
+extern AUD_API void AUD_Source_setAzimuth(AUD_Source* source, float azimuth);
+
+/**
+* Changes the elevation angle of a Source object.
+* \param source The Source object.
+* \param elevation The elevation angle.
+*/
+extern AUD_API void AUD_Source_setElevation(AUD_Source* source, float elevation);
+
+/**
+* Changes the distance of a Source object. [0,1]
+* \param source The Source object.
+* \param distance The distance.
+*/
+extern AUD_API void AUD_Source_setDistance(AUD_Source* source, float distance);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/extern/audaspace/bindings/C/AUD_Special.cpp b/extern/audaspace/bindings/C/AUD_Special.cpp
new file mode 100644
index 00000000000..f8f46651231
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_Special.cpp
@@ -0,0 +1,420 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#include "Exception.h"
+#include "IReader.h"
+#include "file/File.h"
+#include "respec/ChannelMapper.h"
+#include "fx/Lowpass.h"
+#include "fx/Highpass.h"
+#include "fx/Envelope.h"
+#include "respec/LinearResample.h"
+#include "fx/Threshold.h"
+#include "fx/Accumulator.h"
+#include "fx/Sum.h"
+#include "generator/Silence.h"
+#include "fx/Limiter.h"
+#include "devices/DeviceManager.h"
+#include "sequence/Sequence.h"
+#include "file/FileWriter.h"
+#include "devices/ReadDevice.h"
+#include "plugin/PluginManager.h"
+#include "devices/DeviceManager.h"
+#include "devices/IDeviceFactory.h"
+#include "devices/NULLDevice.h"
+
+#include <cassert>
+#include <cstring>
+#include <cmath>
+#include <sstream>
+
+using namespace aud;
+
+#define AUD_CAPI_IMPLEMENTATION
+#include "AUD_Special.h"
+
+static inline AUD_Specs convSpecToC(aud::Specs specs)
+{
+ AUD_Specs s;
+ s.channels = static_cast<AUD_Channels>(specs.channels);
+ s.rate = static_cast<AUD_SampleRate>(specs.rate);
+ return s;
+}
+
+static inline aud::Specs convCToSpec(AUD_Specs specs)
+{
+ aud::Specs s;
+ s.channels = static_cast<Channels>(specs.channels);
+ s.rate = static_cast<SampleRate>(specs.rate);
+ return s;
+}
+
+static inline AUD_DeviceSpecs convDSpecToC(aud::DeviceSpecs specs)
+{
+ AUD_DeviceSpecs s;
+ s.specs = convSpecToC(specs.specs);
+ s.format = static_cast<AUD_SampleFormat>(specs.format);
+ return s;
+}
+
+static inline aud::DeviceSpecs convCToDSpec(AUD_DeviceSpecs specs)
+{
+ aud::DeviceSpecs s;
+ s.specs = convCToSpec(specs.specs);
+ s.format = static_cast<SampleFormat>(specs.format);
+ return s;
+}
+
+AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound)
+{
+ assert(sound);
+
+ AUD_SoundInfo info;
+ info.specs.channels = AUD_CHANNELS_INVALID;
+ info.specs.rate = AUD_RATE_INVALID;
+ info.length = 0.0f;
+
+ try
+ {
+ std::shared_ptr<IReader> reader = (*sound)->createReader();
+
+ if(reader.get())
+ {
+ info.specs = convSpecToC(reader->getSpecs());
+ info.length = reader->getLength() / (float) info.specs.rate;
+ }
+ }
+ catch(Exception&)
+ {
+ }
+
+ return info;
+}
+
+AUD_API float* AUD_readSoundBuffer(const char* filename, float low, float high,
+ float attack, float release, float threshold,
+ int accumulate, int additive, int square,
+ float sthreshold, double samplerate, int* length)
+{
+ Buffer buffer;
+ DeviceSpecs specs;
+ specs.channels = CHANNELS_MONO;
+ specs.rate = (SampleRate)samplerate;
+ std::shared_ptr<ISound> sound;
+
+ std::shared_ptr<ISound> file = std::shared_ptr<ISound>(new File(filename));
+
+ int position = 0;
+
+ try
+ {
+ std::shared_ptr<IReader> reader = file->createReader();
+
+ SampleRate rate = reader->getSpecs().rate;
+
+ sound = std::shared_ptr<ISound>(new ChannelMapper(file, specs));
+
+ if(high < rate)
+ sound = std::shared_ptr<ISound>(new Lowpass(sound, high));
+ if(low > 0)
+ sound = std::shared_ptr<ISound>(new Highpass(sound, low));
+
+ sound = std::shared_ptr<ISound>(new Envelope(sound, attack, release, threshold, 0.1f));
+ sound = std::shared_ptr<ISound>(new LinearResample(sound, specs));
+
+ if(square)
+ sound = std::shared_ptr<ISound>(new Threshold(sound, sthreshold));
+
+ if(accumulate)
+ sound = std::shared_ptr<ISound>(new Accumulator(sound, additive));
+ else if(additive)
+ sound = std::shared_ptr<ISound>(new Sum(sound));
+
+ reader = sound->createReader();
+
+ if(!reader.get())
+ return nullptr;
+
+ int len;
+ bool eos;
+ do
+ {
+ len = samplerate;
+ buffer.resize((position + len) * sizeof(float), true);
+ reader->read(len, eos, buffer.getBuffer() + position);
+ position += len;
+ } while(!eos);
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+
+ float * result = (float *)malloc(position * sizeof(float));
+ std::memcpy(result, buffer.getBuffer(), position * sizeof(float));
+ *length = position;
+ return result;
+}
+
+static void pauseSound(AUD_Handle* handle)
+{
+ assert(handle);
+ (*handle)->pause();
+}
+
+AUD_API AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds)
+{
+ std::shared_ptr<ISound> silence = std::shared_ptr<ISound>(new Silence);
+ std::shared_ptr<ISound> limiter = std::shared_ptr<ISound>(new Limiter(silence, 0, seconds));
+
+ auto device = DeviceManager::getDevice();
+
+ std::lock_guard<ILockable> lock(*device);
+
+ try
+ {
+ AUD_Handle handle2 = device->play(limiter);
+ if(handle2.get())
+ {
+ handle2->setStopCallback((stopCallback)pauseSound, handle);
+ return new AUD_Handle(handle2);
+ }
+ }
+ catch(Exception&)
+ {
+ }
+
+ return nullptr;
+}
+
+AUD_API int AUD_readSound(AUD_Sound* sound, float* buffer, int length, int samples_per_second, short* interrupt)
+{
+ DeviceSpecs specs;
+ float* buf;
+ Buffer aBuffer;
+
+ specs.rate = RATE_INVALID;
+ specs.channels = CHANNELS_MONO;
+ specs.format = FORMAT_INVALID;
+
+ std::shared_ptr<IReader> reader = ChannelMapper(*sound, specs).createReader();
+
+ specs.specs = reader->getSpecs();
+ int len;
+ float samplejump = specs.rate / samples_per_second;
+ float min, max, power, overallmax;
+ bool eos;
+
+ overallmax = 0;
+
+ for(int i = 0; i < length; i++)
+ {
+ len = floor(samplejump * (i+1)) - floor(samplejump * i);
+
+ if(*interrupt)
+ return 0;
+
+ aBuffer.assureSize(len * AUD_SAMPLE_SIZE(specs));
+ buf = aBuffer.getBuffer();
+
+ reader->read(len, eos, buf);
+
+ max = min = *buf;
+ power = *buf * *buf;
+ for(int j = 1; j < len; j++)
+ {
+ if(buf[j] < min)
+ min = buf[j];
+ if(buf[j] > max)
+ max = buf[j];
+ power += buf[j] * buf[j];
+ }
+
+ buffer[i * 3] = min;
+ buffer[i * 3 + 1] = max;
+ buffer[i * 3 + 2] = sqrt(power) / len;
+
+ if(overallmax < max)
+ overallmax = max;
+ if(overallmax < -min)
+ overallmax = -min;
+
+ if(eos)
+ {
+ length = i;
+ break;
+ }
+ }
+
+ if(overallmax > 1.0f)
+ {
+ for(int i = 0; i < length * 3; i++)
+ {
+ buffer[i] /= overallmax;
+ }
+ }
+
+ return length;
+}
+
+AUD_API const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate)
+{
+ try
+ {
+ Sequence* f = dynamic_cast<Sequence *>(sound->get());
+
+ f->setSpecs(convCToSpec(specs.specs));
+ std::shared_ptr<IReader> reader = f->createQualityReader();
+ reader->seek(start);
+ std::shared_ptr<IWriter> writer = FileWriter::createWriter(filename, convCToDSpec(specs), static_cast<Container>(format), static_cast<Codec>(codec), bitrate);
+ FileWriter::writeReader(reader, writer, length, buffersize);
+
+ return nullptr;
+ }
+ catch(Exception& e)
+ {
+ return e.getMessage().c_str();
+ }
+}
+
+AUD_API const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate)
+{
+ try
+ {
+ Sequence* f = dynamic_cast<Sequence *>(sound->get());
+
+ f->setSpecs(convCToSpec(specs.specs));
+
+ std::vector<std::shared_ptr<IWriter> > writers;
+
+ int channels = specs.channels;
+ specs.channels = AUD_CHANNELS_MONO;
+
+ for(int i = 0; i < channels; i++)
+ {
+ std::stringstream stream;
+ std::string fn = filename;
+ size_t index = fn.find_last_of('.');
+ size_t index_slash = fn.find_last_of('/');
+ size_t index_backslash = fn.find_last_of('\\');
+
+ if((index == std::string::npos) ||
+ ((index < index_slash) && (index_slash != std::string::npos)) ||
+ ((index < index_backslash) && (index_backslash != std::string::npos)))
+ {
+ stream << filename << "_" << (i + 1);
+ }
+ else
+ {
+ stream << fn.substr(0, index) << "_" << (i + 1) << fn.substr(index);
+ }
+ writers.push_back(FileWriter::createWriter(stream.str(), convCToDSpec(specs), static_cast<Container>(format), static_cast<Codec>(codec), bitrate));
+ }
+
+ std::shared_ptr<IReader> reader = f->createQualityReader();
+ reader->seek(start);
+ FileWriter::writeReader(reader, writers, length, buffersize);
+
+ return nullptr;
+ }
+ catch(Exception& e)
+ {
+ return e.getMessage().c_str();
+ }
+}
+
+AUD_API AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, float start)
+{
+ try
+ {
+ ReadDevice* device = new ReadDevice(convCToDSpec(specs));
+ device->setQuality(true);
+ device->setVolume(volume);
+
+ Sequence* f = dynamic_cast<Sequence*>(sequencer->get());
+
+ f->setSpecs(convCToSpec(specs.specs));
+
+ AUD_Handle handle = device->play(f->createQualityReader());
+ if(handle.get())
+ {
+ handle->seek(start);
+ }
+
+ return new AUD_Device(device);
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API void AUD_initOnce()
+{
+ PluginManager::loadPlugins();
+ NULLDevice::registerPlugin();
+}
+
+AUD_API void AUD_exitOnce()
+{
+}
+
+AUD_API AUD_Device* AUD_init(const char* device, AUD_DeviceSpecs specs, int buffersize, const char* name)
+{
+ try
+ {
+ std::shared_ptr<IDeviceFactory> factory = DeviceManager::getDeviceFactory(device);
+
+ if(factory)
+ {
+ factory->setName(name);
+ factory->setBufferSize(buffersize);
+ factory->setSpecs(convCToDSpec(specs));
+ auto device = factory->openDevice();
+ DeviceManager::setDevice(device);
+
+ return new AUD_Device(device);
+ }
+ }
+ catch(Exception&)
+ {
+ }
+ return nullptr;
+}
+
+AUD_API void AUD_exit(AUD_Device* device)
+{
+ delete device;
+ DeviceManager::releaseDevice();
+}
+
+
+AUD_API char** AUD_getDeviceNames()
+{
+ std::vector<std::string> v_names = DeviceManager::getAvailableDeviceNames();
+ char** names = (char**) malloc(sizeof(char*) * (v_names.size() + 1));
+
+ for(int i = 0; i < v_names.size(); i++)
+ {
+ std::string name = v_names[i];
+ names[i] = (char*) malloc(sizeof(char) * (name.length() + 1));
+ strcpy(names[i], name.c_str());
+ }
+
+ names[v_names.size()] = nullptr;
+
+ return names;
+}
diff --git a/extern/audaspace/bindings/C/AUD_Special.h b/extern/audaspace/bindings/C/AUD_Special.h
new file mode 100644
index 00000000000..ab79ae915a2
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_Special.h
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+#include "AUD_Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Returns information about a sound.
+ * \param sound The sound to get the info about.
+ * \return The AUD_SoundInfo structure with filled in data.
+ */
+extern AUD_API AUD_SoundInfo AUD_getInfo(AUD_Sound* sound);
+
+/**
+ * Reads a sound file into a newly created float buffer.
+ * The sound is therefore bandpassed, rectified and resampled.
+ */
+extern AUD_API float* AUD_readSoundBuffer(const char* filename, float low, float high,
+ float attack, float release, float threshold,
+ int accumulate, int additive, int square,
+ float sthreshold, double samplerate,
+ int* length);
+
+/**
+ * Pauses a playing sound after a specific amount of time.
+ * \param handle The handle to the sound.
+ * \param seconds The time in seconds.
+ * \return The silence handle.
+ */
+extern AUD_API AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds);
+
+/**
+ * Reads a sound into a buffer for drawing at a specific sampling rate.
+ * \param sound The sound to read.
+ * \param buffer The buffer to write to. Must have a size of 3*4*length.
+ * \param length How many samples to read from the sound.
+ * \param samples_per_second How many samples to read per second of the sound.
+ * \return How many samples really have been read. Always <= length.
+ */
+extern AUD_API int AUD_readSound(AUD_Sound* sound, float* buffer, int length, int samples_per_second, short* interrupt);
+
+/**
+ * Mixes a sound down into a file.
+ * \param sound The sound scene to mix down.
+ * \param start The start frame.
+ * \param length The count of frames to write.
+ * \param buffersize How many samples should be written at once.
+ * \param filename The file to write to.
+ * \param specs The file's audio specification.
+ * \param format The file's container format.
+ * \param codec The codec used for encoding the audio data.
+ * \param bitrate The bitrate for encoding.
+ * \return An error message or NULL in case of success.
+ */
+extern AUD_API const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length,
+ unsigned int buffersize, const char* filename,
+ AUD_DeviceSpecs specs, AUD_Container format,
+ AUD_Codec codec, unsigned int bitrate);
+
+/**
+ * Mixes a sound down into multiple files.
+ * \param sound The sound scene to mix down.
+ * \param start The start frame.
+ * \param length The count of frames to write.
+ * \param buffersize How many samples should be written at once.
+ * \param filename The file to write to, the channel number and an underscore are added at the beginning.
+ * \param specs The file's audio specification.
+ * \param format The file's container format.
+ * \param codec The codec used for encoding the audio data.
+ * \param bitrate The bitrate for encoding.
+ * \return An error message or NULL in case of success.
+ */
+extern AUD_API const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length,
+ unsigned int buffersize, const char* filename,
+ AUD_DeviceSpecs specs, AUD_Container format,
+ AUD_Codec codec, unsigned int bitrate);
+
+/**
+ * Opens a read device and prepares it for mixdown of the sound scene.
+ * \param specs Output audio specifications.
+ * \param sequencer The sound scene to mix down.
+ * \param volume The overall mixdown volume.
+ * \param start The start time of the mixdown in the sound scene.
+ * \return The read device for the mixdown.
+ */
+extern AUD_API AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, float start);
+
+/**
+ * Initializes audio routines (FFMPEG/JACK if it is enabled).
+ */
+extern AUD_API void AUD_initOnce();
+
+/**
+ * Unitinitializes an audio routines.
+ */
+extern AUD_API void AUD_exitOnce();
+
+/**
+ * Initializes an audio device.
+ * \param device The device type that should be used.
+ * \param specs The audio specification to be used.
+ * \param buffersize The buffersize for the device.
+ * \return Whether the device has been initialized.
+ */
+extern AUD_API AUD_Device* AUD_init(const char* device, AUD_DeviceSpecs specs, int buffersize, const char* name);
+
+/**
+ * Unitinitializes an audio device.
+ * \param device The device to free.
+ */
+extern AUD_API void AUD_exit(AUD_Device* device);
+
+/**
+ * Retrieves available devices. Note that all memory returned has to be freed!
+ */
+extern AUD_API char** AUD_getDeviceNames();
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/extern/audaspace/bindings/C/AUD_ThreadPool.cpp b/extern/audaspace/bindings/C/AUD_ThreadPool.cpp
new file mode 100644
index 00000000000..f22a904838b
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_ThreadPool.cpp
@@ -0,0 +1,42 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#include "Exception.h"
+
+#include <cassert>
+
+using namespace aud;
+
+#define AUD_CAPI_IMPLEMENTATION
+#include "AUD_ThreadPool.h"
+
+AUD_API AUD_ThreadPool* AUD_ThreadPool_create(int nThreads)
+{
+ try
+ {
+ return new AUD_ThreadPool(new ThreadPool(nThreads));
+ }
+ catch(Exception&)
+ {
+ return nullptr;
+ }
+}
+
+AUD_API void AUD_ThreadPool_free(AUD_ThreadPool* pool)
+{
+ assert(pool);
+ delete pool;
+} \ No newline at end of file
diff --git a/extern/audaspace/bindings/C/AUD_ThreadPool.h b/extern/audaspace/bindings/C/AUD_ThreadPool.h
new file mode 100644
index 00000000000..c1b2204a80a
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_ThreadPool.h
@@ -0,0 +1,40 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#pragma once
+
+#include "AUD_Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* Creates a new ThreadPool object.
+* \param nThreads The number of threads of the pool.
+* \return The new ThreadPool object.
+*/
+extern AUD_API AUD_ThreadPool* AUD_ThreadPool_create(int nThreads);
+
+/**
+* Deletes a ThreadPool object.
+* \param threadPool The ThreadPool object to be deleted.
+*/
+extern AUD_API void AUD_ThreadPool_free(AUD_ThreadPool* threadPool);
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/extern/audaspace/bindings/C/AUD_Types.h b/extern/audaspace/bindings/C/AUD_Types.h
new file mode 100644
index 00000000000..75e4ffae18c
--- /dev/null
+++ b/extern/audaspace/bindings/C/AUD_Types.h
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+#include "Audaspace.h"
+
+#ifdef __cplusplus
+using namespace aud;
+#endif
+
+#ifdef AUD_CAPI_IMPLEMENTATION
+#include "ISound.h"
+#include "devices/IHandle.h"
+#include "devices/IDevice.h"
+#include "sequence/SequenceEntry.h"
+#include "fx/PlaybackManager.h"
+#include "fx/DynamicMusic.h"
+#include "fx/Source.h"
+#include "util/ThreadPool.h"
+#ifdef WITH_CONVOLUTION
+#include "fx/ImpulseResponse.h"
+#include "fx/HRTF.h"
+#endif
+
+typedef std::shared_ptr<aud::ISound> AUD_Sound;
+typedef std::shared_ptr<aud::IHandle> AUD_Handle;
+typedef std::shared_ptr<aud::IDevice> AUD_Device;
+typedef std::shared_ptr<aud::SequenceEntry> AUD_SequenceEntry;
+typedef std::shared_ptr<aud::PlaybackManager> AUD_PlaybackManager;
+typedef std::shared_ptr<aud::DynamicMusic> AUD_DynamicMusic;
+typedef std::shared_ptr<aud::ThreadPool> AUD_ThreadPool;
+typedef std::shared_ptr<aud::Source> AUD_Source;
+#ifdef WITH_CONVOLUTION
+typedef std::shared_ptr<aud::ImpulseResponse> AUD_ImpulseResponse;
+typedef std::shared_ptr<aud::HRTF> AUD_HRTF;
+#endif
+#else
+typedef void AUD_Sound;
+typedef void AUD_Handle;
+typedef void AUD_Device;
+typedef void AUD_SequenceEntry;
+typedef void AUD_PlaybackManager;
+typedef void AUD_DynamicMusic;
+typedef void AUD_ThreadPool;
+typedef void AUD_Source;
+#ifdef WITH_CONVOLUTION
+typedef void AUD_ImpulseResponse;
+typedef void AUD_HRTF;
+#endif
+#endif
+
+/// Container formats for writers.
+typedef enum
+{
+ AUD_CONTAINER_INVALID = 0,
+ AUD_CONTAINER_AC3,
+ AUD_CONTAINER_FLAC,
+ AUD_CONTAINER_MATROSKA,
+ AUD_CONTAINER_MP2,
+ AUD_CONTAINER_MP3,
+ AUD_CONTAINER_OGG,
+ AUD_CONTAINER_WAV
+} AUD_Container;
+
+/// Audio codecs for writers.
+typedef enum
+{
+ AUD_CODEC_INVALID = 0,
+ AUD_CODEC_AAC,
+ AUD_CODEC_AC3,
+ AUD_CODEC_FLAC,
+ AUD_CODEC_MP2,
+ AUD_CODEC_MP3,
+ AUD_CODEC_PCM,
+ AUD_CODEC_VORBIS,
+ AUD_CODEC_OPUS
+} AUD_Codec;
+
+/**
+ * The format of a sample.
+ * The last 4 bit save the byte count of the format.
+ */
+typedef enum
+{
+ AUD_FORMAT_INVALID = 0x00, /// Invalid sample format.
+ AUD_FORMAT_U8 = 0x01, /// 1 byte unsigned byte.
+ 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_FLOAT32 = 0x24, /// 4 byte float.
+ AUD_FORMAT_FLOAT64 = 0x28 /// 8 byte float.
+} AUD_SampleFormat;
+
+/// The channel count.
+typedef enum
+{
+ AUD_CHANNELS_INVALID = 0, /// Invalid channel count.
+ AUD_CHANNELS_MONO = 1, /// Mono.
+ AUD_CHANNELS_STEREO = 2, /// Stereo.
+ AUD_CHANNELS_STEREO_LFE = 3, /// Stereo with LFE channel.
+ AUD_CHANNELS_SURROUND4 = 4, /// 4 channel surround sound.
+ AUD_CHANNELS_SURROUND5 = 5, /// 5 channel surround sound.
+ AUD_CHANNELS_SURROUND51 = 6, /// 5.1 surround sound.
+ AUD_CHANNELS_SURROUND61 = 7, /// 6.1 surround sound.
+ AUD_CHANNELS_SURROUND71 = 8 /// 7.1 surround sound.
+} AUD_Channels;
+
+/**
+ * The sample rate tells how many samples are played back within one second.
+ * Some exotic formats may use other sample rates than provided here.
+ */
+typedef enum
+{
+ AUD_RATE_INVALID = 0, /// Invalid sample rate.
+ AUD_RATE_8000 = 8000, /// 8000 Hz.
+ AUD_RATE_16000 = 16000, /// 16000 Hz.
+ AUD_RATE_11025 = 11025, /// 11025 Hz.
+ AUD_RATE_22050 = 22050, /// 22050 Hz.
+ AUD_RATE_32000 = 32000, /// 32000 Hz.
+ AUD_RATE_44100 = 44100, /// 44100 Hz.
+ AUD_RATE_48000 = 48000, /// 48000 Hz.
+ AUD_RATE_88200 = 88200, /// 88200 Hz.
+ AUD_RATE_96000 = 96000, /// 96000 Hz.
+ AUD_RATE_192000 = 192000 /// 192000 Hz.
+} AUD_DefaultSampleRate;
+
+/// Sample rate type.
+typedef double AUD_SampleRate;
+
+/// Specification of a sound source.
+typedef struct
+{
+ /// Sample rate in Hz.
+ AUD_SampleRate rate;
+
+ /// Channel count.
+ AUD_Channels channels;
+} AUD_Specs;
+
+/// Specification of a sound device.
+typedef struct
+{
+ /// Sample format.
+ AUD_SampleFormat format;
+
+ union
+ {
+ struct
+ {
+ /// Sample rate in Hz.
+ AUD_SampleRate rate;
+
+ /// Channel count.
+ AUD_Channels channels;
+ };
+ AUD_Specs specs;
+ };
+} AUD_DeviceSpecs;
+
+/// Sound information structure.
+typedef struct
+{
+ AUD_Specs specs;
+ float length;
+} AUD_SoundInfo;
diff --git a/extern/audaspace/bindings/doc/conf.py.in b/extern/audaspace/bindings/doc/conf.py.in
new file mode 100644
index 00000000000..e08efbcf7f6
--- /dev/null
+++ b/extern/audaspace/bindings/doc/conf.py.in
@@ -0,0 +1,261 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# audaspace documentation build configuration file, created by
+# sphinx-quickstart on Tue Sep 9 01:48:48 2014.
+#
+# This file is execfile()d with the current directory set to its
+# containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys
+import os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.insert(0, os.path.abspath('.'))
+
+# -- General configuration ------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ 'sphinx.ext.autodoc',
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = []
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'audaspace'
+copyright = '2009-2015, Jörg Müller'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '@AUDASPACE_VERSION@'
+# The full version, including alpha/beta/rc tags.
+release = '@AUDASPACE_LONG_VERSION@'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = []
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'alabaster'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = []
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'audaspacedoc'
+
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ ('index', 'audaspace.tex', 'audaspace Documentation',
+ 'Jörg Müller', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'audaspace', 'audaspace Documentation',
+ ['Jörg Müller'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'audaspace', 'audaspace Documentation',
+ 'Jörg Müller', 'audaspace', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
diff --git a/extern/audaspace/bindings/doc/device.rst b/extern/audaspace/bindings/doc/device.rst
new file mode 100644
index 00000000000..fd6b334022c
--- /dev/null
+++ b/extern/audaspace/bindings/doc/device.rst
@@ -0,0 +1,7 @@
+Device
+======
+
+.. currentmodule:: aud
+.. autoclass:: Device
+ :members:
+
diff --git a/extern/audaspace/bindings/doc/handle.rst b/extern/audaspace/bindings/doc/handle.rst
new file mode 100644
index 00000000000..aceedbca3a6
--- /dev/null
+++ b/extern/audaspace/bindings/doc/handle.rst
@@ -0,0 +1,7 @@
+Handle
+======
+
+.. currentmodule:: aud
+.. autoclass:: Handle
+ :members:
+
diff --git a/extern/audaspace/bindings/doc/index.rst b/extern/audaspace/bindings/doc/index.rst
new file mode 100644
index 00000000000..b8a26822949
--- /dev/null
+++ b/extern/audaspace/bindings/doc/index.rst
@@ -0,0 +1,35 @@
+.. audaspace documentation master file, created by
+ sphinx-quickstart on Tue Sep 9 01:48:48 2014.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to audaspace's documentation!
+=====================================
+
+.. automodule:: aud
+
+This documentation is valid for both the Python and C bindings of audaspace. If you are looking for installation instructions check the `C++ API documentation <../index.html>`_. As C is not an object oriented language everything is accessible via functions where the first paramter is always the object. For methods these are named as ``AUD_ClassName_method()`` and properties are accessed via ``AUD_ClassName_property_get/set()``. Python users simply ``import aud`` to access the library.
+
+.. toctree::
+ :maxdepth: 2
+
+ tutorials
+
+Classes:
+
+.. toctree::
+ :maxdepth: 2
+
+ device
+ sound
+ handle
+ sequence
+ sequence_entry
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
diff --git a/extern/audaspace/bindings/doc/sequence.rst b/extern/audaspace/bindings/doc/sequence.rst
new file mode 100644
index 00000000000..16fcb00f4dc
--- /dev/null
+++ b/extern/audaspace/bindings/doc/sequence.rst
@@ -0,0 +1,7 @@
+Sequence
+========
+
+.. currentmodule:: aud
+.. autoclass:: Sequence
+ :members:
+
diff --git a/extern/audaspace/bindings/doc/sequence_entry.rst b/extern/audaspace/bindings/doc/sequence_entry.rst
new file mode 100644
index 00000000000..0a3d83388e9
--- /dev/null
+++ b/extern/audaspace/bindings/doc/sequence_entry.rst
@@ -0,0 +1,7 @@
+Sequence Entry
+==============
+
+.. currentmodule:: aud
+.. autoclass:: SequenceEntry
+ :members:
+
diff --git a/extern/audaspace/bindings/doc/sound.rst b/extern/audaspace/bindings/doc/sound.rst
new file mode 100644
index 00000000000..2f14721cf3a
--- /dev/null
+++ b/extern/audaspace/bindings/doc/sound.rst
@@ -0,0 +1,7 @@
+Sound
+=====
+
+.. currentmodule:: aud
+.. autoclass:: Sound
+ :members:
+
diff --git a/extern/audaspace/bindings/doc/tutorials.rst b/extern/audaspace/bindings/doc/tutorials.rst
new file mode 100644
index 00000000000..55f51d9ee2f
--- /dev/null
+++ b/extern/audaspace/bindings/doc/tutorials.rst
@@ -0,0 +1,166 @@
+Tutorials
+=========
+
+Introduction
+------------
+
+The C and Python binding for audaspace were designed with simplicity in mind. This means however that to use the full capabilities of audaspace, there is no way around the C++ library.
+
+Simple Demo
+-----------
+
+The **simple.py** example program contains all the basic building blocks for an application using audaspace. These building blocks are basically the classes :class:`aud.Device`, :class:`aud.Sound` and :class:`aud.Handle`.
+
+We start with importing :mod:`aud` and :mod:`time` as the modules we need for our simple example.
+
+.. code-block:: python
+
+ #!/usr/bin/python
+ import aud, time
+
+The first step now is to open an output device and this can simply be done by allocating a :class:`aud.Device` object.
+
+.. code-block:: python
+
+ device = aud.Device()
+
+To create a sound we can choose to load one from a :func:`aud.Sound.file`, or we use one of our signal generators. We decide to do the latter and create a :func:`aud.Sound.sine` signal with a frequency of 440 Hz.
+
+.. code-block:: python
+
+ sine = aud.Sound.sine(440)
+
+.. note:: At this point nothing is playing back yet, :class:`aud.Sound` objects are just descriptions of sounds.
+
+However instead of a sine wave, we would like to have a square wave to produce a more retro gaming sound. We could of course use the :func:`aud.Sound.square` generator instead of sine, but we want to show how to apply effects, so we apply a :func:`aud.Sound.threshold` which makes a square wave out of our sine too, even if less efficient than directly generating the square wave.
+
+.. code-block:: python
+
+ square = sine.threshold()
+
+.. note:: The :class:`aud.Sound` class offers generator and effect functions.
+
+The we can play our sound by calling the :func:`aud.Device.play` method of our device. This method returns a :class:`aud.Handle` which is used to control the playback of the sound.
+
+.. code-block:: python
+
+ handle = device.play(square)
+
+Now if we do nothing else anymore the application will quit immediately, so we won't hear much of our square wave, so we decide to wait for three seconds before quitting the application by calling :func:`time.sleep`.
+
+.. code-block:: python
+
+ time.sleep(3)
+
+Audioplayer
+-----------
+
+Now that we know the basics of audaspace, we can build our own music player easily by just slightly changing the previous program. The **player.py** example does exactly that, let's have a short look at the differences:
+
+Instead of creating a sine signal and thresholding it, we in fact use the :func:`aud.Sound.file` function to load a sound from a file. The filename we pass is the first command line argument our application got.
+
+.. code-block:: python
+
+ sound = aud.Sound.file(sys.argv[1])
+
+When the sound gets played back we now want to wait until the whole file has been played, so we use the :data:`aud.Handle.status` property to determine whether the sound finished playing.
+
+.. code-block:: python
+
+ while handle.status:
+ time.sleep(0.1)
+
+We don't make any error checks if the user actually added a command line argument. As an exercise you could extend this program to play any number of command line supplied files in sequence.
+
+Siren
+-----
+
+Let's get a little bit more complex. The **siren.py** example plays a generated siren sound that circles around your head. Depending on how many speakers you have and if the output device used supports the speaker setup, you will hear this effect. With stereo speakers you should at least hear some left-right-panning.
+
+We start off again with importing the modules we need and we also define some properties of our siren sound. We want it to consist of two sine sounds with different frequencies. We define a length for the sine sounds and how long a fade in/out should take. We also know already how to open a device.
+
+.. code-block:: python
+
+ #!/usr/bin/python
+ import aud, math, time
+ length = 0.5
+ fadelength = 0.05
+
+ device = aud.Device()
+
+The next thing to do is to define our sine waves and apply all the required effects. As each of the effect functions returns the corresponding sound, we can easily chain those calls together.
+
+.. code-block:: python
+
+ high = aud.Sound.sine(880).limit(0, length).fadein(0, fadelength).fadeout(length - fadelength, length)
+ low = aud.Sound.sine(700).limit(0, length).fadein(0, fadelength).fadeout(length - fadelength, length).volume(0.6)
+
+The next step is to connect the two sines, which we do using the :func:`aud.Sound.join` function.
+
+.. code-block:: python
+
+ sound = high.join(low)
+
+The generated siren sound can now be played back and what we also do is to loop it. Therefore we set the :data:`aud.Handle.loop_count` to a negative value to loop forever.
+
+.. code-block:: python
+
+ handle = device.play(sound)
+ handle.loop_count = -1
+
+Now we use some timing code to make sure our demo runs for 10 seconds, but we also use the time to update the location of our playing sound, with the :data:`aud.Handle.location` property, which is a three dimensional vector. The trigonometic calculation based on the running time of the program keeps the sound on the XZ plane letting it follow a circle around us.
+
+.. code-block:: python
+
+ start = time.time()
+
+ while time.time() - start < 10:
+ angle = time.time() - start
+
+ handle.location = [math.sin(angle), 0, -math.cos(angle)]
+
+As an exercise you could try to let the sound come from the far left and go to the far right and a little bit in front of you within the 10 second runtime of the program. With this change you should be able to hear the volume of the sound change, depending on how far it is away from you. Updating the :data:`aud.Handle.velocity` property properly also enables the doppler effect. Compare your solution to the **siren2.py** demo.
+
+Tetris
+------
+
+The **tetris.py** demo application shows an even more complex application which generates retro tetris music. Looking at the source code there should be nothing new here, again the functions used from audaspace are the same as in the previous examples. In the :func:`parseNote` function all single notes get joined which leads to a very long chain of sounds. If you think of :func:`aud.Sound.join` as a function that creates a binary tree with the two joined sounds as leaves then the :func:`parseNote` function creates a very unbalanced tree.
+
+Insted we could rewrite the code to use two other classes: :class:`aud.Sequence` and :class:`aud.SequenceEntry` to sequence the notes. The **tetris2.py** application does exactly that. Before the while loop we add a variable that stores the current position in the score and create a new :class:`aud.Sequence` object.
+
+.. code-block:: python
+
+ position = 0
+ sequence = aud.Sequence()
+
+Then in the loop we can create the note simply by chaining the :func:`aud.Sound.square` generator and :func:`aud.Sound.fadein` and :func:`aud.Sound.fadeout` effects.
+
+.. code-block:: python
+
+ note = aud.Sound.square(freq, rate).fadein(0, fadelength).fadeout(length - fadelength, fadelength)
+
+Now instead of using :func:`aud.Sound.limit` and :func:`aud.Sound.join` we simply add the sound to the sequence.
+
+.. code-block:: python
+
+ entry = sequence.add(note, position, position + length, 0)
+
+The entry returned from the :func:`aud.Sequence.add` function is an object of the :class:`aud.SequenceEntry` class. We can use this entry to mute the note in case it's actually a pause.
+
+.. code-block:: python
+
+ if char == 'p':
+ entry.muted = True
+
+Lastly we have to update our position variable.
+
+.. code-block:: python
+
+ position += length
+
+Now in **tetris2.py** we used the :data:`aud.SequenceEntry.muted` property to show how the :class:`aud.SequenceEntry` class can be used, but it would actually be smarter to not even create a note for pauses and just skip them. You can try to implement this as an exercise and then check out the solution in **tetris3.py**.
+
+Conclusion
+----------
+
+We introduced all five currently available classes in the audaspace Python API. Of course all classes offer a lot more functions than have been used in these demo applications, check out the specific class documentation for more details.
diff --git a/extern/audaspace/bindings/python/PyAPI.cpp b/extern/audaspace/bindings/python/PyAPI.cpp
new file mode 100644
index 00000000000..cceadbc0992
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyAPI.cpp
@@ -0,0 +1,231 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#include "PyAPI.h"
+#include "PySound.h"
+#include "PyHandle.h"
+#include "PyDevice.h"
+#include "PySequenceEntry.h"
+#include "PySequence.h"
+#include "PyPlaybackManager.h"
+#include "PyDynamicMusic.h"
+#include "PyThreadPool.h"
+#include "PySource.h"
+
+#ifdef WITH_CONVOLUTION
+#include "PyImpulseResponse.h"
+#include "PyHRTF.h"
+#endif
+
+#include "respec/Specification.h"
+#include "devices/IHandle.h"
+#include "devices/I3DDevice.h"
+#include "file/IWriter.h"
+#include "plugin/PluginManager.h"
+#include "sequence/AnimateableProperty.h"
+#include "ISound.h"
+
+#include <memory>
+
+#include <structmember.h>
+
+using namespace aud;
+
+// ====================================================================
+
+#define PY_MODULE_ADD_CONSTANT(module, name) PyModule_AddIntConstant(module, #name, name)
+
+// ====================================================================
+
+extern PyObject* AUDError;
+PyObject* AUDError = nullptr;
+
+// ====================================================================
+
+PyDoc_STRVAR(M_aud_doc,
+ "Audaspace (pronounced \"outer space\") is a high level audio library.");
+
+static struct PyModuleDef audmodule = {
+ PyModuleDef_HEAD_INIT,
+ "aud", /* name of module */
+ M_aud_doc, /* module documentation */
+ -1, /* size of per-interpreter state of the module,
+ or -1 if the module keeps state in global variables. */
+ nullptr, nullptr, nullptr, nullptr, nullptr
+};
+
+PyMODINIT_FUNC
+PyInit_aud()
+{
+ PyObject* module;
+
+ PluginManager::loadPlugins();
+
+ if(!initializeSound())
+ return nullptr;
+
+ if(!initializeDevice())
+ return nullptr;
+
+ if(!initializeHandle())
+ return nullptr;
+
+ if(!initializeSequenceEntry())
+ return nullptr;
+
+ if(!initializeSequence())
+ return nullptr;
+
+ if(!initializeDynamicMusic())
+ return nullptr;
+
+ if(!initializePlaybackManager())
+ return nullptr;
+
+ if(!initializeThreadPool())
+ return nullptr;
+
+ if(!initializeSource())
+ return nullptr;
+
+#ifdef WITH_CONVOLUTION
+ if(!initializeImpulseResponse())
+ return nullptr;
+
+ if(!initializeHRTF())
+ return nullptr;
+#endif
+
+ module = PyModule_Create(&audmodule);
+ if(module == nullptr)
+ return nullptr;
+
+ addSoundToModule(module);
+ addHandleToModule(module);
+ addDeviceToModule(module);
+ addSequenceEntryToModule(module);
+ addSequenceToModule(module);
+ addDynamicMusicToModule(module);
+ addPlaybackManagerToModule(module);
+ addThreadPoolToModule(module);
+ addSourceToModule(module);
+
+#ifdef WITH_CONVOLUTION
+ addImpulseResponseToModule(module);
+ addHRTFToModule(module);
+#endif
+
+ AUDError = PyErr_NewException("aud.error", nullptr, nullptr);
+ Py_INCREF(AUDError);
+ PyModule_AddObject(module, "error", AUDError);
+
+ // animatable property type constants
+ PY_MODULE_ADD_CONSTANT(module, AP_VOLUME);
+ PY_MODULE_ADD_CONSTANT(module, AP_PANNING);
+ PY_MODULE_ADD_CONSTANT(module, AP_PITCH);
+ PY_MODULE_ADD_CONSTANT(module, AP_LOCATION);
+ PY_MODULE_ADD_CONSTANT(module, AP_ORIENTATION);
+ // channels constants
+ PY_MODULE_ADD_CONSTANT(module, CHANNELS_INVALID);
+ PY_MODULE_ADD_CONSTANT(module, CHANNELS_MONO);
+ PY_MODULE_ADD_CONSTANT(module, CHANNELS_STEREO);
+ PY_MODULE_ADD_CONSTANT(module, CHANNELS_STEREO_LFE);
+ PY_MODULE_ADD_CONSTANT(module, CHANNELS_SURROUND4);
+ PY_MODULE_ADD_CONSTANT(module, CHANNELS_SURROUND5);
+ PY_MODULE_ADD_CONSTANT(module, CHANNELS_SURROUND51);
+ PY_MODULE_ADD_CONSTANT(module, CHANNELS_SURROUND61);
+ PY_MODULE_ADD_CONSTANT(module, CHANNELS_SURROUND71);
+ // codec constants
+ PY_MODULE_ADD_CONSTANT(module, CODEC_INVALID);
+ PY_MODULE_ADD_CONSTANT(module, CODEC_AAC);
+ PY_MODULE_ADD_CONSTANT(module, CODEC_AC3);
+ PY_MODULE_ADD_CONSTANT(module, CODEC_FLAC);
+ PY_MODULE_ADD_CONSTANT(module, CODEC_MP2);
+ PY_MODULE_ADD_CONSTANT(module, CODEC_MP3);
+ PY_MODULE_ADD_CONSTANT(module, CODEC_PCM);
+ PY_MODULE_ADD_CONSTANT(module, CODEC_VORBIS);
+ PY_MODULE_ADD_CONSTANT(module, CODEC_OPUS);
+ // container constants
+ PY_MODULE_ADD_CONSTANT(module, CONTAINER_INVALID);
+ PY_MODULE_ADD_CONSTANT(module, CONTAINER_AC3);
+ PY_MODULE_ADD_CONSTANT(module, CONTAINER_FLAC);
+ PY_MODULE_ADD_CONSTANT(module, CONTAINER_MATROSKA);
+ PY_MODULE_ADD_CONSTANT(module, CONTAINER_MP2);
+ PY_MODULE_ADD_CONSTANT(module, CONTAINER_MP3);
+ PY_MODULE_ADD_CONSTANT(module, CONTAINER_OGG);
+ PY_MODULE_ADD_CONSTANT(module, CONTAINER_WAV);
+ // distance model constants
+ PY_MODULE_ADD_CONSTANT(module, DISTANCE_MODEL_EXPONENT);
+ PY_MODULE_ADD_CONSTANT(module, DISTANCE_MODEL_EXPONENT_CLAMPED);
+ PY_MODULE_ADD_CONSTANT(module, DISTANCE_MODEL_INVERSE);
+ PY_MODULE_ADD_CONSTANT(module, DISTANCE_MODEL_INVERSE_CLAMPED);
+ PY_MODULE_ADD_CONSTANT(module, DISTANCE_MODEL_LINEAR);
+ PY_MODULE_ADD_CONSTANT(module, DISTANCE_MODEL_LINEAR_CLAMPED);
+ PY_MODULE_ADD_CONSTANT(module, DISTANCE_MODEL_INVALID);
+ // format constants
+ PY_MODULE_ADD_CONSTANT(module, FORMAT_INVALID);
+ PY_MODULE_ADD_CONSTANT(module, FORMAT_FLOAT32);
+ PY_MODULE_ADD_CONSTANT(module, FORMAT_FLOAT64);
+ PY_MODULE_ADD_CONSTANT(module, FORMAT_INVALID);
+ PY_MODULE_ADD_CONSTANT(module, FORMAT_S16);
+ PY_MODULE_ADD_CONSTANT(module, FORMAT_S24);
+ PY_MODULE_ADD_CONSTANT(module, FORMAT_S32);
+ PY_MODULE_ADD_CONSTANT(module, FORMAT_U8);
+ // rate constants
+ PY_MODULE_ADD_CONSTANT(module, RATE_INVALID);
+ PY_MODULE_ADD_CONSTANT(module, RATE_8000);
+ PY_MODULE_ADD_CONSTANT(module, RATE_16000);
+ PY_MODULE_ADD_CONSTANT(module, RATE_11025);
+ PY_MODULE_ADD_CONSTANT(module, RATE_22050);
+ PY_MODULE_ADD_CONSTANT(module, RATE_32000);
+ PY_MODULE_ADD_CONSTANT(module, RATE_44100);
+ PY_MODULE_ADD_CONSTANT(module, RATE_48000);
+ PY_MODULE_ADD_CONSTANT(module, RATE_88200);
+ PY_MODULE_ADD_CONSTANT(module, RATE_96000);
+ PY_MODULE_ADD_CONSTANT(module, RATE_192000);
+ // status constants
+ PY_MODULE_ADD_CONSTANT(module, STATUS_INVALID);
+ PY_MODULE_ADD_CONSTANT(module, STATUS_PAUSED);
+ PY_MODULE_ADD_CONSTANT(module, STATUS_PLAYING);
+ PY_MODULE_ADD_CONSTANT(module, STATUS_STOPPED);
+
+ return module;
+}
+
+AUD_API PyObject* AUD_getPythonSound(void* sound)
+{
+ if(sound)
+ {
+ Sound* object = (Sound*) Sound_empty();
+ if(object)
+ {
+ object->sound = new std::shared_ptr<ISound>(*reinterpret_cast<std::shared_ptr<ISound>*>(sound));
+ return (PyObject *) object;
+ }
+ }
+
+ return nullptr;
+}
+
+AUD_API void* AUD_getSoundFromPython(PyObject* object)
+{
+ Sound* sound = checkSound(object);
+
+ if(!sound)
+ return nullptr;
+
+ return new std::shared_ptr<ISound>(*reinterpret_cast<std::shared_ptr<ISound>*>(sound->sound));
+}
diff --git a/extern/audaspace/bindings/python/PyAPI.h b/extern/audaspace/bindings/python/PyAPI.h
new file mode 100644
index 00000000000..a413b4813d6
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyAPI.h
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+#include <Python.h>
+#include "Audaspace.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PyMODINIT_FUNC
+PyInit_aud();
+
+/**
+ * Retrieves the python factory of a sound.
+ * \param sound The sound factory.
+ * \return The python factory.
+ */
+extern AUD_API PyObject* AUD_getPythonSound(void* sound);
+
+/**
+ * Retrieves the sound factory of a python factory.
+ * \param sound The python factory.
+ * \return The sound factory.
+ */
+extern AUD_API void* AUD_getSoundFromPython(PyObject* object);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/extern/audaspace/bindings/python/PyDevice.cpp b/extern/audaspace/bindings/python/PyDevice.cpp
new file mode 100644
index 00000000000..a6beef57d83
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyDevice.cpp
@@ -0,0 +1,785 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#include "PyDevice.h"
+
+#include "PySound.h"
+#include "PyHandle.h"
+
+#include "Exception.h"
+#include "devices/IDevice.h"
+#include "devices/I3DDevice.h"
+#include "devices/DeviceManager.h"
+#include "devices/IDeviceFactory.h"
+
+#include <structmember.h>
+
+using namespace aud;
+
+extern PyObject* AUDError;
+static const char* device_not_3d_error = "Device is not a 3D device!";
+
+// ====================================================================
+
+static void
+Device_dealloc(Device* self)
+{
+ if(self->device)
+ delete reinterpret_cast<std::shared_ptr<IDevice>*>(self->device);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *
+Device_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
+{
+ Device* self;
+
+ static const char* kwlist[] = {"type", "rate", "channels", "format", "buffer_size", "name", nullptr};
+ const char* device = nullptr;
+ double rate = RATE_48000;
+ int channels = CHANNELS_STEREO;
+ int format = FORMAT_FLOAT32;
+ int buffersize = AUD_DEFAULT_BUFFER_SIZE;
+ const char* name = "";
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "|sdiiis:Device", const_cast<char**>(kwlist),
+ &device, &rate, &channels, &format, &buffersize, &name))
+ return nullptr;
+
+ if(buffersize < 128)
+ {
+ PyErr_SetString(PyExc_ValueError, "buffer_size must be at least 128!");
+ return nullptr;
+ }
+
+ self = (Device*)type->tp_alloc(type, 0);
+
+ if(self != nullptr)
+ {
+ DeviceSpecs specs;
+ specs.channels = (Channels)channels;
+ specs.format = (SampleFormat)format;
+ specs.rate = (SampleRate)rate;
+
+ self->device = nullptr;
+
+ try
+ {
+ if(!device)
+ {
+ auto dev = DeviceManager::getDevice();
+ if(!dev)
+ {
+ DeviceManager::openDefaultDevice();
+ dev = DeviceManager::getDevice();
+ }
+ self->device = new std::shared_ptr<IDevice>(dev);
+ }
+ else
+ {
+ std::shared_ptr<IDeviceFactory> factory;
+ if(!*device)
+ factory = DeviceManager::getDefaultDeviceFactory();
+ else
+ factory = DeviceManager::getDeviceFactory(device);
+
+ if(factory)
+ {
+ factory->setName(name);
+ factory->setSpecs(specs);
+ factory->setBufferSize(buffersize);
+ self->device = new std::shared_ptr<IDevice>(factory->openDevice());
+ }
+ }
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+
+ if(!self->device)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, "Unsupported device type!");
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Device_lock_doc,
+ "lock()\n\n"
+ "Locks the device so that it's guaranteed, that no samples are "
+ "read from the streams until :meth:`unlock` is called.\n"
+ "This is useful if you want to do start/stop/pause/resume some "
+ "sounds at the same time.\n\n"
+ ".. note:: The device has to be unlocked as often as locked to be "
+ "able to continue playback.\n\n"
+ ".. warning:: Make sure the time between locking and unlocking is "
+ "as short as possible to avoid clicks.");
+
+static PyObject *
+Device_lock(Device* self)
+{
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<IDevice>*>(self->device))->lock();
+ Py_RETURN_NONE;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Device_play_doc,
+ "play(sound, keep=False)\n\n"
+ "Plays a sound.\n\n"
+ ":arg sound: The sound to play.\n"
+ ":type sound: :class:`Sound`\n"
+ ":arg keep: See :attr:`Handle.keep`.\n"
+ ":type keep: bool\n"
+ ":return: The playback handle with which playback can be "
+ "controlled with.\n"
+ ":rtype: :class:`Handle`");
+
+static PyObject *
+Device_play(Device* self, PyObject* args, PyObject* kwds)
+{
+ PyObject* object;
+ PyObject* keepo = nullptr;
+
+ bool keep = false;
+
+ static const char* kwlist[] = {"sound", "keep", nullptr};
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:play", const_cast<char**>(kwlist), &object, &keepo))
+ return nullptr;
+
+ Sound* sound = checkSound(object);
+
+ if(!sound)
+ return nullptr;
+
+ if(keepo != nullptr)
+ {
+ if(!PyBool_Check(keepo))
+ {
+ PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
+ return nullptr;
+ }
+
+ keep = keepo == Py_True;
+ }
+
+ Handle* handle;
+
+ handle = (Handle*)Handle_empty();
+ if(handle != nullptr)
+ {
+ try
+ {
+ handle->handle = new std::shared_ptr<IHandle>((*reinterpret_cast<std::shared_ptr<IDevice>*>(self->device))->play(*reinterpret_cast<std::shared_ptr<ISound>*>(sound->sound), keep));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(handle);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)handle;
+}
+
+PyDoc_STRVAR(M_aud_Device_stopAll_doc,
+ "stopAll()\n\n"
+ "Stops all playing and paused sounds.");
+
+static PyObject *
+Device_stopAll(Device* self)
+{
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<IDevice>*>(self->device))->stopAll();
+ Py_RETURN_NONE;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Device_unlock_doc,
+ "unlock()\n\n"
+ "Unlocks the device after a lock call, see :meth:`lock` for "
+ "details.");
+
+static PyObject *
+Device_unlock(Device* self)
+{
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<IDevice>*>(self->device))->unlock();
+ Py_RETURN_NONE;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static PyMethodDef Device_methods[] = {
+ {"lock", (PyCFunction)Device_lock, METH_NOARGS,
+ M_aud_Device_lock_doc
+ },
+ {"play", (PyCFunction)Device_play, METH_VARARGS | METH_KEYWORDS,
+ M_aud_Device_play_doc
+ },
+ {"stopAll", (PyCFunction)Device_stopAll, METH_NOARGS,
+ M_aud_Device_stopAll_doc
+ },
+ {"unlock", (PyCFunction)Device_unlock, METH_NOARGS,
+ M_aud_Device_unlock_doc
+ },
+ {nullptr} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Device_channels_doc,
+ "The channel count of the device.");
+
+static PyObject *
+Device_get_channels(Device* self, void* nothing)
+{
+ try
+ {
+ DeviceSpecs specs = (*reinterpret_cast<std::shared_ptr<IDevice>*>(self->device))->getSpecs();
+ return Py_BuildValue("i", specs.channels);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Device_distance_model_doc,
+ "The distance model of the device.\n\n"
+ ".. seealso:: http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm#_Toc199835864");
+
+static PyObject *
+Device_get_distance_model(Device* self, void* nothing)
+{
+ try
+ {
+ I3DDevice* device = dynamic_cast<I3DDevice*>(reinterpret_cast<std::shared_ptr<IDevice>*>(self->device)->get());
+ if(device)
+ {
+ return Py_BuildValue("i", int(device->getDistanceModel()));
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return nullptr;
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Device_set_distance_model(Device* self, PyObject* args, void* nothing)
+{
+ int model;
+
+ if(!PyArg_Parse(args, "i:distance_model", &model))
+ return -1;
+
+ try
+ {
+ I3DDevice* device = dynamic_cast<I3DDevice*>(reinterpret_cast<std::shared_ptr<IDevice>*>(self->device)->get());
+ if(device)
+ {
+ device->setDistanceModel(DistanceModel(model));
+ return 0;
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Device_doppler_factor_doc,
+ "The doppler factor of the device.\n"
+ "This factor is a scaling factor for the velocity vectors in "
+ "doppler calculation. So a value bigger than 1 will exaggerate "
+ "the effect as it raises the velocity.");
+
+static PyObject *
+Device_get_doppler_factor(Device* self, void* nothing)
+{
+ try
+ {
+ I3DDevice* device = dynamic_cast<I3DDevice*>(reinterpret_cast<std::shared_ptr<IDevice>*>(self->device)->get());
+ if(device)
+ {
+ return Py_BuildValue("f", device->getDopplerFactor());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return nullptr;
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Device_set_doppler_factor(Device* self, PyObject* args, void* nothing)
+{
+ float factor;
+
+ if(!PyArg_Parse(args, "f:doppler_factor", &factor))
+ return -1;
+
+ try
+ {
+ I3DDevice* device = dynamic_cast<I3DDevice*>(reinterpret_cast<std::shared_ptr<IDevice>*>(self->device)->get());
+ if(device)
+ {
+ device->setDopplerFactor(factor);
+ return 0;
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Device_format_doc,
+ "The native sample format of the device.");
+
+static PyObject *
+Device_get_format(Device* self, void* nothing)
+{
+ try
+ {
+ DeviceSpecs specs = (*reinterpret_cast<std::shared_ptr<IDevice>*>(self->device))->getSpecs();
+ return Py_BuildValue("i", specs.format);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Device_listener_location_doc,
+ "The listeners's location in 3D space, a 3D tuple of floats.");
+
+static PyObject *
+Device_get_listener_location(Device* self, void* nothing)
+{
+ try
+ {
+ I3DDevice* device = dynamic_cast<I3DDevice*>(reinterpret_cast<std::shared_ptr<IDevice>*>(self->device)->get());
+ if(device)
+ {
+ Vector3 v = device->getListenerLocation();
+ return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return nullptr;
+}
+
+static int
+Device_set_listener_location(Device* self, PyObject* args, void* nothing)
+{
+ float x, y, z;
+
+ if(!PyArg_Parse(args, "(fff):listener_location", &x, &y, &z))
+ return -1;
+
+ try
+ {
+ I3DDevice* device = dynamic_cast<I3DDevice*>(reinterpret_cast<std::shared_ptr<IDevice>*>(self->device)->get());
+ if(device)
+ {
+ Vector3 location(x, y, z);
+ device->setListenerLocation(location);
+ return 0;
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Device_listener_orientation_doc,
+ "The listener's orientation in 3D space as quaternion, a 4 float tuple.");
+
+static PyObject *
+Device_get_listener_orientation(Device* self, void* nothing)
+{
+ try
+ {
+ I3DDevice* device = dynamic_cast<I3DDevice*>(reinterpret_cast<std::shared_ptr<IDevice>*>(self->device)->get());
+ if(device)
+ {
+ Quaternion o = device->getListenerOrientation();
+ return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return nullptr;
+}
+
+static int
+Device_set_listener_orientation(Device* self, PyObject* args, void* nothing)
+{
+ float w, x, y, z;
+
+ if(!PyArg_Parse(args, "(ffff):listener_orientation", &w, &x, &y, &z))
+ return -1;
+
+ try
+ {
+ I3DDevice* device = dynamic_cast<I3DDevice*>(reinterpret_cast<std::shared_ptr<IDevice>*>(self->device)->get());
+ if(device)
+ {
+ Quaternion orientation(w, x, y, z);
+ device->setListenerOrientation(orientation);
+ return 0;
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Device_listener_velocity_doc,
+ "The listener's velocity in 3D space, a 3D tuple of floats.");
+
+static PyObject *
+Device_get_listener_velocity(Device* self, void* nothing)
+{
+ try
+ {
+ I3DDevice* device = dynamic_cast<I3DDevice*>(reinterpret_cast<std::shared_ptr<IDevice>*>(self->device)->get());
+ if(device)
+ {
+ Vector3 v = device->getListenerVelocity();
+ return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return nullptr;
+}
+
+static int
+Device_set_listener_velocity(Device* self, PyObject* args, void* nothing)
+{
+ float x, y, z;
+
+ if(!PyArg_Parse(args, "(fff):listener_velocity", &x, &y, &z))
+ return -1;
+
+ try
+ {
+ I3DDevice* device = dynamic_cast<I3DDevice*>(reinterpret_cast<std::shared_ptr<IDevice>*>(self->device)->get());
+ if(device)
+ {
+ Vector3 velocity(x, y, z);
+ device->setListenerVelocity(velocity);
+ return 0;
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Device_rate_doc,
+ "The sampling rate of the device in Hz.");
+
+static PyObject *
+Device_get_rate(Device* self, void* nothing)
+{
+ try
+ {
+ DeviceSpecs specs = (*reinterpret_cast<std::shared_ptr<IDevice>*>(self->device))->getSpecs();
+ return Py_BuildValue("d", specs.rate);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Device_speed_of_sound_doc,
+ "The speed of sound of the device.\n"
+ "The speed of sound in air is typically 343.3 m/s.");
+
+static PyObject *
+Device_get_speed_of_sound(Device* self, void* nothing)
+{
+ try
+ {
+ I3DDevice* device = dynamic_cast<I3DDevice*>(reinterpret_cast<std::shared_ptr<IDevice>*>(self->device)->get());
+ if(device)
+ {
+ return Py_BuildValue("f", device->getSpeedOfSound());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return nullptr;
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Device_set_speed_of_sound(Device* self, PyObject* args, void* nothing)
+{
+ float speed;
+
+ if(!PyArg_Parse(args, "f:speed_of_sound", &speed))
+ return -1;
+
+ try
+ {
+ I3DDevice* device = dynamic_cast<I3DDevice*>(reinterpret_cast<std::shared_ptr<IDevice>*>(self->device)->get());
+ if(device)
+ {
+ device->setSpeedOfSound(speed);
+ return 0;
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Device_volume_doc,
+ "The overall volume of the device.");
+
+static PyObject *
+Device_get_volume(Device* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<IDevice>*>(self->device))->getVolume());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Device_set_volume(Device* self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:volume", &volume))
+ return -1;
+
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<IDevice>*>(self->device))->setVolume(volume);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return -1;
+ }
+}
+
+static PyGetSetDef Device_properties[] = {
+ {(char*)"channels", (getter)Device_get_channels, nullptr,
+ M_aud_Device_channels_doc, nullptr },
+ {(char*)"distance_model", (getter)Device_get_distance_model, (setter)Device_set_distance_model,
+ M_aud_Device_distance_model_doc, nullptr },
+ {(char*)"doppler_factor", (getter)Device_get_doppler_factor, (setter)Device_set_doppler_factor,
+ M_aud_Device_doppler_factor_doc, nullptr },
+ {(char*)"format", (getter)Device_get_format, nullptr,
+ M_aud_Device_format_doc, nullptr },
+ {(char*)"listener_location", (getter)Device_get_listener_location, (setter)Device_set_listener_location,
+ M_aud_Device_listener_location_doc, nullptr },
+ {(char*)"listener_orientation", (getter)Device_get_listener_orientation, (setter)Device_set_listener_orientation,
+ M_aud_Device_listener_orientation_doc, nullptr },
+ {(char*)"listener_velocity", (getter)Device_get_listener_velocity, (setter)Device_set_listener_velocity,
+ M_aud_Device_listener_velocity_doc, nullptr },
+ {(char*)"rate", (getter)Device_get_rate, nullptr,
+ M_aud_Device_rate_doc, nullptr },
+ {(char*)"speed_of_sound", (getter)Device_get_speed_of_sound, (setter)Device_set_speed_of_sound,
+ M_aud_Device_speed_of_sound_doc, nullptr },
+ {(char*)"volume", (getter)Device_get_volume, (setter)Device_set_volume,
+ M_aud_Device_volume_doc, nullptr },
+ {nullptr} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Device_doc,
+ "Device objects represent an audio output backend like OpenAL or "
+ "SDL, but might also represent a file output or RAM buffer "
+ "output.");
+
+static PyTypeObject DeviceType = {
+ PyVarObject_HEAD_INIT(nullptr, 0)
+ "aud.Device", /* tp_name */
+ sizeof(Device), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Device_dealloc,/* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ M_aud_Device_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ Device_methods, /* tp_methods */
+ 0, /* tp_members */
+ Device_properties, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Device_new, /* tp_new */
+};
+
+AUD_API PyObject* Device_empty()
+{
+ return DeviceType.tp_alloc(&DeviceType, 0);
+}
+
+
+AUD_API Device* checkDevice(PyObject* device)
+{
+ if(!PyObject_TypeCheck(device, &DeviceType))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type Device!");
+ return nullptr;
+ }
+
+ return (Device*)device;
+}
+
+
+bool initializeDevice()
+{
+ return PyType_Ready(&DeviceType) >= 0;
+}
+
+
+void addDeviceToModule(PyObject* module)
+{
+ Py_INCREF(&DeviceType);
+ PyModule_AddObject(module, "Device", (PyObject *)&DeviceType);
+}
diff --git a/extern/audaspace/bindings/python/PyDevice.h b/extern/audaspace/bindings/python/PyDevice.h
new file mode 100644
index 00000000000..610b5b4cd23
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyDevice.h
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+#include <Python.h>
+#include "Audaspace.h"
+
+typedef void Reference_IDevice;
+
+typedef struct {
+ PyObject_HEAD
+ Reference_IDevice* device;
+} Device;
+
+extern AUD_API PyObject* Device_empty();
+extern AUD_API Device* checkDevice(PyObject* device);
+
+bool initializeDevice();
+void addDeviceToModule(PyObject* module);
diff --git a/extern/audaspace/bindings/python/PyDynamicMusic.cpp b/extern/audaspace/bindings/python/PyDynamicMusic.cpp
new file mode 100644
index 00000000000..d49f73737c2
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyDynamicMusic.cpp
@@ -0,0 +1,467 @@
+/*******************************************************************************
+* Copyright 2015-2016 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#include "PyDynamicMusic.h"
+#include "PySound.h"
+#include "PyHandle.h"
+#include "PyDevice.h"
+
+#include "Exception.h"
+#include "fx/DynamicMusic.h"
+
+extern PyObject* AUDError;
+
+static PyObject *
+DynamicMusic_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
+{
+ DynamicMusicP* self = (DynamicMusicP*)type->tp_alloc(type, 0);
+
+ if(self != nullptr)
+ {
+ PyObject* object;
+ if(!PyArg_ParseTuple(args, "O:device", &object))
+ return nullptr;
+ Device* device = checkDevice(object);
+
+ try
+ {
+ self->dynamicMusic = new std::shared_ptr<aud::DynamicMusic>(new aud::DynamicMusic(*reinterpret_cast<std::shared_ptr<aud::IDevice>*>(device->device)));
+ }
+ catch(aud::Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+static void
+DynamicMusic_dealloc(DynamicMusicP* self)
+{
+ if(self->dynamicMusic)
+ delete reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+PyDoc_STRVAR(M_aud_DynamicMusic_addScene_doc,
+ "addScene(scene)\n\n"
+ "Adds a new scene.\n\n"
+ ":arg scene: The scene sound.\n"
+ ":type scene: :class:`Sound`\n"
+ ":return: The new scene id.\n"
+ ":rtype: int");
+
+static PyObject *
+DynamicMusic_addScene(DynamicMusicP* self, PyObject* args)
+{
+ PyObject* object;
+ if(!PyArg_Parse(args, "O:sound", &object))
+ return nullptr;
+
+ Sound* sound = checkSound(object);
+ if(!sound)
+ return nullptr;
+
+ try
+ {
+ return Py_BuildValue("i", (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->addScene(*reinterpret_cast<std::shared_ptr<aud::ISound>*>(sound->sound)));
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_DynamicMusic_addTransition_doc,
+ "addTransition(ini, end, transition)\n\n"
+ "Adds a new scene.\n\n"
+ ":arg ini: the initial scene foor the transition.\n"
+ ":type ini: int\n"
+ ":arg end: The final scene for the transition.\n"
+ ":type end: int\n"
+ ":arg transition: The transition sound.\n"
+ ":type transition: :class:`Sound`\n"
+ ":return: false if the ini or end scenes don't exist, true othrwise.\n"
+ ":rtype: bool");
+
+static PyObject *
+DynamicMusic_addTransition(DynamicMusicP* self, PyObject* args)
+{
+ PyObject* object;
+ int ini, end;
+ if(!PyArg_ParseTuple(args, "iiO:sound", &ini, &end, &object))
+ return nullptr;
+ Sound* sound = checkSound(object);
+ if(!sound)
+ return nullptr;
+
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->addTransition(ini, end, *reinterpret_cast<std::shared_ptr<aud::ISound>*>(sound->sound));
+ Py_RETURN_NONE;
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_DynamicMusic_resume_doc,
+ "resume()\n\n"
+ "Resumes playback of the scene.\n\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: bool");
+
+static PyObject *
+DynamicMusic_resume(DynamicMusicP* self)
+{
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->resume());
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_DynamicMusic_pause_doc,
+ "pause()\n\n"
+ "Pauses playback of the scene.\n\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: bool");
+
+static PyObject *
+DynamicMusic_pause(DynamicMusicP* self)
+{
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->pause());
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_DynamicMusic_stop_doc,
+ "stop()\n\n"
+ "Stops playback of the scene.\n\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: bool\n\n");
+
+static PyObject *
+DynamicMusic_stop(DynamicMusicP* self)
+{
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->stop());
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static PyMethodDef DynamicMusic_methods[] = {
+ { "addScene", (PyCFunction)DynamicMusic_addScene, METH_O,
+ M_aud_DynamicMusic_addScene_doc
+ },
+ { "addTransition", (PyCFunction)DynamicMusic_addTransition, METH_VARARGS,
+ M_aud_DynamicMusic_addTransition_doc
+ },
+ { "resume", (PyCFunction)DynamicMusic_resume, METH_NOARGS,
+ M_aud_DynamicMusic_resume_doc
+ },
+ { "pause", (PyCFunction)DynamicMusic_pause, METH_NOARGS,
+ M_aud_DynamicMusic_pause_doc
+ },
+ { "stop", (PyCFunction)DynamicMusic_stop, METH_NOARGS,
+ M_aud_DynamicMusic_stop_doc
+ },
+ { nullptr } /* Sentinel */
+};
+
+/////////////////////////////////////////////////////
+
+PyDoc_STRVAR(M_aud_DynamicMusic_status_doc,
+ "Whether the scene is playing, paused or stopped (=invalid).");
+
+static PyObject *
+DynamicMusic_get_status(DynamicMusicP* self, void* nothing)
+{
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->getStatus());
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_DynamicMusic_position_doc,
+ "The playback position of the scene in seconds.");
+
+static int
+DynamicMusic_set_position(DynamicMusicP* self, PyObject* args, void* nothing)
+{
+ float position;
+
+ if(!PyArg_Parse(args, "f:position", &position))
+ return -1;
+
+ try
+ {
+ if((*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->seek(position))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't seek the sound!");
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+static PyObject *
+DynamicMusic_get_position(DynamicMusicP* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->getPosition());
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_DynamicMusic_fadeTime_doc,
+ "The length in seconds of the crossfade transition");
+
+static int
+DynamicMusic_set_fadeTime(DynamicMusicP* self, PyObject* args, void* nothing)
+{
+ float fadeTime;
+
+ if(!PyArg_Parse(args, "f:fadeTime", &fadeTime))
+ return -1;
+
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->setFadeTime(fadeTime);
+ return 0;
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+static PyObject *
+DynamicMusic_get_fadeTime(DynamicMusicP* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->getFadeTime());
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_DynamicMusic_scene_doc,
+ "The current scene");
+
+static int
+DynamicMusic_set_scene(DynamicMusicP* self, PyObject* args, void* nothing)
+{
+ int scene;
+
+ if(!PyArg_Parse(args, "i:scene", &scene))
+ return -1;
+
+ try
+ {
+ if((*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->changeScene(scene))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't change the scene!");
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+static PyObject *
+DynamicMusic_get_scene(DynamicMusicP* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("i", (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->getScene());
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_DynamicMusic_volume_doc,
+ "The volume of the scene.");
+
+static int
+DynamicMusic_set_volume(DynamicMusicP* self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:volume", &volume))
+ return -1;
+
+ try
+ {
+ if((*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->setVolume(volume))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't change the volume!");
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+static PyObject *
+DynamicMusic_get_volume(DynamicMusicP* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::DynamicMusic>*>(self->dynamicMusic))->getVolume());
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static PyGetSetDef DynamicMusic_properties[] = {
+ { (char*)"status", (getter)DynamicMusic_get_status, nullptr,
+ M_aud_DynamicMusic_status_doc, nullptr },
+ { (char*)"position", (getter)DynamicMusic_get_position, (setter)DynamicMusic_set_position,
+ M_aud_DynamicMusic_position_doc, nullptr },
+ { (char*)"fadeTime", (getter)DynamicMusic_get_fadeTime, (setter)DynamicMusic_set_fadeTime,
+ M_aud_DynamicMusic_fadeTime_doc, nullptr },
+ { (char*)"scene", (getter)DynamicMusic_get_scene, (setter)DynamicMusic_set_scene,
+ M_aud_DynamicMusic_scene_doc, nullptr },
+ { (char*)"volume", (getter)DynamicMusic_get_volume, (setter)DynamicMusic_set_volume,
+ M_aud_DynamicMusic_volume_doc, nullptr },
+ { nullptr } /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_DynamicMusic_doc,
+ "The DynamicMusic object allows to play music depending on a current scene, scene changes are managed by the class, with the possibility of custom transitions.\n"
+ "The default transition is a crossfade effect, and the default scene is silent and has id 0");
+
+PyTypeObject DynamicMusicType = {
+ PyVarObject_HEAD_INIT(nullptr, 0)
+ "aud.DynamicMusic", /* tp_name */
+ sizeof(DynamicMusicP), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)DynamicMusic_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ M_aud_DynamicMusic_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ DynamicMusic_methods, /* tp_methods */
+ 0, /* tp_members */
+ DynamicMusic_properties, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ DynamicMusic_new, /* tp_new */
+};
+
+AUD_API PyObject* DynamicMusic_empty()
+{
+ return DynamicMusicType.tp_alloc(&DynamicMusicType, 0);
+}
+
+
+AUD_API DynamicMusicP* checkDynamicMusic(PyObject* dynamicMusic)
+{
+ if(!PyObject_TypeCheck(dynamicMusic, &DynamicMusicType))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type DynamicMusic!");
+ return nullptr;
+ }
+
+ return (DynamicMusicP*)dynamicMusic;
+}
+
+
+bool initializeDynamicMusic()
+{
+ return PyType_Ready(&DynamicMusicType) >= 0;
+}
+
+
+void addDynamicMusicToModule(PyObject* module)
+{
+ Py_INCREF(&DynamicMusicType);
+ PyModule_AddObject(module, "DynamicMusic", (PyObject *)&DynamicMusicType);
+} \ No newline at end of file
diff --git a/extern/audaspace/bindings/python/PyDynamicMusic.h b/extern/audaspace/bindings/python/PyDynamicMusic.h
new file mode 100644
index 00000000000..f19de2d8c75
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyDynamicMusic.h
@@ -0,0 +1,33 @@
+/*******************************************************************************
+* Copyright 2015-2016 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#pragma once
+
+#include <Python.h>
+#include "Audaspace.h"
+
+typedef void Reference_DynamicMusic;
+
+typedef struct {
+ PyObject_HEAD
+ Reference_DynamicMusic* dynamicMusic;
+} DynamicMusicP;
+
+extern AUD_API PyObject* DynamicMusic_empty();
+extern AUD_API DynamicMusicP* checkDynamicMusic(PyObject* dynamicMusic);
+
+bool initializeDynamicMusic();
+void addDynamicMusicToModule(PyObject* module); \ No newline at end of file
diff --git a/extern/audaspace/bindings/python/PyHRTF.cpp b/extern/audaspace/bindings/python/PyHRTF.cpp
new file mode 100644
index 00000000000..2a5b6be624f
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyHRTF.cpp
@@ -0,0 +1,247 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#include "PyHRTF.h"
+#include "PySound.h"
+
+#include "Exception.h"
+#include "fx/HRTF.h"
+#include "fx/HRTFLoader.h"
+
+extern PyObject* AUDError;
+
+static PyObject *
+HRTF_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
+{
+ HRTFP* self = (HRTFP*)type->tp_alloc(type, 0);
+
+ if(self != nullptr)
+ {
+ try
+ {
+ self->hrtf = new std::shared_ptr<aud::HRTF>(new aud::HRTF());
+ }
+ catch(aud::Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+static void
+HRTF_dealloc(HRTFP* self)
+{
+ if(self->hrtf)
+ delete reinterpret_cast<std::shared_ptr<aud::HRTF>*>(self->hrtf);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+PyDoc_STRVAR(M_aud_HRTF_addImpulseResponse_doc,
+ "addImpulseResponseFromSound(sound, azimuth, elevation)\n\n"
+ "Adds a new hrtf to the HRTF object\n\n"
+ ":arg sound: The sound that contains the hrtf.\n"
+ ":type sound: :class:`Sound`\n"
+ ":arg azimuth: The azimuth angle of the hrtf.\n"
+ ":type azimuth: float\n"
+ ":arg elevation: The elevation angle of the hrtf.\n"
+ ":type elevation: float\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: bool");
+
+static PyObject *
+HRTF_addImpulseResponseFromSound(HRTFP* self, PyObject* args)
+{
+ PyObject* object;
+ float azimuth, elevation;
+
+ if(!PyArg_ParseTuple(args, "Off:hrtf", &object, &azimuth, &elevation))
+ return nullptr;
+
+ Sound* ir = checkSound(object);
+ if(!ir)
+ return nullptr;
+
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<aud::HRTF>*>(self->hrtf))->addImpulseResponse(std::make_shared<aud::StreamBuffer>(*reinterpret_cast<std::shared_ptr<aud::ISound>*>(ir->sound)), azimuth, elevation));
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_HRTF_loadLeftHrtfSet_doc,
+ "loadLeftHrtfSet(extension, directory)\n\n"
+ "Loads all HRTFs from a directory.\n\n"
+ ":arg extension: The file extension of the hrtfs.\n"
+ ":type extension: string\n"
+ ":arg directory: The path to where the HRTF files are located.\n"
+ ":type extension: string\n"
+ ":return: The loaded :class:`HRTF` object.\n"
+ ":rtype: :class:`HRTF`\n\n");
+
+static PyObject *
+HRTF_loadLeftHrtfSet(PyTypeObject* type, PyObject* args)
+{
+ const char* dir = nullptr;
+ const char* ext = nullptr;
+
+ if(!PyArg_ParseTuple(args, "ss:hrtf", &ext, &dir))
+ return nullptr;
+
+ HRTFP* self;
+ self = (HRTFP*)type->tp_alloc(type, 0);
+
+ try
+ {
+ self->hrtf = new std::shared_ptr<aud::HRTF>(aud::HRTFLoader::loadLeftHRTFs(ext, dir));
+ }
+ catch(aud::Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_HRTF_loadRightHrtfSet_doc,
+ "loadLeftHrtfSet(extension, directory)\n\n"
+ "Loads all HRTFs from a directory.\n\n"
+ ":arg extension: The file extension of the hrtfs.\n"
+ ":type extension: string\n"
+ ":arg directory: The path to where the HRTF files are located.\n"
+ ":type extension: string\n"
+ ":return: The loaded :class:`HRTF` object.\n"
+ ":rtype: :class:`HRTF`\n\n");
+
+static PyObject *
+HRTF_loadRightHrtfSet(PyTypeObject* type, PyObject* args)
+{
+ const char* dir = nullptr;
+ const char* ext = nullptr;
+
+ if(!PyArg_ParseTuple(args, "ss:hrtf", &ext, &dir))
+ return nullptr;
+
+ HRTFP* self;
+ self = (HRTFP*)type->tp_alloc(type, 0);
+
+ try
+ {
+ self->hrtf = new std::shared_ptr<aud::HRTF>(aud::HRTFLoader::loadRightHRTFs(ext, dir));
+ }
+ catch(aud::Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ return (PyObject *)self;
+}
+
+static PyMethodDef HRTF_methods[] = {
+ { "addImpulseResponseFromSound", (PyCFunction)HRTF_addImpulseResponseFromSound, METH_VARARGS | METH_KEYWORDS,
+ M_aud_HRTF_addImpulseResponse_doc
+ },
+ { "loadLeftHrtfSet", (PyCFunction)HRTF_loadLeftHrtfSet, METH_VARARGS | METH_CLASS,
+ M_aud_HRTF_loadLeftHrtfSet_doc
+ },
+ { "loadRightHrtfSet", (PyCFunction)HRTF_loadRightHrtfSet, METH_VARARGS | METH_CLASS,
+ M_aud_HRTF_loadRightHrtfSet_doc
+ },
+ { nullptr } /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_HRTF_doc,
+ "An HRTF object represents a set of head related transfer functions as impulse responses. It's used for binaural sound");
+
+PyTypeObject HRTFType = {
+ PyVarObject_HEAD_INIT(nullptr, 0)
+ "aud.HRTF", /* tp_name */
+ sizeof(HRTFP), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)HRTF_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ M_aud_HRTF_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ HRTF_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ HRTF_new, /* tp_new */
+};
+
+AUD_API PyObject* HRTF_empty()
+{
+ return HRTFType.tp_alloc(&HRTFType, 0);
+}
+
+
+AUD_API HRTFP* checkHRTF(PyObject* hrtf)
+{
+ if(!PyObject_TypeCheck(hrtf, &HRTFType))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type HRTF!");
+ return nullptr;
+ }
+
+ return (HRTFP*)hrtf;
+}
+
+
+bool initializeHRTF()
+{
+ return PyType_Ready(&HRTFType) >= 0;
+}
+
+
+void addHRTFToModule(PyObject* module)
+{
+ Py_INCREF(&HRTFType);
+ PyModule_AddObject(module, "HRTF", (PyObject *)&HRTFType);
+}
diff --git a/extern/audaspace/bindings/python/PyHRTF.h b/extern/audaspace/bindings/python/PyHRTF.h
new file mode 100644
index 00000000000..0445069929f
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyHRTF.h
@@ -0,0 +1,33 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#pragma once
+
+#include <Python.h>
+#include "Audaspace.h"
+
+typedef void Reference_HRTF;
+
+typedef struct {
+ PyObject_HEAD
+ Reference_HRTF* hrtf;
+} HRTFP;
+
+extern AUD_API PyObject* HRTF_empty();
+extern AUD_API HRTFP* checkHRTF(PyObject* hrtf);
+
+bool initializeHRTF();
+void addHRTFToModule(PyObject* module); \ No newline at end of file
diff --git a/extern/audaspace/bindings/python/PyHandle.cpp b/extern/audaspace/bindings/python/PyHandle.cpp
new file mode 100644
index 00000000000..7f7a7660049
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyHandle.cpp
@@ -0,0 +1,1126 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#include "PyHandle.h"
+
+#include "devices/IHandle.h"
+#include "devices/I3DHandle.h"
+#include "Exception.h"
+
+#include <memory>
+
+#include <structmember.h>
+
+using namespace aud;
+
+extern PyObject* AUDError;
+static const char* device_not_3d_error = "Device is not a 3D device!";
+
+static void
+Handle_dealloc(Handle* self)
+{
+ if(self->handle)
+ delete reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+PyDoc_STRVAR(M_aud_Handle_pause_doc,
+ "pause()\n\n"
+ "Pauses playback.\n\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: bool");
+
+static PyObject *
+Handle_pause(Handle* self)
+{
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->pause());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Handle_resume_doc,
+ "resume()\n\n"
+ "Resumes playback.\n\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: bool");
+
+static PyObject *
+Handle_resume(Handle* self)
+{
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->resume());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Handle_stop_doc,
+ "stop()\n\n"
+ "Stops playback.\n\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: bool\n\n"
+ ".. note:: This makes the handle invalid.");
+
+static PyObject *
+Handle_stop(Handle* self)
+{
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->stop());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static PyMethodDef Handle_methods[] = {
+ {"pause", (PyCFunction)Handle_pause, METH_NOARGS,
+ M_aud_Handle_pause_doc
+ },
+ {"resume", (PyCFunction)Handle_resume, METH_NOARGS,
+ M_aud_Handle_resume_doc
+ },
+ {"stop", (PyCFunction)Handle_stop, METH_NOARGS,
+ M_aud_Handle_stop_doc
+ },
+ {nullptr} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Handle_attenuation_doc,
+ "This factor is used for distance based attenuation of the "
+ "source.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+Handle_get_attenuation(Handle* self, void* nothing)
+{
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ return Py_BuildValue("f", handle->getAttenuation());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return nullptr;
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Handle_set_attenuation(Handle* self, PyObject* args, void* nothing)
+{
+ float factor;
+
+ if(!PyArg_Parse(args, "f:attenuation", &factor))
+ return -1;
+
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ if(handle->setAttenuation(factor))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the attenuation!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_cone_angle_inner_doc,
+ "The opening angle of the inner cone of the source. If the cone "
+ "values of a source are set there are two (audible) cones with "
+ "the apex at the :attr:`location` of the source and with infinite "
+ "height, heading in the direction of the source's "
+ ":attr:`orientation`.\n"
+ "In the inner cone the volume is normal. Outside the outer cone "
+ "the volume will be :attr:`cone_volume_outer` and in the area "
+ "between the volume will be interpolated linearly.");
+
+static PyObject *
+Handle_get_cone_angle_inner(Handle* self, void* nothing)
+{
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ return Py_BuildValue("f", handle->getConeAngleInner());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return nullptr;
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Handle_set_cone_angle_inner(Handle* self, PyObject* args, void* nothing)
+{
+ float angle;
+
+ if(!PyArg_Parse(args, "f:cone_angle_inner", &angle))
+ return -1;
+
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ if(handle->setConeAngleInner(angle))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the cone inner angle!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_cone_angle_outer_doc,
+ "The opening angle of the outer cone of the source.\n\n"
+ ".. seealso:: :attr:`cone_angle_inner`");
+
+static PyObject *
+Handle_get_cone_angle_outer(Handle* self, void* nothing)
+{
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ return Py_BuildValue("f", handle->getConeAngleOuter());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return nullptr;
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Handle_set_cone_angle_outer(Handle* self, PyObject* args, void* nothing)
+{
+ float angle;
+
+ if(!PyArg_Parse(args, "f:cone_angle_outer", &angle))
+ return -1;
+
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ if(handle->setConeAngleOuter(angle))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the cone outer angle!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_cone_volume_outer_doc,
+ "The volume outside the outer cone of the source.\n\n"
+ ".. seealso:: :attr:`cone_angle_inner`");
+
+static PyObject *
+Handle_get_cone_volume_outer(Handle* self, void* nothing)
+{
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ return Py_BuildValue("f", handle->getConeVolumeOuter());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return nullptr;
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Handle_set_cone_volume_outer(Handle* self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:cone_volume_outer", &volume))
+ return -1;
+
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ if(handle->setConeVolumeOuter(volume))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the cone outer volume!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_distance_maximum_doc,
+ "The maximum distance of the source.\n"
+ "If the listener is further away the source volume will be 0.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+Handle_get_distance_maximum(Handle* self, void* nothing)
+{
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ return Py_BuildValue("f", handle->getDistanceMaximum());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return nullptr;
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Handle_set_distance_maximum(Handle* self, PyObject* args, void* nothing)
+{
+ float distance;
+
+ if(!PyArg_Parse(args, "f:distance_maximum", &distance))
+ return -1;
+
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ if(handle->setDistanceMaximum(distance))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the maximum distance!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_distance_reference_doc,
+ "The reference distance of the source.\n"
+ "At this distance the volume will be exactly :attr:`volume`.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+Handle_get_distance_reference(Handle* self, void* nothing)
+{
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ return Py_BuildValue("f", handle->getDistanceReference());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return nullptr;
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Handle_set_distance_reference(Handle* self, PyObject* args, void* nothing)
+{
+ float distance;
+
+ if(!PyArg_Parse(args, "f:distance_reference", &distance))
+ return -1;
+
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ if(handle->setDistanceReference(distance))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the reference distance!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_keep_doc,
+ "Whether the sound should be kept paused in the device when its "
+ "end is reached.\n"
+ "This can be used to seek the sound to some position and start "
+ "playback again.\n\n"
+ ".. warning:: If this is set to true and you forget stopping this "
+ "equals a memory leak as the handle exists until the device is "
+ "destroyed.");
+
+static PyObject *
+Handle_get_keep(Handle* self, void* nothing)
+{
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->getKeep());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Handle_set_keep(Handle* self, PyObject* args, void* nothing)
+{
+ if(!PyBool_Check(args))
+ {
+ PyErr_SetString(PyExc_TypeError, "keep is not a boolean!");
+ return -1;
+ }
+
+ bool keep = args == Py_True;
+
+ try
+ {
+ if((*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->setKeep(keep))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set keep of the sound!");
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_location_doc,
+ "The source's location in 3D space, a 3D tuple of floats.");
+
+static PyObject *
+Handle_get_location(Handle* self, void* nothing)
+{
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ Vector3 v = handle->getLocation();
+ return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return nullptr;
+}
+
+static int
+Handle_set_location(Handle* self, PyObject* args, void* nothing)
+{
+ float x, y, z;
+
+ if(!PyArg_Parse(args, "(fff):location", &x, &y, &z))
+ return -1;
+
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ Vector3 location(x, y, z);
+ if(handle->setLocation(location))
+ return 0;
+ PyErr_SetString(AUDError, "Location couldn't be set!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_loop_count_doc,
+ "The (remaining) loop count of the sound. A negative value indicates infinity.");
+
+static PyObject *
+Handle_get_loop_count(Handle* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("i", (*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->getLoopCount());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Handle_set_loop_count(Handle* self, PyObject* args, void* nothing)
+{
+ int loops;
+
+ if(!PyArg_Parse(args, "i:loop_count", &loops))
+ return -1;
+
+ try
+ {
+ if((*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->setLoopCount(loops))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the loop count!");
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_orientation_doc,
+ "The source's orientation in 3D space as quaternion, a 4 float tuple.");
+
+static PyObject *
+Handle_get_orientation(Handle* self, void* nothing)
+{
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ Quaternion o = handle->getOrientation();
+ return Py_BuildValue("(ffff)", o.w(), o.x(), o.y(), o.z());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return nullptr;
+}
+
+static int
+Handle_set_orientation(Handle* self, PyObject* args, void* nothing)
+{
+ float w, x, y, z;
+
+ if(!PyArg_Parse(args, "(ffff):orientation", &w, &x, &y, &z))
+ return -1;
+
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ Quaternion orientation(w, x, y, z);
+ if(handle->setOrientation(orientation))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the orientation!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_pitch_doc,
+ "The pitch of the sound.");
+
+static PyObject *
+Handle_get_pitch(Handle* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->getPitch());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Handle_set_pitch(Handle* self, PyObject* args, void* nothing)
+{
+ float pitch;
+
+ if(!PyArg_Parse(args, "f:pitch", &pitch))
+ return -1;
+
+ try
+ {
+ if((*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->setPitch(pitch))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the sound pitch!");
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_position_doc,
+ "The playback position of the sound in seconds.");
+
+static PyObject *
+Handle_get_position(Handle* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->getPosition());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Handle_set_position(Handle* self, PyObject* args, void* nothing)
+{
+ float position;
+
+ if(!PyArg_Parse(args, "f:position", &position))
+ return -1;
+
+ try
+ {
+ if((*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->seek(position))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't seek the sound!");
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_relative_doc,
+ "Whether the source's location, velocity and orientation is relative or absolute to the listener.");
+
+static PyObject *
+Handle_get_relative(Handle* self, void* nothing)
+{
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ return PyBool_FromLong((long)handle->isRelative());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return nullptr;
+}
+
+static int
+Handle_set_relative(Handle* self, PyObject* args, void* nothing)
+{
+ if(!PyBool_Check(args))
+ {
+ PyErr_SetString(PyExc_TypeError, "Value is not a boolean!");
+ return -1;
+ }
+
+ bool relative = (args == Py_True);
+
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ if(handle->setRelative(relative))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the relativeness!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_status_doc,
+ "Whether the sound is playing, paused or stopped (=invalid).");
+
+static PyObject *
+Handle_get_status(Handle* self, void* nothing)
+{
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->getStatus());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Handle_velocity_doc,
+ "The source's velocity in 3D space, a 3D tuple of floats.");
+
+static PyObject *
+Handle_get_velocity(Handle* self, void* nothing)
+{
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ Vector3 v = handle->getVelocity();
+ return Py_BuildValue("(fff)", v.x(), v.y(), v.z());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return nullptr;
+}
+
+static int
+Handle_set_velocity(Handle* self, PyObject* args, void* nothing)
+{
+ float x, y, z;
+
+ if(!PyArg_Parse(args, "(fff):velocity", &x, &y, &z))
+ return -1;
+
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ Vector3 velocity(x, y, z);
+ if(handle->setVelocity(velocity))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the velocity!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_volume_doc,
+ "The volume of the sound.");
+
+static PyObject *
+Handle_get_volume(Handle* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->getVolume());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Handle_set_volume(Handle* self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:volume", &volume))
+ return -1;
+
+ try
+ {
+ if((*reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle))->setVolume(volume))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the sound volume!");
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_volume_maximum_doc,
+ "The maximum volume of the source.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+Handle_get_volume_maximum(Handle* self, void* nothing)
+{
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ return Py_BuildValue("f", handle->getVolumeMaximum());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return nullptr;
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Handle_set_volume_maximum(Handle* self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:volume_maximum", &volume))
+ return -1;
+
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ if(handle->setVolumeMaximum(volume))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the maximum volume!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Handle_volume_minimum_doc,
+ "The minimum volume of the source.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+Handle_get_volume_minimum(Handle* self, void* nothing)
+{
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ return Py_BuildValue("f", handle->getVolumeMinimum());
+ }
+ else
+ {
+ PyErr_SetString(AUDError, device_not_3d_error);
+ return nullptr;
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Handle_set_volume_minimum(Handle* self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:volume_minimum", &volume))
+ return -1;
+
+ try
+ {
+ I3DHandle* handle = dynamic_cast<I3DHandle*>(reinterpret_cast<std::shared_ptr<IHandle>*>(self->handle)->get());
+ if(handle)
+ {
+ if(handle->setVolumeMinimum(volume))
+ return 0;
+ PyErr_SetString(AUDError, "Couldn't set the minimum volume!");
+ }
+ else
+ PyErr_SetString(AUDError, device_not_3d_error);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+static PyGetSetDef Handle_properties[] = {
+ {(char*)"attenuation", (getter)Handle_get_attenuation, (setter)Handle_set_attenuation,
+ M_aud_Handle_attenuation_doc, nullptr },
+ {(char*)"cone_angle_inner", (getter)Handle_get_cone_angle_inner, (setter)Handle_set_cone_angle_inner,
+ M_aud_Handle_cone_angle_inner_doc, nullptr },
+ {(char*)"cone_angle_outer", (getter)Handle_get_cone_angle_outer, (setter)Handle_set_cone_angle_outer,
+ M_aud_Handle_cone_angle_outer_doc, nullptr },
+ {(char*)"cone_volume_outer", (getter)Handle_get_cone_volume_outer, (setter)Handle_set_cone_volume_outer,
+ M_aud_Handle_cone_volume_outer_doc, nullptr },
+ {(char*)"distance_maximum", (getter)Handle_get_distance_maximum, (setter)Handle_set_distance_maximum,
+ M_aud_Handle_distance_maximum_doc, nullptr },
+ {(char*)"distance_reference", (getter)Handle_get_distance_reference, (setter)Handle_set_distance_reference,
+ M_aud_Handle_distance_reference_doc, nullptr },
+ {(char*)"keep", (getter)Handle_get_keep, (setter)Handle_set_keep,
+ M_aud_Handle_keep_doc, nullptr },
+ {(char*)"location", (getter)Handle_get_location, (setter)Handle_set_location,
+ M_aud_Handle_location_doc, nullptr },
+ {(char*)"loop_count", (getter)Handle_get_loop_count, (setter)Handle_set_loop_count,
+ M_aud_Handle_loop_count_doc, nullptr },
+ {(char*)"orientation", (getter)Handle_get_orientation, (setter)Handle_set_orientation,
+ M_aud_Handle_orientation_doc, nullptr },
+ {(char*)"pitch", (getter)Handle_get_pitch, (setter)Handle_set_pitch,
+ M_aud_Handle_pitch_doc, nullptr },
+ {(char*)"position", (getter)Handle_get_position, (setter)Handle_set_position,
+ M_aud_Handle_position_doc, nullptr },
+ {(char*)"relative", (getter)Handle_get_relative, (setter)Handle_set_relative,
+ M_aud_Handle_relative_doc, nullptr },
+ {(char*)"status", (getter)Handle_get_status, nullptr,
+ M_aud_Handle_status_doc, nullptr },
+ {(char*)"velocity", (getter)Handle_get_velocity, (setter)Handle_set_velocity,
+ M_aud_Handle_velocity_doc, nullptr },
+ {(char*)"volume", (getter)Handle_get_volume, (setter)Handle_set_volume,
+ M_aud_Handle_volume_doc, nullptr },
+ {(char*)"volume_maximum", (getter)Handle_get_volume_maximum, (setter)Handle_set_volume_maximum,
+ M_aud_Handle_volume_maximum_doc, nullptr },
+ {(char*)"volume_minimum", (getter)Handle_get_volume_minimum, (setter)Handle_set_volume_minimum,
+ M_aud_Handle_volume_minimum_doc, nullptr },
+ {nullptr} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Handle_doc,
+ "Handle objects are playback handles that can be used to control "
+ "playback of a sound. If a sound is played back multiple times "
+ "then there are as many handles.");
+
+static PyTypeObject HandleType = {
+ PyVarObject_HEAD_INIT(nullptr, 0)
+ "aud.Handle", /* tp_name */
+ sizeof(Handle), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Handle_dealloc,/* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ M_aud_Handle_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ Handle_methods, /* tp_methods */
+ 0, /* tp_members */
+ Handle_properties, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+
+AUD_API PyObject* Handle_empty()
+{
+ return HandleType.tp_alloc(&HandleType, 0);
+}
+
+
+AUD_API Handle*checkHandle(PyObject* handle)
+{
+ if(!PyObject_TypeCheck(handle, &HandleType))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type Handle!");
+ return nullptr;
+ }
+
+ return (Handle*)handle;
+}
+
+
+bool initializeHandle()
+{
+ return PyType_Ready(&HandleType) >= 0;
+}
+
+
+void addHandleToModule(PyObject* module)
+{
+ Py_INCREF(&HandleType);
+ PyModule_AddObject(module, "Handle", (PyObject *)&HandleType);
+}
+
+
diff --git a/extern/audaspace/bindings/python/PyHandle.h b/extern/audaspace/bindings/python/PyHandle.h
new file mode 100644
index 00000000000..95006c88da7
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyHandle.h
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+#include <Python.h>
+#include "Audaspace.h"
+
+typedef void Reference_IHandle;
+
+typedef struct {
+ PyObject_HEAD
+ Reference_IHandle* handle;
+} Handle;
+
+extern AUD_API PyObject* Handle_empty();
+extern AUD_API Handle* checkHandle(PyObject* handle);
+
+bool initializeHandle();
+void addHandleToModule(PyObject* module);
diff --git a/extern/audaspace/bindings/python/PyImpulseResponse.cpp b/extern/audaspace/bindings/python/PyImpulseResponse.cpp
new file mode 100644
index 00000000000..5200c938511
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyImpulseResponse.cpp
@@ -0,0 +1,137 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#include "PyImpulseResponse.h"
+#include "PySound.h"
+
+#include "Exception.h"
+#include "fx/ImpulseResponse.h"
+#include "util/StreamBuffer.h"
+
+extern PyObject* AUDError;
+
+static PyObject *
+ImpulseResponse_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
+{
+ ImpulseResponseP* self = (ImpulseResponseP*)type->tp_alloc(type, 0);
+
+ if(self != nullptr)
+ {
+ PyObject* object;
+ if(!PyArg_ParseTuple(args, "O:sound", &object))
+ return nullptr;
+ Sound* sound = checkSound(object);
+
+ try
+ {
+ self->impulseResponse = new std::shared_ptr<aud::ImpulseResponse>(new aud::ImpulseResponse(std::make_shared<aud::StreamBuffer>(*reinterpret_cast<std::shared_ptr<aud::ISound>*>(sound->sound))));
+ }
+ catch(aud::Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+static void
+ImpulseResponse_dealloc(ImpulseResponseP* self)
+{
+ if(self->impulseResponse)
+ delete reinterpret_cast<std::shared_ptr<aud::ImpulseResponse>*>(self->impulseResponse);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyMethodDef ImpulseResponse_methods[] = {
+ { nullptr } /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_ImpulseResponse_doc,
+ "An ImpulseResponse object represents a filter with which to convolve a sound.");
+
+PyTypeObject ImpulseResponseType = {
+ PyVarObject_HEAD_INIT(nullptr, 0)
+ "aud.ImpulseResponse", /* tp_name */
+ sizeof(ImpulseResponseP), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)ImpulseResponse_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ M_aud_ImpulseResponse_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ ImpulseResponse_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ ImpulseResponse_new, /* tp_new */
+};
+
+AUD_API PyObject* ImpulseResponse_empty()
+{
+ return ImpulseResponseType.tp_alloc(&ImpulseResponseType, 0);
+}
+
+
+AUD_API ImpulseResponseP* checkImpulseResponse(PyObject* impulseResponse)
+{
+ if(!PyObject_TypeCheck(impulseResponse, &ImpulseResponseType))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type ImpulseResponse!");
+ return nullptr;
+ }
+
+ return (ImpulseResponseP*)impulseResponse;
+}
+
+
+bool initializeImpulseResponse()
+{
+ return PyType_Ready(&ImpulseResponseType) >= 0;
+}
+
+
+void addImpulseResponseToModule(PyObject* module)
+{
+ Py_INCREF(&ImpulseResponseType);
+ PyModule_AddObject(module, "ImpulseResponse", (PyObject *)&ImpulseResponseType);
+}
diff --git a/extern/audaspace/bindings/python/PyImpulseResponse.h b/extern/audaspace/bindings/python/PyImpulseResponse.h
new file mode 100644
index 00000000000..3e974c0701c
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyImpulseResponse.h
@@ -0,0 +1,33 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#pragma once
+
+#include <Python.h>
+#include "Audaspace.h"
+
+typedef void Reference_ImpulseResponse;
+
+typedef struct {
+ PyObject_HEAD
+ Reference_ImpulseResponse* impulseResponse;
+} ImpulseResponseP;
+
+extern AUD_API PyObject* ImpulseResponse_empty();
+extern AUD_API ImpulseResponseP* checkImpulseResponse(PyObject* impulseResponse);
+
+bool initializeImpulseResponse();
+void addImpulseResponseToModule(PyObject* module); \ No newline at end of file
diff --git a/extern/audaspace/bindings/python/PyPlaybackManager.cpp b/extern/audaspace/bindings/python/PyPlaybackManager.cpp
new file mode 100644
index 00000000000..9b6614cae9a
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyPlaybackManager.cpp
@@ -0,0 +1,389 @@
+/*******************************************************************************
+* Copyright 2015-2016 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#include "PyPlaybackManager.h"
+#include "PySound.h"
+#include "PyHandle.h"
+#include "PyDevice.h"
+
+#include "Exception.h"
+#include "fx/PlaybackManager.h"
+
+extern PyObject* AUDError;
+
+static PyObject *
+PlaybackManager_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
+{
+ PlaybackManagerP* self = (PlaybackManagerP*)type->tp_alloc(type, 0);
+
+ if(self != nullptr)
+ {
+ PyObject* object;
+ if(!PyArg_ParseTuple(args, "O:catKey", &object))
+ return nullptr;
+ Device* device = checkDevice(object);
+
+ try
+ {
+ self->playbackManager = new std::shared_ptr<aud::PlaybackManager>(new aud::PlaybackManager(*reinterpret_cast<std::shared_ptr<aud::IDevice>*>(device->device)));
+ }
+ catch(aud::Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+static void
+PlaybackManager_dealloc(PlaybackManagerP* self)
+{
+ if(self->playbackManager)
+ delete reinterpret_cast<std::shared_ptr<aud::PlaybackManager>*>(self->playbackManager);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+PyDoc_STRVAR(M_aud_PlaybackManager_play_doc,
+ "setVolume(sound, catKey)\n\n"
+ "Plays a sound through the playback manager and assigns it to a category.\n\n"
+ ":arg sound: The sound to play.\n"
+ ":type sound: :class:`Sound`\n"
+ ":arg catKey: the key of the category in which the sound will be added, if it doesn't exist, a new one will be created.\n"
+ ":type catKey: int\n"
+ ":return: The playback handle with which playback can be controlled with.\n"
+ ":rtype: :class:`Handle`");
+
+static PyObject *
+PlaybackManager_play(PlaybackManagerP* self, PyObject* args)
+{
+ PyObject* object;
+ unsigned int cat;
+
+ if(!PyArg_ParseTuple(args, "OI:catKey", &object, &cat))
+ return nullptr;
+
+ Sound* sound = checkSound(object);
+ if(!sound)
+ return nullptr;
+
+ Handle* handle;
+
+ handle = (Handle*)Handle_empty();
+ if(handle != nullptr)
+ {
+ try
+ {
+ handle->handle = new std::shared_ptr<aud::IHandle>((*reinterpret_cast<std::shared_ptr<aud::PlaybackManager>*>(self->playbackManager))->play(*reinterpret_cast<std::shared_ptr<aud::ISound>*>(sound->sound), cat));
+ }
+ catch(aud::Exception& e)
+ {
+ Py_DECREF(handle);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)handle;
+}
+
+PyDoc_STRVAR(M_aud_PlaybackManager_resume_doc,
+ "resume(catKey)\n\n"
+ "Resumes playback of the catgory.\n\n"
+ ":arg catKey: the key of the category.\n"
+ ":type catKey: int\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: bool");
+
+static PyObject *
+PlaybackManager_resume(PlaybackManagerP* self, PyObject* args)
+{
+ unsigned int cat;
+
+ if(!PyArg_ParseTuple(args, "I:catKey", &cat))
+ return nullptr;
+
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<aud::PlaybackManager>*>(self->playbackManager))->resume(cat));
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_PlaybackManager_pause_doc,
+ "pause(catKey)\n\n"
+ "Pauses playback of the category.\n\n"
+ ":arg catKey: the key of the category.\n"
+ ":type catKey: int\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: bool");
+
+static PyObject *
+PlaybackManager_pause(PlaybackManagerP* self, PyObject* args)
+{
+ unsigned int cat;
+
+ if(!PyArg_ParseTuple(args, "I:catKey", &cat))
+ return nullptr;
+
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<aud::PlaybackManager>*>(self->playbackManager))->pause(cat));
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_PlaybackManager_add_category_doc,
+ "addCategory(volume)\n\n"
+ "Adds a category with a custom volume.\n\n"
+ ":arg volume: The volume for ther new category.\n"
+ ":type volume: float\n"
+ ":return: The key of the new category.\n"
+ ":rtype: int\n\n");
+
+static PyObject *
+PlaybackManager_add_category(PlaybackManagerP* self, PyObject* args)
+{
+ float vol;
+
+ if(!PyArg_ParseTuple(args, "f:volume", &vol))
+ return nullptr;
+
+ try
+ {
+ return Py_BuildValue("I", (*reinterpret_cast<std::shared_ptr<aud::PlaybackManager>*>(self->playbackManager))->addCategory(vol));
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_PlaybackManager_get_volume_doc,
+ "getVolume(catKey)\n\n"
+ "Retrieves the volume of a category.\n\n"
+ ":arg catKey: the key of the category.\n"
+ ":type catKey: int\n"
+ ":return: The volume of the cateogry.\n"
+ ":rtype: float\n\n");
+
+static PyObject *
+PlaybackManager_get_volume(PlaybackManagerP* self, PyObject* args)
+{
+ unsigned int cat;
+
+ if(!PyArg_ParseTuple(args, "I:catKey", &cat))
+ return nullptr;
+
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::PlaybackManager>*>(self->playbackManager))->getVolume(cat));
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_PlaybackManager_set_volume_doc,
+ "setVolume(volume, catKey)\n\n"
+ "Changes the volume of a category.\n\n"
+ ":arg volume: the new volume value.\n"
+ ":type volume: float\n"
+ ":arg catKey: the key of the category.\n"
+ ":type catKey: int\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: int\n\n");
+
+static PyObject *
+PlaybackManager_set_volume(PlaybackManagerP* self, PyObject* args)
+{
+ float volume;
+ unsigned int cat;
+
+ if(!PyArg_ParseTuple(args, "fI:volume", &volume, &cat))
+ return nullptr;
+
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<aud::PlaybackManager>*>(self->playbackManager))->setVolume(volume, cat));
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_PlaybackManager_stop_doc,
+ "stop(catKey)\n\n"
+ "Stops playback of the category.\n\n"
+ ":arg catKey: the key of the category.\n"
+ ":type catKey: int\n"
+ ":return: Whether the action succeeded.\n"
+ ":rtype: bool\n\n");
+
+static PyObject *
+PlaybackManager_stop(PlaybackManagerP* self, PyObject* args)
+{
+ unsigned int cat;
+
+ if(!PyArg_ParseTuple(args, "I:catKey", &cat))
+ return nullptr;
+
+ try
+ {
+ return PyBool_FromLong((long)(*reinterpret_cast<std::shared_ptr<aud::PlaybackManager>*>(self->playbackManager))->stop(cat));
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_PlaybackManager_clean_doc,
+ "clean()\n\n"
+ "Cleans all the invalid and finished sound from the playback manager.\n\n");
+
+static PyObject *
+PlaybackManager_clean(PlaybackManagerP* self)
+{
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<aud::PlaybackManager>*>(self->playbackManager))->clean();
+ Py_RETURN_NONE;
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static PyMethodDef PlaybackManager_methods[] = {
+ { "play", (PyCFunction)PlaybackManager_play, METH_VARARGS | METH_KEYWORDS,
+ M_aud_PlaybackManager_play_doc
+ },
+ { "resume", (PyCFunction)PlaybackManager_resume, METH_VARARGS,
+ M_aud_PlaybackManager_resume_doc
+ },
+ { "pause", (PyCFunction)PlaybackManager_pause, METH_VARARGS,
+ M_aud_PlaybackManager_pause_doc
+ },
+ { "stop", (PyCFunction)PlaybackManager_stop, METH_VARARGS,
+ M_aud_PlaybackManager_stop_doc
+ },
+ { "addCategory", (PyCFunction)PlaybackManager_add_category, METH_VARARGS,
+ M_aud_PlaybackManager_add_category_doc
+ },
+ { "getVolume", (PyCFunction)PlaybackManager_get_volume, METH_VARARGS,
+ M_aud_PlaybackManager_get_volume_doc
+ },
+ { "setVolume", (PyCFunction)PlaybackManager_set_volume, METH_VARARGS,
+ M_aud_PlaybackManager_set_volume_doc
+ },
+ { "clean", (PyCFunction)PlaybackManager_clean, METH_NOARGS,
+ M_aud_PlaybackManager_clean_doc
+ },
+ { nullptr } /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_PlaybackManager_doc,
+ "A PlabackManager object allows to easily control groups os sounds organized in categories.");
+
+PyTypeObject PlaybackManagerType = {
+ PyVarObject_HEAD_INIT(nullptr, 0)
+ "aud.PlaybackManager", /* tp_name */
+ sizeof(PlaybackManagerP), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)PlaybackManager_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ M_aud_PlaybackManager_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ PlaybackManager_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PlaybackManager_new, /* tp_new */
+};
+
+AUD_API PyObject* PlaybackManager_empty()
+{
+ return PlaybackManagerType.tp_alloc(&PlaybackManagerType, 0);
+}
+
+
+AUD_API PlaybackManagerP* checkPlaybackManager(PyObject* playbackManager)
+{
+ if(!PyObject_TypeCheck(playbackManager, &PlaybackManagerType))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type PlaybackManager!");
+ return nullptr;
+ }
+
+ return (PlaybackManagerP*)playbackManager;
+}
+
+
+bool initializePlaybackManager()
+{
+ return PyType_Ready(&PlaybackManagerType) >= 0;
+}
+
+
+void addPlaybackManagerToModule(PyObject* module)
+{
+ Py_INCREF(&PlaybackManagerType);
+ PyModule_AddObject(module, "PlaybackManager", (PyObject *)&PlaybackManagerType);
+}
diff --git a/extern/audaspace/bindings/python/PyPlaybackManager.h b/extern/audaspace/bindings/python/PyPlaybackManager.h
new file mode 100644
index 00000000000..f26df1b32d0
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyPlaybackManager.h
@@ -0,0 +1,33 @@
+/*******************************************************************************
+* Copyright 2015-2016 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#pragma once
+
+#include <Python.h>
+#include "Audaspace.h"
+
+typedef void Reference_PlaybackManager;
+
+typedef struct {
+ PyObject_HEAD
+ Reference_PlaybackManager* playbackManager;
+} PlaybackManagerP;
+
+extern AUD_API PyObject* PlaybackManager_empty();
+extern AUD_API PlaybackManagerP* checkPlaybackManager(PyObject* playbackManager);
+
+bool initializePlaybackManager();
+void addPlaybackManagerToModule(PyObject* module); \ No newline at end of file
diff --git a/extern/audaspace/bindings/python/PySequence.cpp b/extern/audaspace/bindings/python/PySequence.cpp
new file mode 100644
index 00000000000..d4773c743ee
--- /dev/null
+++ b/extern/audaspace/bindings/python/PySequence.cpp
@@ -0,0 +1,655 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#include "PySequence.h"
+
+#include "PySound.h"
+#include "PySequenceEntry.h"
+
+#include "sequence/AnimateableProperty.h"
+#include "sequence/Sequence.h"
+#include "Exception.h"
+
+#include <vector>
+#include <structmember.h>
+
+using aud::Channels;
+using aud::DistanceModel;
+using aud::Exception;
+using aud::ISound;
+using aud::AnimateableProperty;
+using aud::AnimateablePropertyType;
+using aud::Specs;
+
+extern PyObject* AUDError;
+
+// ====================================================================
+
+static void
+Sequence_dealloc(Sequence* self)
+{
+ if(self->sequence)
+ delete reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *
+Sequence_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
+{
+ Sequence* self;
+
+ int channels = aud::CHANNELS_STEREO;
+ double rate = aud::RATE_48000;
+ float fps = 30.0f;
+ bool muted = false;
+ PyObject* mutedo = nullptr;
+
+ self = (Sequence*)type->tp_alloc(type, 0);
+ if(self != nullptr)
+ {
+ static const char* kwlist[] = {"channels", "rate", "fps", "muted", nullptr};
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "|idfO:Sequence", const_cast<char**>(kwlist), &channels, &rate, &fps, &mutedo))
+ {
+ Py_DECREF(self);
+ return nullptr;
+ }
+
+ if(mutedo)
+ {
+ if(!PyBool_Check(mutedo))
+ {
+ PyErr_SetString(PyExc_TypeError, "muted is not a boolean!");
+ return nullptr;
+ }
+
+ muted = mutedo == Py_True;
+ }
+
+ aud::Specs specs;
+ specs.channels = static_cast<aud::Channels>(channels);
+ specs.rate = rate;
+
+ try
+ {
+ self->sequence = new std::shared_ptr<aud::Sequence>(new aud::Sequence(specs, fps, muted));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Sequence_add_doc,
+ "add()\n\n"
+ "Adds a new entry to the scene.\n"
+ ":arg sound: The sound this entry should play.\n"
+ ":type sound: :class:`Sound`\n"
+ ":arg begin: The start time.\n"
+ ":type begin: float\n"
+ ":arg end: The end time or a negative value if determined by the sound.\n"
+ ":type end: float\n"
+ ":arg skip: How much seconds should be skipped at the beginning.\n"
+ ":type skip: float\n"
+ ":return: The entry added.\n"
+ ":rtype: :class:`SequenceEntry`");
+
+static PyObject *
+Sequence_add(Sequence* self, PyObject* args, PyObject* kwds)
+{
+ PyObject* object;
+ float begin;
+ float end = -1.0f;
+ float skip = 0.0f;
+
+ static const char* kwlist[] = {"sound", "begin", "end", "skip", nullptr};
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "Of|ff:add", const_cast<char**>(kwlist), &object, &begin, &end, &skip))
+ return nullptr;
+
+ Sound* sound = checkSound(object);
+
+ if(!sound)
+ return nullptr;
+
+ SequenceEntry* entry;
+
+ entry = (SequenceEntry*)SequenceEntry_empty();
+ if(entry != nullptr)
+ {
+ try
+ {
+ entry->entry = new std::shared_ptr<aud::SequenceEntry>((*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->add(*reinterpret_cast<std::shared_ptr<ISound>*>(sound->sound), begin, end, skip));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(entry);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)entry;
+}
+
+PyDoc_STRVAR(M_aud_Sequence_remove_doc,
+ "reomve()\n\n"
+ "Adds a new entry to the scene.\n"
+ ":arg entry: The entry to remove.\n"
+ ":type entry: :class:`SequenceEntry`\n");
+
+static PyObject *
+Sequence_remove(Sequence* self, PyObject* args)
+{
+ PyObject* object;
+
+ if(!PyArg_ParseTuple(args, "O:remove", &object))
+ return nullptr;
+
+ SequenceEntry* entry = checkSequenceEntry(object);
+
+ if(!entry)
+ return nullptr;
+
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->remove(*reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(entry->entry));
+ Py_RETURN_NONE;
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(entry);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Sequence_setAnimationData_doc,
+ "setAnimationData()\n\n"
+ "Writes animation data to a sequence.\n\n"
+ ":arg type: The type of animation data.\n"
+ ":type type: int\n"
+ ":arg frame: The frame this data is for.\n"
+ ":type frame: int\n"
+ ":arg data: The data to write.\n"
+ ":type data: sequence of float\n"
+ ":arg animated: Whether the attribute is animated.\n"
+ ":type animated: bool");
+
+static PyObject *
+Sequence_setAnimationData(Sequence* self, PyObject* args)
+{
+ int type, frame;
+ PyObject* py_data;
+ Py_ssize_t py_data_len;
+ PyObject* animatedo;
+ bool animated;
+
+ if(!PyArg_ParseTuple(args, "iiOO:setAnimationData", &type, &frame, &py_data, &animatedo))
+ return nullptr;
+
+ if(!PySequence_Check(py_data))
+ {
+ PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!");
+ return nullptr;
+ }
+
+ py_data_len= PySequence_Size(py_data);
+
+ std::vector<float> data;
+ data.resize(py_data_len);
+
+ PyObject* py_value;
+ float value;
+
+ for(Py_ssize_t i = 0; i < py_data_len; i++)
+ {
+ py_value = PySequence_GetItem(py_data, i);
+ value= (float)PyFloat_AsDouble(py_value);
+ Py_DECREF(py_value);
+
+ if(value == -1.0f && PyErr_Occurred()) {
+ return nullptr;
+ }
+
+ data.push_back(value);
+ }
+
+ if(!PyBool_Check(animatedo))
+ {
+ PyErr_SetString(PyExc_TypeError, "animated is not a boolean!");
+ return nullptr;
+ }
+
+ animated = animatedo == Py_True;
+
+ try
+ {
+ AnimateableProperty* prop = (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getAnimProperty(static_cast<AnimateablePropertyType>(type));
+
+ if(prop->getCount() != py_data_len)
+ {
+ PyErr_SetString(PyExc_ValueError, "the amount of floats doesn't fit the animated property");
+ return nullptr;
+ }
+
+ if(animated)
+ {
+ if(frame >= 0)
+ prop->write(&data[0], frame, 1);
+ }
+ else
+ {
+ prop->write(&data[0]);
+ }
+ Py_RETURN_NONE;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static PyMethodDef Sequence_methods[] = {
+ {"add", (PyCFunction)Sequence_add, METH_VARARGS | METH_KEYWORDS,
+ M_aud_Sequence_add_doc
+ },
+ {"remove", (PyCFunction)Sequence_remove, METH_VARARGS,
+ M_aud_Sequence_remove_doc
+ },
+ {"setAnimationData", (PyCFunction)Sequence_setAnimationData, METH_VARARGS,
+ M_aud_Sequence_setAnimationData_doc
+ },
+ {nullptr} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Sequence_channels_doc,
+ "The channel count of the sequence.");
+
+static PyObject *
+Sequence_get_channels(Sequence* self, void* nothing)
+{
+ try
+ {
+ Specs specs = (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getSpecs();
+ return Py_BuildValue("i", specs.channels);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Sequence_set_channels(Sequence* self, PyObject* args, void* nothing)
+{
+ int channels;
+
+ if(!PyArg_Parse(args, "i:channels", &channels))
+ return -1;
+
+ try
+ {
+ std::shared_ptr<aud::Sequence> sequence = *reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence);
+ Specs specs = sequence->getSpecs();
+ specs.channels = static_cast<Channels>(channels);
+ sequence->setSpecs(specs);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return -1;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Sequence_distance_model_doc,
+ "The distance model of the sequence.\n\n"
+ ".. seealso:: http://connect.creativelabs.com/openal/Documentation/OpenAL%201.1%20Specification.htm#_Toc199835864");
+
+static PyObject *
+Sequence_get_distance_model(Sequence* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("i", (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getDistanceModel());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Sequence_set_distance_model(Sequence* self, PyObject* args, void* nothing)
+{
+ int distance_model;
+
+ if(!PyArg_Parse(args, "i:distance_model", &distance_model))
+ return -1;
+
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->setDistanceModel(static_cast<DistanceModel>(distance_model));
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return -1;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Sequence_doppler_factor_doc,
+ "The doppler factor of the sequence.\n"
+ "This factor is a scaling factor for the velocity vectors in "
+ "doppler calculation. So a value bigger than 1 will exaggerate "
+ "the effect as it raises the velocity.");
+
+static PyObject *
+Sequence_get_doppler_factor(Sequence* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getDopplerFactor());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Sequence_set_doppler_factor(Sequence* self, PyObject* args, void* nothing)
+{
+ float factor;
+
+ if(!PyArg_Parse(args, "f:doppler_factor", &factor))
+ return -1;
+
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->setDopplerFactor(factor);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return -1;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Sequence_fps_doc,
+ "The listeners's location in 3D space, a 3D tuple of floats.");
+
+static PyObject *
+Sequence_get_fps(Sequence* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getFPS());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Sequence_set_fps(Sequence* self, PyObject* args, void* nothing)
+{
+ float fps;
+
+ if(!PyArg_Parse(args, "f:fps", &fps))
+ return -1;
+
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->setFPS(fps);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return -1;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Sequence_muted_doc,
+ "Whether the whole sequence is muted.\n");
+
+static PyObject *
+Sequence_get_muted(Sequence* self, void* nothing)
+{
+ try
+ {
+ std::shared_ptr<aud::Sequence>* sequence = reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence);
+ return PyBool_FromLong((long)(*sequence)->isMuted());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Sequence_set_muted(Sequence* self, PyObject* args, void* nothing)
+{
+ if(!PyBool_Check(args))
+ {
+ PyErr_SetString(PyExc_TypeError, "muted is not a boolean!");
+ return -1;
+ }
+
+ bool muted = args == Py_True;
+
+ try
+ {
+ std::shared_ptr<aud::Sequence>* sequence = reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence);
+ (*sequence)->mute(muted);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_Sequence_rate_doc,
+ "The sampling rate of the sequence in Hz.");
+
+static PyObject *
+Sequence_get_rate(Sequence* self, void* nothing)
+{
+ try
+ {
+ Specs specs = (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getSpecs();
+ return Py_BuildValue("d", specs.rate);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Sequence_set_rate(Sequence* self, PyObject* args, void* nothing)
+{
+ double rate;
+
+ if(!PyArg_Parse(args, "d:rate", &rate))
+ return -1;
+
+ try
+ {
+ std::shared_ptr<aud::Sequence> sequence = *reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence);
+ Specs specs = sequence->getSpecs();
+ specs.rate = rate;
+ sequence->setSpecs(specs);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return -1;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Sequence_speed_of_sound_doc,
+ "The speed of sound of the sequence.\n"
+ "The speed of sound in air is typically 343.3 m/s.");
+
+static PyObject *
+Sequence_get_speed_of_sound(Sequence* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->getSpeedOfSound());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+Sequence_set_speed_of_sound(Sequence* self, PyObject* args, void* nothing)
+{
+ float speed;
+
+ if(!PyArg_Parse(args, "f:speed_of_sound", &speed))
+ return -1;
+
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<aud::Sequence>*>(self->sequence))->setSpeedOfSound(speed);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return -1;
+ }
+}
+
+static PyGetSetDef Sequence_properties[] = {
+ {(char*)"channels", (getter)Sequence_get_channels, (setter)Sequence_set_channels,
+ M_aud_Sequence_channels_doc, nullptr },
+ {(char*)"distance_model", (getter)Sequence_get_distance_model, (setter)Sequence_set_distance_model,
+ M_aud_Sequence_distance_model_doc, nullptr },
+ {(char*)"doppler_factor", (getter)Sequence_get_doppler_factor, (setter)Sequence_set_doppler_factor,
+ M_aud_Sequence_doppler_factor_doc, nullptr },
+ {(char*)"fps", (getter)Sequence_get_fps, (setter)Sequence_set_fps,
+ M_aud_Sequence_fps_doc, nullptr },
+ {(char*)"muted", (getter)Sequence_get_muted, (setter)Sequence_set_muted,
+ M_aud_Sequence_muted_doc, nullptr },
+ {(char*)"rate", (getter)Sequence_get_rate, (setter)Sequence_set_rate,
+ M_aud_Sequence_rate_doc, nullptr },
+ {(char*)"speed_of_sound", (getter)Sequence_get_speed_of_sound, (setter)Sequence_set_speed_of_sound,
+ M_aud_Sequence_speed_of_sound_doc, nullptr },
+ {nullptr} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Sequence_doc,
+ "This sound represents sequenced entries to play a sound scene.");
+
+extern PyTypeObject SoundType;
+
+static PyTypeObject SequenceType = {
+ PyVarObject_HEAD_INIT(nullptr, 0)
+ "aud.Sequence", /* tp_name */
+ sizeof(Sequence), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Sequence_dealloc,/* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ M_aud_Sequence_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ Sequence_methods, /* tp_methods */
+ 0, /* tp_members */
+ Sequence_properties, /* tp_getset */
+ &SoundType, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Sequence_new, /* tp_new */
+};
+
+AUD_API PyObject* Sequence_empty()
+{
+ return SequenceType.tp_alloc(&SequenceType, 0);
+}
+
+
+AUD_API Sequence* checkSequence(PyObject* sequence)
+{
+ if(!PyObject_TypeCheck(sequence, &SequenceType))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type Sequence!");
+ return nullptr;
+ }
+
+ return (Sequence*)sequence;
+}
+
+
+bool initializeSequence()
+{
+ return PyType_Ready(&SequenceType) >= 0;
+}
+
+
+void addSequenceToModule(PyObject* module)
+{
+ Py_INCREF(&SequenceType);
+ PyModule_AddObject(module, "Sequence", (PyObject *)&SequenceType);
+}
diff --git a/extern/audaspace/bindings/python/PySequence.h b/extern/audaspace/bindings/python/PySequence.h
new file mode 100644
index 00000000000..17855121dda
--- /dev/null
+++ b/extern/audaspace/bindings/python/PySequence.h
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+#include <Python.h>
+#include "Audaspace.h"
+
+typedef void Reference_Sequence;
+
+typedef struct {
+ PyObject_HEAD
+ Reference_Sequence* sequence;
+} Sequence;
+
+extern AUD_API PyObject* Sequence_empty();
+extern AUD_API Sequence* checkSequence(PyObject* sequence);
+
+bool initializeSequence();
+void addSequenceToModule(PyObject* module);
diff --git a/extern/audaspace/bindings/python/PySequenceEntry.cpp b/extern/audaspace/bindings/python/PySequenceEntry.cpp
new file mode 100644
index 00000000000..e6a034ed880
--- /dev/null
+++ b/extern/audaspace/bindings/python/PySequenceEntry.cpp
@@ -0,0 +1,740 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#include "PySequenceEntry.h"
+
+#include "PySound.h"
+
+#include "Exception.h"
+#include "sequence/AnimateableProperty.h"
+#include "sequence/SequenceEntry.h"
+
+#include <structmember.h>
+#include <vector>
+
+using aud::Exception;
+using aud::AnimateableProperty;
+using aud::AnimateablePropertyType;
+using aud::ISound;
+
+extern PyObject* AUDError;
+
+// ====================================================================
+
+static void
+SequenceEntry_dealloc(SequenceEntry* self)
+{
+ if(self->entry)
+ delete reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+PyDoc_STRVAR(M_aud_SequenceEntry_move_doc,
+ "move()\n\n"
+ "Moves the entry.\n\n"
+ ":arg begin: The new start time.\n"
+ ":type begin: float\n"
+ ":arg end: The new end time or a negative value if unknown.\n"
+ ":type end: float\n"
+ ":arg skip: How many seconds to skip at the beginning.\n"
+ ":type skip: float\n");
+
+static PyObject *
+SequenceEntry_move(SequenceEntry* self, PyObject* args)
+{
+ float begin, end, skip;
+
+ if(!PyArg_ParseTuple(args, "fff:move", &begin, &end, &skip))
+ return nullptr;
+
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry))->move(begin, end, skip);
+ Py_RETURN_NONE;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_SequenceEntry_setAnimationData_doc,
+ "setAnimationData()\n\n"
+ "Writes animation data to a sequenced entry.\n\n"
+ ":arg type: The type of animation data.\n"
+ ":type type: int\n"
+ ":arg frame: The frame this data is for.\n"
+ ":type frame: int\n"
+ ":arg data: The data to write.\n"
+ ":type data: sequence of float\n"
+ ":arg animated: Whether the attribute is animated.\n"
+ ":type animated: bool");
+
+static PyObject *
+SequenceEntry_setAnimationData(SequenceEntry* self, PyObject* args)
+{
+ int type, frame;
+ PyObject* py_data;
+ Py_ssize_t py_data_len;
+ PyObject* animatedo;
+ bool animated;
+
+ if(!PyArg_ParseTuple(args, "iiOO:setAnimationData", &type, &frame, &py_data, &animatedo))
+ return nullptr;
+
+ if(!PySequence_Check(py_data))
+ {
+ PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!");
+ return nullptr;
+ }
+
+ py_data_len= PySequence_Size(py_data);
+
+ std::vector<float> data;
+ data.resize(py_data_len);
+
+ PyObject* py_value;
+ float value;
+
+ for(Py_ssize_t i = 0; i < py_data_len; i++)
+ {
+ py_value = PySequence_GetItem(py_data, i);
+ value= (float)PyFloat_AsDouble(py_value);
+ Py_DECREF(py_value);
+
+ if(value == -1.0f && PyErr_Occurred()) {
+ return nullptr;
+ }
+
+ data.push_back(value);
+ }
+
+ if(!PyBool_Check(animatedo))
+ {
+ PyErr_SetString(PyExc_TypeError, "animated is not a boolean!");
+ return nullptr;
+ }
+
+ animated = animatedo == Py_True;
+
+ try
+ {
+ AnimateableProperty* prop = (*reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry))->getAnimProperty(static_cast<AnimateablePropertyType>(type));
+
+ if(prop->getCount() != py_data_len)
+ {
+ PyErr_SetString(PyExc_ValueError, "the amount of floats doesn't fit the animated property");
+ return nullptr;
+ }
+
+ if(animated)
+ {
+ if(frame >= 0)
+ prop->write(&data[0], frame, 1);
+ }
+ else
+ {
+ prop->write(&data[0]);
+ }
+ Py_RETURN_NONE;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static PyMethodDef SequenceEntry_methods[] = {
+ {"move", (PyCFunction)SequenceEntry_move, METH_VARARGS,
+ M_aud_SequenceEntry_move_doc
+ },
+ {"setAnimationData", (PyCFunction)SequenceEntry_setAnimationData, METH_VARARGS,
+ M_aud_SequenceEntry_setAnimationData_doc
+ },
+ {nullptr} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_SequenceEntry_attenuation_doc,
+ "This factor is used for distance based attenuation of the "
+ "source.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+SequenceEntry_get_attenuation(SequenceEntry* self, void* nothing)
+{
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ return Py_BuildValue("f", (*entry)->getAttenuation());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+SequenceEntry_set_attenuation(SequenceEntry* self, PyObject* args, void* nothing)
+{
+ float factor;
+
+ if(!PyArg_Parse(args, "f:attenuation", &factor))
+ return -1;
+
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ (*entry)->setAttenuation(factor);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_SequenceEntry_cone_angle_inner_doc,
+ "The opening angle of the inner cone of the source. If the cone "
+ "values of a source are set there are two (audible) cones with "
+ "the apex at the :attr:`location` of the source and with infinite "
+ "height, heading in the direction of the source's "
+ ":attr:`orientation`.\n"
+ "In the inner cone the volume is normal. Outside the outer cone "
+ "the volume will be :attr:`cone_volume_outer` and in the area "
+ "between the volume will be interpolated linearly.");
+
+static PyObject *
+SequenceEntry_get_cone_angle_inner(SequenceEntry* self, void* nothing)
+{
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ return Py_BuildValue("f", (*entry)->getConeAngleInner());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+SequenceEntry_set_cone_angle_inner(SequenceEntry* self, PyObject* args, void* nothing)
+{
+ float angle;
+
+ if(!PyArg_Parse(args, "f:cone_angle_inner", &angle))
+ return -1;
+
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ (*entry)->setConeAngleInner(angle);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_SequenceEntry_cone_angle_outer_doc,
+ "The opening angle of the outer cone of the source.\n\n"
+ ".. seealso:: :attr:`cone_angle_inner`");
+
+static PyObject *
+SequenceEntry_get_cone_angle_outer(SequenceEntry* self, void* nothing)
+{
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ return Py_BuildValue("f", (*entry)->getConeAngleOuter());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+SequenceEntry_set_cone_angle_outer(SequenceEntry* self, PyObject* args, void* nothing)
+{
+ float angle;
+
+ if(!PyArg_Parse(args, "f:cone_angle_outer", &angle))
+ return -1;
+
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ (*entry)->setConeAngleOuter(angle);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_SequenceEntry_cone_volume_outer_doc,
+ "The volume outside the outer cone of the source.\n\n"
+ ".. seealso:: :attr:`cone_angle_inner`");
+
+static PyObject *
+SequenceEntry_get_cone_volume_outer(SequenceEntry* self, void* nothing)
+{
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ return Py_BuildValue("f", (*entry)->getConeVolumeOuter());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+SequenceEntry_set_cone_volume_outer(SequenceEntry* self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:cone_volume_outer", &volume))
+ return -1;
+
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ (*entry)->setConeVolumeOuter(volume);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_SequenceEntry_distance_maximum_doc,
+ "The maximum distance of the source.\n"
+ "If the listener is further away the source volume will be 0.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+SequenceEntry_get_distance_maximum(SequenceEntry* self, void* nothing)
+{
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ return Py_BuildValue("f", (*entry)->getDistanceMaximum());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+SequenceEntry_set_distance_maximum(SequenceEntry* self, PyObject* args, void* nothing)
+{
+ float distance;
+
+ if(!PyArg_Parse(args, "f:distance_maximum", &distance))
+ return -1;
+
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ (*entry)->setDistanceMaximum(distance);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_SequenceEntry_distance_reference_doc,
+ "The reference distance of the source.\n"
+ "At this distance the volume will be exactly :attr:`volume`.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+SequenceEntry_get_distance_reference(SequenceEntry* self, void* nothing)
+{
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ return Py_BuildValue("f", (*entry)->getDistanceReference());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+SequenceEntry_set_distance_reference(SequenceEntry* self, PyObject* args, void* nothing)
+{
+ float distance;
+
+ if(!PyArg_Parse(args, "f:distance_reference", &distance))
+ return -1;
+
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ (*entry)->setDistanceReference(distance);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_SequenceEntry_muted_doc,
+ "Whether the entry is muted.\n");
+
+static PyObject *
+SequenceEntry_get_muted(SequenceEntry* self, void* nothing)
+{
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ return PyBool_FromLong((long)(*entry)->isMuted());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+SequenceEntry_set_muted(SequenceEntry* self, PyObject* args, void* nothing)
+{
+ if(!PyBool_Check(args))
+ {
+ PyErr_SetString(PyExc_TypeError, "muted is not a boolean!");
+ return -1;
+ }
+
+ bool muted = args == Py_True;
+
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ (*entry)->mute(muted);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_SequenceEntry_relative_doc,
+ "Whether the source's location, velocity and orientation is relative or absolute to the listener.");
+
+static PyObject *
+SequenceEntry_get_relative(SequenceEntry* self, void* nothing)
+{
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ return PyBool_FromLong((long)(*entry)->isRelative());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return nullptr;
+}
+
+static int
+SequenceEntry_set_relative(SequenceEntry* self, PyObject* args, void* nothing)
+{
+ if(!PyBool_Check(args))
+ {
+ PyErr_SetString(PyExc_TypeError, "Value is not a boolean!");
+ return -1;
+ }
+
+ bool relative = (args == Py_True);
+
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ (*entry)->setRelative(relative);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_SequenceEntry_sound_doc,
+ "The sound the entry is representing and will be played in the sequence.");
+
+static PyObject *
+SequenceEntry_get_sound(SequenceEntry* self, void* nothing)
+{
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ Sound* object = (Sound*) Sound_empty();
+ if(object)
+ {
+ object->sound = new std::shared_ptr<ISound>((*entry)->getSound());
+ return (PyObject *) object;
+ }
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return nullptr;
+}
+
+static int
+SequenceEntry_set_sound(SequenceEntry* self, PyObject* args, void* nothing)
+{
+ Sound* sound = checkSound(args);
+
+ if(!sound)
+ return -1;
+
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ (*entry)->setSound(*reinterpret_cast<std::shared_ptr<ISound>*>(sound->sound));
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_SequenceEntry_volume_maximum_doc,
+ "The maximum volume of the source.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+SequenceEntry_get_volume_maximum(SequenceEntry* self, void* nothing)
+{
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ return Py_BuildValue("f", (*entry)->getVolumeMaximum());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+SequenceEntry_set_volume_maximum(SequenceEntry* self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:volume_maximum", &volume))
+ return -1;
+
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ (*entry)->setVolumeMaximum(volume);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+PyDoc_STRVAR(M_aud_SequenceEntry_volume_minimum_doc,
+ "The minimum volume of the source.\n\n"
+ ".. seealso:: :attr:`Device.distance_model`");
+
+static PyObject *
+SequenceEntry_get_volume_minimum(SequenceEntry* self, void* nothing)
+{
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ return Py_BuildValue("f", (*entry)->getVolumeMinimum());
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static int
+SequenceEntry_set_volume_minimum(SequenceEntry* self, PyObject* args, void* nothing)
+{
+ float volume;
+
+ if(!PyArg_Parse(args, "f:volume_minimum", &volume))
+ return -1;
+
+ try
+ {
+ std::shared_ptr<aud::SequenceEntry>* entry = reinterpret_cast<std::shared_ptr<aud::SequenceEntry>*>(self->entry);
+ (*entry)->setVolumeMinimum(volume);
+ return 0;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+static PyGetSetDef SequenceEntry_properties[] = {
+ {(char*)"attenuation", (getter)SequenceEntry_get_attenuation, (setter)SequenceEntry_set_attenuation,
+ M_aud_SequenceEntry_attenuation_doc, nullptr },
+ {(char*)"cone_angle_inner", (getter)SequenceEntry_get_cone_angle_inner, (setter)SequenceEntry_set_cone_angle_inner,
+ M_aud_SequenceEntry_cone_angle_inner_doc, nullptr },
+ {(char*)"cone_angle_outer", (getter)SequenceEntry_get_cone_angle_outer, (setter)SequenceEntry_set_cone_angle_outer,
+ M_aud_SequenceEntry_cone_angle_outer_doc, nullptr },
+ {(char*)"cone_volume_outer", (getter)SequenceEntry_get_cone_volume_outer, (setter)SequenceEntry_set_cone_volume_outer,
+ M_aud_SequenceEntry_cone_volume_outer_doc, nullptr },
+ {(char*)"distance_maximum", (getter)SequenceEntry_get_distance_maximum, (setter)SequenceEntry_set_distance_maximum,
+ M_aud_SequenceEntry_distance_maximum_doc, nullptr },
+ {(char*)"distance_reference", (getter)SequenceEntry_get_distance_reference, (setter)SequenceEntry_set_distance_reference,
+ M_aud_SequenceEntry_distance_reference_doc, nullptr },
+ {(char*)"muted", (getter)SequenceEntry_get_muted, (setter)SequenceEntry_set_muted,
+ M_aud_SequenceEntry_muted_doc, nullptr },
+ {(char*)"relative", (getter)SequenceEntry_get_relative, (setter)SequenceEntry_set_relative,
+ M_aud_SequenceEntry_relative_doc, nullptr },
+ {(char*)"sound", (getter)SequenceEntry_get_sound, (setter)SequenceEntry_set_sound,
+ M_aud_SequenceEntry_sound_doc, nullptr },
+ {(char*)"volume_maximum", (getter)SequenceEntry_get_volume_maximum, (setter)SequenceEntry_set_volume_maximum,
+ M_aud_SequenceEntry_volume_maximum_doc, nullptr },
+ {(char*)"volume_minimum", (getter)SequenceEntry_get_volume_minimum, (setter)SequenceEntry_set_volume_minimum,
+ M_aud_SequenceEntry_volume_minimum_doc, nullptr },
+ {nullptr} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_SequenceEntry_doc,
+ "SequenceEntry objects represent an entry of a sequenced sound.");
+
+static PyTypeObject SequenceEntryType = {
+ PyVarObject_HEAD_INIT(nullptr, 0)
+ "aud.SequenceEntry", /* tp_name */
+ sizeof(SequenceEntry), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)SequenceEntry_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ M_aud_SequenceEntry_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ SequenceEntry_methods, /* tp_methods */
+ 0, /* tp_members */
+ SequenceEntry_properties, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+AUD_API PyObject* SequenceEntry_empty()
+{
+ return SequenceEntryType.tp_alloc(&SequenceEntryType, 0);
+}
+
+
+AUD_API SequenceEntry* checkSequenceEntry(PyObject* entry)
+{
+ if(!PyObject_TypeCheck(entry, &SequenceEntryType))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type SequenceEntry!");
+ return nullptr;
+ }
+
+ return (SequenceEntry*)entry;
+}
+
+
+bool initializeSequenceEntry()
+{
+ return PyType_Ready(&SequenceEntryType) >= 0;
+}
+
+
+void addSequenceEntryToModule(PyObject* module)
+{
+ Py_INCREF(&SequenceEntryType);
+ PyModule_AddObject(module, "SequenceEntry", (PyObject *)&SequenceEntryType);
+}
diff --git a/extern/audaspace/bindings/python/PySequenceEntry.h b/extern/audaspace/bindings/python/PySequenceEntry.h
new file mode 100644
index 00000000000..7bb4ae4a281
--- /dev/null
+++ b/extern/audaspace/bindings/python/PySequenceEntry.h
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+#include <Python.h>
+#include "Audaspace.h"
+
+typedef void Reference_SequenceEntry;
+
+typedef struct {
+ PyObject_HEAD
+ Reference_SequenceEntry* entry;
+} SequenceEntry;
+
+extern AUD_API PyObject* SequenceEntry_empty();
+extern AUD_API SequenceEntry* checkSequenceEntry(PyObject* entry);
+
+bool initializeSequenceEntry();
+void addSequenceEntryToModule(PyObject* module);
diff --git a/extern/audaspace/bindings/python/PySound.cpp b/extern/audaspace/bindings/python/PySound.cpp
new file mode 100644
index 00000000000..2ab1974be49
--- /dev/null
+++ b/extern/audaspace/bindings/python/PySound.cpp
@@ -0,0 +1,1966 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#include "PySound.h"
+#include "PySource.h"
+#include "PyThreadPool.h"
+
+#ifdef WITH_CONVOLUTION
+#include "PyHRTF.h"
+#include "PyImpulseResponse.h"
+#endif
+
+#include "Exception.h"
+#include "file/File.h"
+#include "file/FileWriter.h"
+#include "util/StreamBuffer.h"
+#include "generator/Sawtooth.h"
+#include "generator/Silence.h"
+#include "generator/Sine.h"
+#include "generator/Square.h"
+#include "generator/Triangle.h"
+#include "fx/Accumulator.h"
+#include "fx/ADSR.h"
+#include "fx/Delay.h"
+#include "fx/Envelope.h"
+#include "fx/Fader.h"
+#include "fx/Highpass.h"
+#include "fx/IIRFilter.h"
+#include "fx/Limiter.h"
+#include "fx/Loop.h"
+#include "fx/Lowpass.h"
+#include "fx/MutableSound.h"
+#include "fx/Pitch.h"
+#include "fx/Reverse.h"
+#include "fx/SoundList.h"
+#include "fx/Sum.h"
+#include "fx/Threshold.h"
+#include "fx/Volume.h"
+#include "respec/ChannelMapper.h"
+#include "respec/ChannelMapperReader.h"
+#include "respec/LinearResample.h"
+#include "respec/JOSResample.h"
+#include "respec/JOSResampleReader.h"
+#include "sequence/Double.h"
+#include "sequence/PingPong.h"
+#include "sequence/Superpose.h"
+
+#ifdef WITH_CONVOLUTION
+#include "fx/BinauralSound.h"
+#include "fx/ConvolverSound.h"
+#endif
+
+#include <cstring>
+#include <structmember.h>
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+#include <numpy/ndarrayobject.h>
+
+using namespace aud;
+
+extern PyObject* AUDError;
+
+static void
+Sound_dealloc(Sound* self)
+{
+ if(self->sound)
+ delete reinterpret_cast<std::shared_ptr<ISound>*>(self->sound);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyObject *
+Sound_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
+{
+ Sound* self;
+
+ self = (Sound*)type->tp_alloc(type, 0);
+ if(self != nullptr)
+ {
+ static const char* kwlist[] = {"filename", nullptr};
+ const char* filename = nullptr;
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "s:Sound", const_cast<char**>(kwlist), &filename))
+ {
+ Py_DECREF(self);
+ return nullptr;
+ }
+
+ try
+ {
+ self->sound = new std::shared_ptr<ISound>(new File(filename));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Sound_data_doc,
+ "data()\n\n"
+ "Retrieves the data of the sound as numpy array.\n\n"
+ ":return: A two dimensional numpy float array.\n"
+ ":rtype: :class:`numpy.ndarray`\n\n"
+ ".. note:: Best efficiency with cached sounds.");
+
+static PyObject *
+Sound_data(Sound* self)
+{
+ std::shared_ptr<ISound> sound = *reinterpret_cast<std::shared_ptr<ISound>*>(self->sound);
+
+ auto stream_buffer = std::dynamic_pointer_cast<StreamBuffer>(sound);
+ if(!stream_buffer)
+ stream_buffer = std::make_shared<StreamBuffer>(sound);
+ Specs specs = stream_buffer->getSpecs();
+ auto buffer = stream_buffer->getBuffer();
+
+ npy_intp dimensions[2];
+ dimensions[0] = buffer->getSize() / AUD_SAMPLE_SIZE(specs);
+ dimensions[1] = specs.channels;
+
+ PyArrayObject* array = reinterpret_cast<PyArrayObject*>(PyArray_SimpleNew(2, dimensions, NPY_FLOAT));
+
+ sample_t* data = reinterpret_cast<sample_t*>(PyArray_DATA(array));
+
+ std::memcpy(data, buffer->getBuffer(), buffer->getSize());
+
+ Py_INCREF(array);
+
+ return reinterpret_cast<PyObject*>(array);
+}
+
+PyDoc_STRVAR(M_aud_Sound_write_doc,
+ "write(filename, rate, channels, format, container, codec, bitrate, buffersize)\n\n"
+ "Writes the sound to a file.\n\n"
+ ":arg filename: The path to write to.\n"
+ ":type filename: string\n"
+ ":arg rate: The sample rate to write with.\n"
+ ":type rate: int\n"
+ ":arg channels: The number of channels to write with.\n"
+ ":type channels: int\n"
+ ":arg format: The sample format to write with.\n"
+ ":type format: int\n"
+ ":arg container: The container format for the file.\n"
+ ":type container: int\n"
+ ":arg codec: The codec to use in the file.\n"
+ ":type codec: int\n"
+ ":arg bitrate: The bitrate to write with.\n"
+ ":type bitrate: int\n"
+ ":arg buffersize: The size of the writing buffer.\n"
+ ":type buffersize: int\n");
+
+static PyObject *
+Sound_write(Sound* self, PyObject* args, PyObject* kwds)
+{
+ const char* filename = nullptr;
+ int rate = RATE_INVALID;
+ Channels channels = CHANNELS_INVALID;
+ SampleFormat format = FORMAT_INVALID;
+ Container container = CONTAINER_INVALID;
+ Codec codec = CODEC_INVALID;
+ int bitrate = 0;
+ int buffersize = 0;
+
+ static const char* kwlist[] = {"filename", "rate", "channels", "format", "container", "codec", "bitrate", "buffersize", nullptr};
+
+ if(!PyArg_ParseTupleAndKeywords(args, kwds, "s|iiiiiii:write", const_cast<char**>(kwlist), &filename, &rate, &channels, &format, &container, &codec, &bitrate, &buffersize))
+ return nullptr;
+
+ try
+ {
+ std::shared_ptr<IReader> reader = (*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound))->createReader();
+
+ DeviceSpecs specs;
+ specs.specs = reader->getSpecs();
+
+ if((rate != RATE_INVALID) && (specs.rate != rate))
+ {
+ specs.rate = rate;
+ reader = std::make_shared<JOSResampleReader>(reader, rate);
+ }
+
+ if((channels != CHANNELS_INVALID) && (specs.channels != channels))
+ {
+ specs.channels = channels;
+ reader = std::make_shared<ChannelMapperReader>(reader, channels);
+ }
+
+ if(format == FORMAT_INVALID)
+ format = FORMAT_S16;
+ specs.format = format;
+
+ const char* invalid_container_error = "Container could not be determined from filename.";
+
+ if(container == CONTAINER_INVALID)
+ {
+ std::string path = filename;
+
+ if(path.length() < 4)
+ {
+ PyErr_SetString(AUDError, invalid_container_error);
+ return nullptr;
+ }
+
+ std::string extension = path.substr(path.length() - 4);
+
+ if(extension == ".ac3")
+ container = CONTAINER_AC3;
+ else if(extension == "flac")
+ container = CONTAINER_FLAC;
+ else if(extension == ".mkv")
+ container = CONTAINER_MATROSKA;
+ else if(extension == ".mp2")
+ container = CONTAINER_MP2;
+ else if(extension == ".mp3")
+ container = CONTAINER_MP3;
+ else if(extension == ".ogg")
+ container = CONTAINER_OGG;
+ else if(extension == ".wav")
+ container = CONTAINER_WAV;
+ else
+ {
+ PyErr_SetString(AUDError, invalid_container_error);
+ return nullptr;
+ }
+ }
+
+ if(codec == CODEC_INVALID)
+ {
+ switch(container)
+ {
+ case CONTAINER_AC3:
+ codec = CODEC_AC3;
+ break;
+ case CONTAINER_FLAC:
+ codec = CODEC_FLAC;
+ break;
+ case CONTAINER_MATROSKA:
+ codec = CODEC_OPUS;
+ break;
+ case CONTAINER_MP2:
+ codec = CODEC_MP2;
+ break;
+ case CONTAINER_MP3:
+ codec = CODEC_MP3;
+ break;
+ case CONTAINER_OGG:
+ codec = CODEC_VORBIS;
+ break;
+ case CONTAINER_WAV:
+ codec = CODEC_PCM;
+ break;
+ default:
+ PyErr_SetString(AUDError, "Unknown container, cannot select default codec.");
+ return nullptr;
+ }
+ }
+
+ if(buffersize <= 0)
+ buffersize = AUD_DEFAULT_BUFFER_SIZE;
+
+ std::shared_ptr<IWriter> writer = FileWriter::createWriter(filename, specs, container, codec, bitrate);
+ FileWriter::writeReader(reader, writer, 0, buffersize);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(M_aud_Sound_buffer_doc,
+ "buffer(data, rate)\n\n"
+ "Creates a sound from a data buffer.\n\n"
+ ":arg data: The data as two dimensional numpy array.\n"
+ ":type data: numpy.ndarray\n"
+ ":arg rate: The sample rate.\n"
+ ":type rate: double\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_buffer(PyTypeObject* type, PyObject* args)
+{
+ PyArrayObject* array = nullptr;
+ double rate = RATE_INVALID;
+
+ if(!PyArg_ParseTuple(args, "Od:buffer", &array, &rate))
+ return nullptr;
+
+ if((!PyObject_TypeCheck(reinterpret_cast<PyObject*>(array), &PyArray_Type)) || (PyArray_TYPE(array) != NPY_FLOAT))
+ {
+ PyErr_SetString(PyExc_TypeError, "The data needs to be supplied as float32 numpy array!");
+ return nullptr;
+ }
+
+ if(PyArray_NDIM(array) > 2)
+ {
+ PyErr_SetString(PyExc_TypeError, "The array needs to have one or two dimensions!");
+ return nullptr;
+ }
+
+ if(rate <= 0)
+ {
+ PyErr_SetString(PyExc_TypeError, "The sample rate has to be positive!");
+ return nullptr;
+ }
+
+ Specs specs;
+ specs.rate = rate;
+ specs.channels = CHANNELS_MONO;
+
+ if(PyArray_NDIM(array) == 2)
+ specs.channels = static_cast<Channels>(PyArray_DIM(array, 1));
+
+ int size = PyArray_DIM(array, 0) * AUD_SAMPLE_SIZE(specs);
+
+ std::shared_ptr<Buffer> buffer = std::make_shared<Buffer>(size);
+
+ std::memcpy(buffer->getBuffer(), PyArray_DATA(array), size);
+
+ Sound* self;
+
+ self = (Sound*)type->tp_alloc(type, 0);
+ if(self != nullptr)
+ {
+ try
+ {
+ self->sound = new std::shared_ptr<StreamBuffer>(new StreamBuffer(buffer, specs));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Sound_cache_doc,
+ "cache()\n\n"
+ "Caches a sound into RAM.\n"
+ "This saves CPU usage needed for decoding and file access if the "
+ "underlying sound reads from a file on the harddisk, but it "
+ "consumes a lot of memory.\n\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`\n\n"
+ ".. note:: Only known-length factories can be buffered.\n\n"
+ ".. warning:: Raw PCM data needs a lot of space, only buffer "
+ "short factories.");
+
+static PyObject *
+Sound_cache(Sound* self)
+{
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new StreamBuffer(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound)));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_file_doc,
+ "file(filename)\n\n"
+ "Creates a sound object of a sound file.\n\n"
+ ":arg filename: Path of the file.\n"
+ ":type filename: string\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`\n\n"
+ ".. warning:: If the file doesn't exist or can't be read you will "
+ "not get an exception immediately, but when you try to start "
+ "playback of that sound.");
+
+static PyObject *
+Sound_file(PyTypeObject* type, PyObject* args)
+{
+ const char* filename = nullptr;
+
+ if(!PyArg_ParseTuple(args, "s:file", &filename))
+ return nullptr;
+
+ Sound* self;
+
+ self = (Sound*)type->tp_alloc(type, 0);
+ if(self != nullptr)
+ {
+ try
+ {
+ self->sound = new std::shared_ptr<ISound>(new File(filename));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Sound_sawtooth_doc,
+ "sawtooth(frequency, rate=48000)\n\n"
+ "Creates a sawtooth sound which plays a sawtooth wave.\n\n"
+ ":arg frequency: The frequency of the sawtooth wave in Hz.\n"
+ ":type frequency: float\n"
+ ":arg rate: The sampling rate in Hz. It's recommended to set this "
+ "value to the playback device's samling rate to avoid resamping.\n"
+ ":type rate: int\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_sawtooth(PyTypeObject* type, PyObject* args)
+{
+ float frequency;
+ double rate = 48000;
+
+ if(!PyArg_ParseTuple(args, "f|d:sawtooth", &frequency, &rate))
+ return nullptr;
+
+ Sound* self;
+
+ self = (Sound*)type->tp_alloc(type, 0);
+ if(self != nullptr)
+ {
+ try
+ {
+ self->sound = new std::shared_ptr<ISound>(new Sawtooth(frequency, (SampleRate)rate));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Sound_silence_doc,
+ "silence()\n\n"
+ "Creates a silence sound which plays simple silence.\n\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_silence(PyTypeObject* type)
+{
+ Sound* self;
+
+ self = (Sound*)type->tp_alloc(type, 0);
+ if(self != nullptr)
+ {
+ try
+ {
+ self->sound = new std::shared_ptr<ISound>(new Silence());
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Sound_sine_doc,
+ "sine(frequency, rate=48000)\n\n"
+ "Creates a sine sound which plays a sine wave.\n\n"
+ ":arg frequency: The frequency of the sine wave in Hz.\n"
+ ":type frequency: float\n"
+ ":arg rate: The sampling rate in Hz. It's recommended to set this "
+ "value to the playback device's samling rate to avoid resamping.\n"
+ ":type rate: int\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_sine(PyTypeObject* type, PyObject* args)
+{
+ float frequency;
+ double rate = 48000;
+
+ if(!PyArg_ParseTuple(args, "f|d:sine", &frequency, &rate))
+ return nullptr;
+
+ Sound* self;
+
+ self = (Sound*)type->tp_alloc(type, 0);
+ if(self != nullptr)
+ {
+ try
+ {
+ self->sound = new std::shared_ptr<ISound>(new Sine(frequency, (SampleRate)rate));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Sound_square_doc,
+ "square(frequency, rate=48000)\n\n"
+ "Creates a square sound which plays a square wave.\n\n"
+ ":arg frequency: The frequency of the square wave in Hz.\n"
+ ":type frequency: float\n"
+ ":arg rate: The sampling rate in Hz. It's recommended to set this "
+ "value to the playback device's samling rate to avoid resamping.\n"
+ ":type rate: int\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_square(PyTypeObject* type, PyObject* args)
+{
+ float frequency;
+ double rate = 48000;
+
+ if(!PyArg_ParseTuple(args, "f|d:square", &frequency, &rate))
+ return nullptr;
+
+ Sound* self;
+
+ self = (Sound*)type->tp_alloc(type, 0);
+ if(self != nullptr)
+ {
+ try
+ {
+ self->sound = new std::shared_ptr<ISound>(new Square(frequency, (SampleRate)rate));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Sound_triangle_doc,
+ "triangle(frequency, rate=48000)\n\n"
+ "Creates a triangle sound which plays a triangle wave.\n\n"
+ ":arg frequency: The frequency of the triangle wave in Hz.\n"
+ ":type frequency: float\n"
+ ":arg rate: The sampling rate in Hz. It's recommended to set this "
+ "value to the playback device's samling rate to avoid resamping.\n"
+ ":type rate: int\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_triangle(PyTypeObject* type, PyObject* args)
+{
+ float frequency;
+ double rate = 48000;
+
+ if(!PyArg_ParseTuple(args, "f|d:triangle", &frequency, &rate))
+ return nullptr;
+
+ Sound* self;
+
+ self = (Sound*)type->tp_alloc(type, 0);
+ if(self != nullptr)
+ {
+ try
+ {
+ self->sound = new std::shared_ptr<ISound>(new Triangle(frequency, (SampleRate)rate));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Sound_accumulate_doc,
+ "accumulate(additive=False)\n\n"
+ "Accumulates a sound by summing over positive input differences thus generating a monotonic sigal. "
+ "If additivity is set to true negative input differences get added too, but positive ones with a factor of two. "
+ "Note that with additivity the signal is not monotonic anymore.\n\n"
+ ":arg additive: Whether the accumulation should be additive or not.\n"
+ ":type time: bool\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_accumulate(Sound* self, PyObject* args)
+{
+ bool additive = false;
+ PyObject* additiveo;
+
+ if(!PyArg_ParseTuple(args, "|O:accumulate", &additiveo))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ if(additiveo != nullptr)
+ {
+ if(!PyBool_Check(additiveo))
+ {
+ PyErr_SetString(PyExc_TypeError, "additive is not a boolean!");
+ return nullptr;
+ }
+
+ additive = additiveo == Py_True;
+ }
+
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Accumulator(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), additive));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_ADSR_doc,
+ "ADSR(attack,decay,sustain,release)\n\n"
+ "Attack-Decay-Sustain-Release envelopes the volume of a sound. "
+ "Note: there is currently no way to trigger the release with this API.\n\n"
+ ":arg attack: The attack time in seconds.\n"
+ ":type attack: float\n"
+ ":arg decay: The decay time in seconds.\n"
+ ":type decay: float\n"
+ ":arg sustain: The sustain level.\n"
+ ":type sustain: float\n"
+ ":arg release: The release level.\n"
+ ":type release: float\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_ADSR(Sound* self, PyObject* args)
+{
+ float attack, decay, sustain, release;
+
+ if(!PyArg_ParseTuple(args, "ffff:ADSR", &attack, &decay, &sustain, &release))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new ADSR(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), attack, decay, sustain, release));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_delay_doc,
+ "delay(time)\n\n"
+ "Delays by playing adding silence in front of the other sound's "
+ "data.\n\n"
+ ":arg time: How many seconds of silence should be added before "
+ "the sound.\n"
+ ":type time: float\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_delay(Sound* self, PyObject* args)
+{
+ float delay;
+
+ if(!PyArg_ParseTuple(args, "f:delay", &delay))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Delay(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), delay));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_envelope_doc,
+ "envelope(attack, release, threshold, arthreshold)\n\n"
+ "Delays by playing adding silence in front of the other sound's "
+ "data.\n\n"
+ ":arg attack: The attack factor.\n"
+ ":type attack: float\n"
+ ":arg release: The release factor.\n"
+ ":type release: float\n"
+ ":arg threshold: The general threshold value.\n"
+ ":type threshold: float\n"
+ ":arg arthreshold: The attack/release threshold value.\n"
+ ":type arthreshold: float\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_envelope(Sound* self, PyObject* args)
+{
+ float attack, release, threshold, arthreshold;
+
+ if(!PyArg_ParseTuple(args, "ffff:envelope", &attack, &release, &threshold, &arthreshold))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Envelope(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), attack, release, threshold, arthreshold));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_fadein_doc,
+ "fadein(start, length)\n\n"
+ "Fades a sound in by raising the volume linearly in the given "
+ "time interval.\n\n"
+ ":arg start: Time in seconds when the fading should start.\n"
+ ":type start: float\n"
+ ":arg length: Time in seconds how long the fading should last.\n"
+ ":type length: float\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`\n\n"
+ ".. note:: Before the fade starts it plays silence.");
+
+static PyObject *
+Sound_fadein(Sound* self, PyObject* args)
+{
+ float start, length;
+
+ if(!PyArg_ParseTuple(args, "ff:fadein", &start, &length))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Fader(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), FADE_IN, start, length));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_fadeout_doc,
+ "fadeout(start, length)\n\n"
+ "Fades a sound in by lowering the volume linearly in the given "
+ "time interval.\n\n"
+ ":arg start: Time in seconds when the fading should start.\n"
+ ":type start: float\n"
+ ":arg length: Time in seconds how long the fading should last.\n"
+ ":type length: float\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`\n\n"
+ ".. note:: After the fade this sound plays silence, so that "
+ "the length of the sound is not altered.");
+
+static PyObject *
+Sound_fadeout(Sound* self, PyObject* args)
+{
+ float start, length;
+
+ if(!PyArg_ParseTuple(args, "ff:fadeout", &start, &length))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Fader(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), FADE_OUT, start, length));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_filter_doc,
+ "filter(b, a = (1))\n\n"
+ "Filters a sound with the supplied IIR filter coefficients.\n"
+ "Without the second parameter you'll get a FIR filter.\n"
+ "If the first value of the a sequence is 0 it will be set to 1 "
+ "automatically.\n"
+ "If the first value of the a sequence is neither 0 nor 1, all "
+ "filter coefficients will be scaled by this value so that it is 1 "
+ "in the end, you don't have to scale yourself.\n\n"
+ ":arg b: The nominator filter coefficients.\n"
+ ":type b: sequence of float\n"
+ ":arg a: The denominator filter coefficients.\n"
+ ":type a: sequence of float\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_filter(Sound* self, PyObject* args)
+{
+ PyObject* py_b;
+ PyObject* py_a = nullptr;
+ Py_ssize_t py_a_len;
+ Py_ssize_t py_b_len;
+
+ if(!PyArg_ParseTuple(args, "O|O:filter", &py_b, &py_a))
+ return nullptr;
+
+ if(!PySequence_Check(py_b) || (py_a != nullptr && !PySequence_Check(py_a)))
+ {
+ PyErr_SetString(PyExc_TypeError, "Parameter is not a sequence!");
+ return nullptr;
+ }
+
+ py_a_len= py_a ? PySequence_Size(py_a) : 0;
+ py_b_len= PySequence_Size(py_b);
+
+ if(!py_b_len || ((py_a != nullptr) && !py_a_len))
+ {
+ PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!");
+ return nullptr;
+ }
+
+ std::vector<float> a, b;
+ PyObject* py_value;
+ float value;
+
+ for(Py_ssize_t i = 0; i < py_b_len; i++)
+ {
+ py_value = PySequence_GetItem(py_b, i);
+ value= (float)PyFloat_AsDouble(py_value);
+ Py_DECREF(py_value);
+
+ if(value == -1.0f && PyErr_Occurred()) {
+ return nullptr;
+ }
+
+ b.push_back(value);
+ }
+
+ if(py_a)
+ {
+ for(Py_ssize_t i = 0; i < py_a_len; i++)
+ {
+ py_value = PySequence_GetItem(py_a, i);
+ value= (float)PyFloat_AsDouble(py_value);
+ Py_DECREF(py_value);
+
+ if(value == -1.0f && PyErr_Occurred()) {
+ return nullptr;
+ }
+
+ a.push_back(value);
+ }
+
+ if(a[0] == 0)
+ a[0] = 1;
+ }
+ else
+ a.push_back(1);
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new IIRFilter(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), b, a));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_highpass_doc,
+ "highpass(frequency, Q=0.5)\n\n"
+ "Creates a second order highpass filter based on the transfer "
+ "function H(s) = s^2 / (s^2 + s/Q + 1)\n\n"
+ ":arg frequency: The cut off trequency of the highpass.\n"
+ ":type frequency: float\n"
+ ":arg Q: Q factor of the lowpass.\n"
+ ":type Q: float\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_highpass(Sound* self, PyObject* args)
+{
+ float frequency;
+ float Q = 0.5;
+
+ if(!PyArg_ParseTuple(args, "f|f:highpass", &frequency, &Q))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Highpass(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), frequency, Q));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_limit_doc,
+ "limit(start, end)\n\n"
+ "Limits a sound within a specific start and end time.\n\n"
+ ":arg start: Start time in seconds.\n"
+ ":type start: float\n"
+ ":arg end: End time in seconds.\n"
+ ":type end: float\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_limit(Sound* self, PyObject* args)
+{
+ float start, end;
+
+ if(!PyArg_ParseTuple(args, "ff:limit", &start, &end))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Limiter(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), start, end));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_loop_doc,
+ "loop(count)\n\n"
+ "Loops a sound.\n\n"
+ ":arg count: How often the sound should be looped. "
+ "Negative values mean endlessly.\n"
+ ":type count: integer\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`\n\n"
+ ".. note:: This is a filter function, you might consider using "
+ ":attr:`Handle.loop_count` instead.");
+
+static PyObject *
+Sound_loop(Sound* self, PyObject* args)
+{
+ int loop;
+
+ if(!PyArg_ParseTuple(args, "i:loop", &loop))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Loop(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), loop));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_lowpass_doc,
+ "lowpass(frequency, Q=0.5)\n\n"
+ "Creates a second order lowpass filter based on the transfer "
+ "function H(s) = 1 / (s^2 + s/Q + 1)\n\n"
+ ":arg frequency: The cut off trequency of the lowpass.\n"
+ ":type frequency: float\n"
+ ":arg Q: Q factor of the lowpass.\n"
+ ":type Q: float\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_lowpass(Sound* self, PyObject* args)
+{
+ float frequency;
+ float Q = 0.5;
+
+ if(!PyArg_ParseTuple(args, "f|f:lowpass", &frequency, &Q))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Lowpass(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), frequency, Q));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_pitch_doc,
+ "pitch(factor)\n\n"
+ "Changes the pitch of a sound with a specific factor.\n\n"
+ ":arg factor: The factor to change the pitch with.\n"
+ ":type factor: float\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`\n\n"
+ ".. note:: This is done by changing the sample rate of the "
+ "underlying sound, which has to be an integer, so the factor "
+ "value rounded and the factor may not be 100 % accurate.\n\n"
+ ".. note:: This is a filter function, you might consider using "
+ ":attr:`Handle.pitch` instead.");
+
+static PyObject *
+Sound_pitch(Sound* self, PyObject* args)
+{
+ float factor;
+
+ if(!PyArg_ParseTuple(args, "f:pitch", &factor))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Pitch(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), factor));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_rechannel_doc,
+ "rechannel(channels)\n\n"
+ "Rechannels the sound.\n\n"
+ ":arg channels: The new channel configuration.\n"
+ ":type channels: int\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_rechannel(Sound* self, PyObject* args)
+{
+ int channels;
+
+ if(!PyArg_ParseTuple(args, "i:rechannel", &channels))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ DeviceSpecs specs;
+ specs.channels = static_cast<Channels>(channels);
+ specs.rate = RATE_INVALID;
+ specs.format = FORMAT_INVALID;
+ parent->sound = new std::shared_ptr<ISound>(new ChannelMapper(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), specs));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_resample_doc,
+ "resample(rate, high_quality)\n\n"
+ "Resamples the sound.\n\n"
+ ":arg rate: The new sample rate.\n"
+ ":type rate: double\n"
+ ":arg high_quality: When true use a higher quality but slower resampler.\n"
+ ":type high_quality: bool\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_resample(Sound* self, PyObject* args)
+{
+ double rate;
+ PyObject* high_qualityo;
+ bool high_quality = false;
+
+ if(!PyArg_ParseTuple(args, "d|O:resample", &rate, &high_qualityo))
+ return nullptr;
+
+ if(!PyBool_Check(high_qualityo))
+ {
+ PyErr_SetString(PyExc_TypeError, "high_quality is not a boolean!");
+ return nullptr;
+ }
+
+ high_quality = high_qualityo == Py_True;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ DeviceSpecs specs;
+ specs.channels = CHANNELS_INVALID;
+ specs.rate = rate;
+ specs.format = FORMAT_INVALID;
+ if(high_quality)
+ parent->sound = new std::shared_ptr<ISound>(new JOSResample(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), specs));
+ else
+ parent->sound = new std::shared_ptr<ISound>(new LinearResample(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), specs));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_reverse_doc,
+ "reverse()\n\n"
+ "Plays a sound reversed.\n\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`\n\n"
+ ".. note:: The sound has to have a finite length and has to be "
+ "seekable. It's recommended to use this only with factories with "
+ "fast and accurate seeking, which is not true for encoded audio "
+ "files, such ones should be buffered using :meth:`cache` before "
+ "being played reversed.\n\n"
+ ".. warning:: If seeking is not accurate in the underlying sound "
+ "you'll likely hear skips/jumps/cracks.");
+
+static PyObject *
+Sound_reverse(Sound* self)
+{
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Reverse(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound)));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_sum_doc,
+ "sum()\n\n"
+ "Sums the samples of a sound.\n\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_sum(Sound* self)
+{
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Sum(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound)));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_threshold_doc,
+ "threshold(threshold = 0)\n\n"
+ "Makes a threshold wave out of an audio wave by setting all samples "
+ "with a amplitude >= threshold to 1, all <= -threshold to -1 and "
+ "all between to 0.\n\n"
+ ":arg threshold: Threshold value over which an amplitude counts "
+ "non-zero.\n"
+ ":type threshold: float\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_threshold(Sound* self, PyObject* args)
+{
+ float threshold = 0;
+
+ if(!PyArg_ParseTuple(args, "|f:threshold", &threshold))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Threshold(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), threshold));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_volume_doc,
+ "volume(volume)\n\n"
+ "Changes the volume of a sound.\n\n"
+ ":arg volume: The new volume..\n"
+ ":type volume: float\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`\n\n"
+ ".. note:: Should be in the range [0, 1] to avoid clipping.\n\n"
+ ".. note:: This is a filter function, you might consider using "
+ ":attr:`Handle.volume` instead.");
+
+static PyObject *
+Sound_volume(Sound* self, PyObject* args)
+{
+ float volume;
+
+ if(!PyArg_ParseTuple(args, "f:volume", &volume))
+ return nullptr;
+
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Volume(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), volume));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_join_doc,
+ "join(sound)\n\n"
+ "Plays two factories in sequence.\n\n"
+ ":arg sound: The sound to play second.\n"
+ ":type sound: :class:`Sound`\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`\n\n"
+ ".. note:: The two factories have to have the same specifications "
+ "(channels and samplerate).");
+
+static PyObject *
+Sound_join(Sound* self, PyObject* object)
+{
+ PyTypeObject* type = Py_TYPE(self);
+
+ if(!PyObject_TypeCheck(object, type))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object has to be of type Sound!");
+ return nullptr;
+ }
+
+ Sound* parent;
+ Sound* child = (Sound*)object;
+
+ parent = (Sound*)type->tp_alloc(type, 0);
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Double(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), *reinterpret_cast<std::shared_ptr<ISound>*>(child->sound)));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_mix_doc,
+ "mix(sound)\n\n"
+ "Mixes two factories.\n\n"
+ ":arg sound: The sound to mix over the other.\n"
+ ":type sound: :class:`Sound`\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`\n\n"
+ ".. note:: The two factories have to have the same specifications "
+ "(channels and samplerate).");
+
+static PyObject *
+Sound_mix(Sound* self, PyObject* object)
+{
+ PyTypeObject* type = Py_TYPE(self);
+
+ if(!PyObject_TypeCheck(object, type))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type Sound!");
+ return nullptr;
+ }
+
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+ Sound* child = (Sound*)object;
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new Superpose(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), *reinterpret_cast<std::shared_ptr<ISound>*>(child->sound)));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_pingpong_doc,
+ "pingpong()\n\n"
+ "Plays a sound forward and then backward.\n"
+ "This is like joining a sound with its reverse.\n\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_pingpong(Sound* self)
+{
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new PingPong(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound)));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_list_doc,
+ "list()\n\n"
+ "Creates an empty sound list that can contain several sounds.\n\n"
+ ":arg random: wether the playback will be random or not.\n"
+ ":type random: int\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_list(PyTypeObject* type, PyObject* args)
+{
+ int random;
+
+ if(!PyArg_ParseTuple(args, "i:random", &random))
+ return nullptr;
+
+ Sound* self;
+
+ self = (Sound*)type->tp_alloc(type, 0);
+ if(self != nullptr)
+ {
+ try
+ {
+ self->sound = new std::shared_ptr<ISound>(new SoundList(random));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+PyDoc_STRVAR(M_aud_Sound_mutable_doc,
+ "mutable()\n\n"
+ "Creates a sound that will be restarted when sought backwards.\n"
+ "If the original sound is a sound list, the playing sound can change.\n\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_mutable(Sound* self)
+{
+ PyTypeObject* type = Py_TYPE(self);
+ Sound* parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new MutableSound(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound)));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_list_addSound_doc,
+ "addSound(sound)\n\n"
+ "Adds a new sound to a sound list.\n\n"
+ ":arg sound: The sound that will be added to the list.\n"
+ ":type sound: :class:`Sound`\n\n"
+ ".. note:: You can only add a sound to a sound list.");
+
+static PyObject *
+Sound_list_addSound(Sound* self, PyObject* object)
+{
+ PyTypeObject* type = Py_TYPE(self);
+
+ if(!PyObject_TypeCheck(object, type))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object has to be of type Sound!");
+ return nullptr;
+ }
+
+ Sound* child = (Sound*)object;
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<SoundList>*>(self->sound))->addSound(*reinterpret_cast<std::shared_ptr<ISound>*>(child->sound));
+ Py_RETURN_NONE;
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+#ifdef WITH_CONVOLUTION
+
+PyDoc_STRVAR(M_aud_Sound_convolver_doc,
+ "convolver()\n\n"
+ "Creates a sound that will apply convolution to another sound.\n\n"
+ ":arg impulseResponse: The filter with which convolve the sound.\n"
+ ":type impulseResponse: :class:`ImpulseResponse`\n"
+ ":arg threadPool: A thread pool used to parallelize convolution.\n"
+ ":type threadPool: :class:`ThreadPool`\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_convolver(Sound* self, PyObject* args)
+{
+ PyTypeObject* type = Py_TYPE(self);
+
+ PyObject* object1;
+ PyObject* object2;
+
+ if(!PyArg_ParseTuple(args, "OO:convolver", &object1, &object2))
+ return nullptr;
+
+ ImpulseResponseP* filter = checkImpulseResponse(object1);
+ if(!filter)
+ return nullptr;
+
+ ThreadPoolP* threadPool = checkThreadPool(object2);
+ if(!threadPool)
+ return nullptr;
+
+ Sound* parent;
+ parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new ConvolverSound(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), *reinterpret_cast<std::shared_ptr<ImpulseResponse>*>(filter->impulseResponse), *reinterpret_cast<std::shared_ptr<ThreadPool>*>(threadPool->threadPool)));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+PyDoc_STRVAR(M_aud_Sound_binaural_doc,
+ "convolver()\n\n"
+ "Creates a binaural sound using another sound as source. The original sound must be mono\n\n"
+ ":arg hrtfs: An HRTF set.\n"
+ ":type hrtf: :class:`HRTF`\n"
+ ":arg source: An object representing the source position of the sound.\n"
+ ":type source: :class:`Source`\n"
+ ":arg threadPool: A thread pool used to parallelize convolution.\n"
+ ":type threadPool: :class:`ThreadPool`\n"
+ ":return: The created :class:`Sound` object.\n"
+ ":rtype: :class:`Sound`");
+
+static PyObject *
+Sound_binaural(Sound* self, PyObject* args)
+{
+ PyTypeObject* type = Py_TYPE(self);
+
+ PyObject* object1;
+ PyObject* object2;
+ PyObject* object3;
+
+ if(!PyArg_ParseTuple(args, "OOO:binaural", &object1, &object2, &object3))
+ return nullptr;
+
+ HRTFP* hrtfs = checkHRTF(object1);
+ if(!hrtfs)
+ return nullptr;
+
+ SourceP* source = checkSource(object2);
+ if(!hrtfs)
+ return nullptr;
+
+ ThreadPoolP* threadPool = checkThreadPool(object3);
+ if(!threadPool)
+ return nullptr;
+
+ Sound* parent;
+ parent = (Sound*)type->tp_alloc(type, 0);
+
+ if(parent != nullptr)
+ {
+ try
+ {
+ parent->sound = new std::shared_ptr<ISound>(new BinauralSound(*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound), *reinterpret_cast<std::shared_ptr<HRTF>*>(hrtfs->hrtf), *reinterpret_cast<std::shared_ptr<Source>*>(source->source), *reinterpret_cast<std::shared_ptr<ThreadPool>*>(threadPool->threadPool)));
+ }
+ catch(Exception& e)
+ {
+ Py_DECREF(parent);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)parent;
+}
+
+#endif
+
+static PyMethodDef Sound_methods[] = {
+ {"data", (PyCFunction)Sound_data, METH_NOARGS,
+ M_aud_Sound_data_doc
+ },
+ {"write", (PyCFunction)Sound_write, METH_VARARGS | METH_KEYWORDS,
+ M_aud_Sound_write_doc
+ },
+ {"buffer", (PyCFunction)Sound_buffer, METH_VARARGS | METH_CLASS,
+ M_aud_Sound_buffer_doc
+ },
+ {"cache", (PyCFunction)Sound_cache, METH_NOARGS,
+ M_aud_Sound_cache_doc
+ },
+ {"file", (PyCFunction)Sound_file, METH_VARARGS | METH_CLASS,
+ M_aud_Sound_file_doc
+ },
+ {"sawtooth", (PyCFunction)Sound_sawtooth, METH_VARARGS | METH_CLASS,
+ M_aud_Sound_sawtooth_doc
+ },
+ {"silence", (PyCFunction)Sound_silence, METH_NOARGS | METH_CLASS,
+ M_aud_Sound_silence_doc
+ },
+ {"sine", (PyCFunction)Sound_sine, METH_VARARGS | METH_CLASS,
+ M_aud_Sound_sine_doc
+ },
+ {"square", (PyCFunction)Sound_square, METH_VARARGS | METH_CLASS,
+ M_aud_Sound_square_doc
+ },
+ {"triangle", (PyCFunction)Sound_triangle, METH_VARARGS | METH_CLASS,
+ M_aud_Sound_triangle_doc
+ },
+ {"accumulate", (PyCFunction)Sound_accumulate, METH_VARARGS,
+ M_aud_Sound_accumulate_doc
+ },
+ {"ADSR", (PyCFunction)Sound_ADSR, METH_VARARGS,
+ M_aud_Sound_ADSR_doc
+ },
+ {"delay", (PyCFunction)Sound_delay, METH_VARARGS,
+ M_aud_Sound_delay_doc
+ },
+ {"envelope", (PyCFunction)Sound_envelope, METH_VARARGS,
+ M_aud_Sound_envelope_doc
+ },
+ {"fadein", (PyCFunction)Sound_fadein, METH_VARARGS,
+ M_aud_Sound_fadein_doc
+ },
+ {"fadeout", (PyCFunction)Sound_fadeout, METH_VARARGS,
+ M_aud_Sound_fadeout_doc
+ },
+ {"filter", (PyCFunction)Sound_filter, METH_VARARGS,
+ M_aud_Sound_filter_doc
+ },
+ {"highpass", (PyCFunction)Sound_highpass, METH_VARARGS,
+ M_aud_Sound_highpass_doc
+ },
+ {"limit", (PyCFunction)Sound_limit, METH_VARARGS,
+ M_aud_Sound_limit_doc
+ },
+ {"loop", (PyCFunction)Sound_loop, METH_VARARGS,
+ M_aud_Sound_loop_doc
+ },
+ {"lowpass", (PyCFunction)Sound_lowpass, METH_VARARGS,
+ M_aud_Sound_lowpass_doc
+ },
+ {"pitch", (PyCFunction)Sound_pitch, METH_VARARGS,
+ M_aud_Sound_pitch_doc
+ },
+ {"rechannel", (PyCFunction)Sound_rechannel, METH_VARARGS,
+ M_aud_Sound_rechannel_doc
+ },
+ {"resample", (PyCFunction)Sound_resample, METH_VARARGS,
+ M_aud_Sound_resample_doc
+ },
+ {"reverse", (PyCFunction)Sound_reverse, METH_NOARGS,
+ M_aud_Sound_reverse_doc
+ },
+ {"sum", (PyCFunction)Sound_sum, METH_NOARGS,
+ M_aud_Sound_sum_doc
+ },
+ {"threshold", (PyCFunction)Sound_threshold, METH_VARARGS,
+ M_aud_Sound_threshold_doc
+ },
+ {"volume", (PyCFunction)Sound_volume, METH_VARARGS,
+ M_aud_Sound_volume_doc
+ },
+ {"join", (PyCFunction)Sound_join, METH_O,
+ M_aud_Sound_join_doc
+ },
+ {"mix", (PyCFunction)Sound_mix, METH_O,
+ M_aud_Sound_mix_doc
+ },
+ { "pingpong", (PyCFunction)Sound_pingpong, METH_NOARGS,
+ M_aud_Sound_pingpong_doc
+ },
+ { "list", (PyCFunction)Sound_list, METH_VARARGS | METH_CLASS,
+ M_aud_Sound_list_doc
+ },
+ { "mutable", (PyCFunction)Sound_mutable, METH_NOARGS,
+ M_aud_Sound_mutable_doc
+ },
+ { "addSound", (PyCFunction)Sound_list_addSound, METH_O,
+ M_aud_Sound_list_addSound_doc
+ },
+#ifdef WITH_CONVOLUTION
+ { "convolver", (PyCFunction)Sound_convolver, METH_VARARGS,
+ M_aud_Sound_convolver_doc
+ },
+ { "binaural", (PyCFunction)Sound_binaural, METH_VARARGS,
+ M_aud_Sound_binaural_doc
+ },
+#endif
+ {nullptr} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Sound_specs_doc,
+ "The sample specification of the sound as a tuple with rate and channel count.");
+
+static PyObject *
+Sound_get_specs(Sound* self, void* nothing)
+{
+ try
+ {
+ Specs specs = (*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound))->createReader()->getSpecs();
+ return Py_BuildValue("(di)", specs.rate, specs.channels);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Sound_length_doc,
+ "The sample specification of the sound as a tuple with rate and channel count.");
+
+static PyObject *
+Sound_get_length(Sound* self, void* nothing)
+{
+ try
+ {
+ int length = (*reinterpret_cast<std::shared_ptr<ISound>*>(self->sound))->createReader()->getLength();
+ return Py_BuildValue("i", length);
+ }
+ catch(Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static PyGetSetDef Sound_properties[] = {
+ {(char*)"specs", (getter)Sound_get_specs, nullptr,
+ M_aud_Sound_specs_doc, nullptr },
+ {(char*)"length", (getter)Sound_get_length, nullptr,
+ M_aud_Sound_length_doc, nullptr },
+ {nullptr} /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Sound_doc,
+ "Sound objects are immutable and represent a sound that can be "
+ "played simultaneously multiple times. They are called factories "
+ "because they create reader objects internally that are used for "
+ "playback.");
+
+PyTypeObject SoundType = {
+ PyVarObject_HEAD_INIT(nullptr, 0)
+ "aud.Sound", /* tp_name */
+ sizeof(Sound), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Sound_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ M_aud_Sound_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ Sound_methods, /* tp_methods */
+ 0, /* tp_members */
+ Sound_properties, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Sound_new, /* tp_new */
+};
+
+AUD_API PyObject* Sound_empty()
+{
+ return SoundType.tp_alloc(&SoundType, 0);
+}
+
+AUD_API Sound* checkSound(PyObject* sound)
+{
+ if(!PyObject_TypeCheck(sound, &SoundType))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type Sound!");
+ return nullptr;
+ }
+
+ return (Sound*)sound;
+}
+
+
+bool initializeSound()
+{
+ import_array();
+
+ return PyType_Ready(&SoundType) >= 0;
+}
+
+
+void addSoundToModule(PyObject* module)
+{
+ Py_INCREF(&SoundType);
+ PyModule_AddObject(module, "Sound", (PyObject *)&SoundType);
+}
diff --git a/extern/audaspace/bindings/python/PySound.h b/extern/audaspace/bindings/python/PySound.h
new file mode 100644
index 00000000000..657bb2131e6
--- /dev/null
+++ b/extern/audaspace/bindings/python/PySound.h
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2009-2016 Jörg Müller
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+
+#pragma once
+
+#include <Python.h>
+#include "Audaspace.h"
+
+typedef void Reference_ISound;
+
+typedef struct {
+ PyObject_HEAD
+ Reference_ISound* sound;
+} Sound;
+
+extern AUD_API PyObject* Sound_empty();
+extern AUD_API Sound* checkSound(PyObject* sound);
+
+bool initializeSound();
+void addSoundToModule(PyObject* module);
diff --git a/extern/audaspace/bindings/python/PySource.cpp b/extern/audaspace/bindings/python/PySource.cpp
new file mode 100644
index 00000000000..a948cf46645
--- /dev/null
+++ b/extern/audaspace/bindings/python/PySource.cpp
@@ -0,0 +1,260 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#include "PySource.h"
+
+#include "Exception.h"
+#include "fx/Source.h"
+
+#include <memory>
+
+extern PyObject* AUDError;
+
+static PyObject *
+Source_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
+{
+ SourceP* self = (SourceP*)type->tp_alloc(type, 0);
+
+ if(self != nullptr)
+ {
+ float azimuth, elevation, distance;
+ if(!PyArg_ParseTuple(args, "fff:angles", &azimuth, &elevation, &distance))
+ return nullptr;
+
+ try
+ {
+ self->source = new std::shared_ptr<aud::Source>(new aud::Source(azimuth, elevation, distance));
+ }
+ catch(aud::Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+static void
+Source_dealloc(SourceP* self)
+{
+ if(self->source)
+ delete reinterpret_cast<std::shared_ptr<aud::Source>*>(self->source);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyMethodDef Source_methods[] = {
+ { nullptr } /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Source_azimuth_doc,
+ "The azimuth angle.");
+
+static int
+Source_set_azimuth(SourceP* self, PyObject* args, void* nothing)
+{
+ float azimuth;
+
+ if(!PyArg_Parse(args, "f:azimuth", &azimuth))
+ return -1;
+
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<aud::Source>*>(self->source))->setAzimuth(azimuth);
+ return 0;
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+static PyObject *
+Source_get_azimuth(SourceP* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::Source>*>(self->source))->getAzimuth());
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Source_elevation_doc,
+ "The elevation angle.");
+
+static int
+Source_set_elevation(SourceP* self, PyObject* args, void* nothing)
+{
+ float elevation;
+
+ if(!PyArg_Parse(args, "f:elevation", &elevation))
+ return -1;
+
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<aud::Source>*>(self->source))->setElevation(elevation);
+ return 0;
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+static PyObject *
+Source_get_elevation(SourceP* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::Source>*>(self->source))->getElevation());
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+PyDoc_STRVAR(M_aud_Source_distance_doc,
+ "The distance value. 0 is min, 1 is max.");
+
+static int
+Source_set_distance(SourceP* self, PyObject* args, void* nothing)
+{
+ float distance;
+
+ if(!PyArg_Parse(args, "f:distance", &distance))
+ return -1;
+
+ try
+ {
+ (*reinterpret_cast<std::shared_ptr<aud::Source>*>(self->source))->setDistance(distance);
+ return 0;
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ }
+
+ return -1;
+}
+
+static PyObject *
+Source_get_distance(SourceP* self, void* nothing)
+{
+ try
+ {
+ return Py_BuildValue("f", (*reinterpret_cast<std::shared_ptr<aud::Source>*>(self->source))->getDistance());
+ }
+ catch(aud::Exception& e)
+ {
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+}
+
+static PyGetSetDef Source_properties[] = {
+ { (char*)"azimuth", (getter)Source_get_azimuth, (setter)Source_set_azimuth,
+ M_aud_Source_azimuth_doc, nullptr },
+ { (char*)"elevation", (getter)Source_get_elevation, (setter)Source_set_elevation,
+ M_aud_Source_elevation_doc, nullptr },
+ { (char*)"distance", (getter)Source_get_distance, (setter)Source_set_distance,
+ M_aud_Source_distance_doc, nullptr },
+ { nullptr } /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_Source_doc,
+ "The source object represents the source position of a binaural sound.");
+
+PyTypeObject SourceType = {
+ PyVarObject_HEAD_INIT(nullptr, 0)
+ "aud.Source", /* tp_name */
+ sizeof(SourceP), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Source_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ M_aud_Source_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ Source_methods, /* tp_methods */
+ 0, /* tp_members */
+ Source_properties, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ Source_new, /* tp_new */
+};
+
+AUD_API PyObject* Source_empty()
+{
+ return SourceType.tp_alloc(&SourceType, 0);
+}
+
+
+AUD_API SourceP* checkSource(PyObject* source)
+{
+ if(!PyObject_TypeCheck(source, &SourceType))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type Source!");
+ return nullptr;
+ }
+
+ return (SourceP*)source;
+}
+
+
+bool initializeSource()
+{
+ return PyType_Ready(&SourceType) >= 0;
+}
+
+
+void addSourceToModule(PyObject* module)
+{
+ Py_INCREF(&SourceType);
+ PyModule_AddObject(module, "Source", (PyObject *)&SourceType);
+}
diff --git a/extern/audaspace/bindings/python/PySource.h b/extern/audaspace/bindings/python/PySource.h
new file mode 100644
index 00000000000..19960d80901
--- /dev/null
+++ b/extern/audaspace/bindings/python/PySource.h
@@ -0,0 +1,33 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#pragma once
+
+#include <Python.h>
+#include "Audaspace.h"
+
+typedef void Reference_Source;
+
+typedef struct {
+ PyObject_HEAD
+ Reference_Source* source;
+} SourceP;
+
+extern AUD_API PyObject* Source_empty();
+extern AUD_API SourceP* checkSource(PyObject* source);
+
+bool initializeSource();
+void addSourceToModule(PyObject* module); \ No newline at end of file
diff --git a/extern/audaspace/bindings/python/PyThreadPool.cpp b/extern/audaspace/bindings/python/PyThreadPool.cpp
new file mode 100644
index 00000000000..75811f08273
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyThreadPool.cpp
@@ -0,0 +1,134 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#include "PyThreadPool.h"
+
+#include "Exception.h"
+#include "util/ThreadPool.h"
+
+extern PyObject* AUDError;
+
+static PyObject *
+ThreadPool_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
+{
+ ThreadPoolP* self = (ThreadPoolP*)type->tp_alloc(type, 0);
+
+ if(self != nullptr)
+ {
+ unsigned int nThreads;
+ if(!PyArg_ParseTuple(args, "I:nThreads", &nThreads))
+ return nullptr;
+
+ try
+ {
+ self->threadPool = new std::shared_ptr<aud::ThreadPool>(new aud::ThreadPool(nThreads));
+ }
+ catch(aud::Exception& e)
+ {
+ Py_DECREF(self);
+ PyErr_SetString(AUDError, e.what());
+ return nullptr;
+ }
+ }
+
+ return (PyObject *)self;
+}
+
+static void
+ThreadPool_dealloc(ThreadPoolP* self)
+{
+ if(self->threadPool)
+ delete reinterpret_cast<std::shared_ptr<aud::ThreadPool>*>(self->threadPool);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyMethodDef ThreadPool_methods[] = {
+ { nullptr } /* Sentinel */
+};
+
+PyDoc_STRVAR(M_aud_ThreadPool_doc,
+ "A ThreadPool is used to parallelize convolution efficiently.");
+
+PyTypeObject ThreadPoolType = {
+ PyVarObject_HEAD_INIT(nullptr, 0)
+ "aud.ThreadPool", /* tp_name */
+ sizeof(ThreadPoolP), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)ThreadPool_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ M_aud_ThreadPool_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ ThreadPool_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ ThreadPool_new, /* tp_new */
+};
+
+AUD_API PyObject* ThreadPool_empty()
+{
+ return ThreadPoolType.tp_alloc(&ThreadPoolType, 0);
+}
+
+
+AUD_API ThreadPoolP* checkThreadPool(PyObject* threadPool)
+{
+ if(!PyObject_TypeCheck(threadPool, &ThreadPoolType))
+ {
+ PyErr_SetString(PyExc_TypeError, "Object is not of type ThreadPool!");
+ return nullptr;
+ }
+
+ return (ThreadPoolP*)threadPool;
+}
+
+
+bool initializeThreadPool()
+{
+ return PyType_Ready(&ThreadPoolType) >= 0;
+}
+
+
+void addThreadPoolToModule(PyObject* module)
+{
+ Py_INCREF(&ThreadPoolType);
+ PyModule_AddObject(module, "ThreadPool", (PyObject *)&ThreadPoolType);
+}
diff --git a/extern/audaspace/bindings/python/PyThreadPool.h b/extern/audaspace/bindings/python/PyThreadPool.h
new file mode 100644
index 00000000000..e38d905f52a
--- /dev/null
+++ b/extern/audaspace/bindings/python/PyThreadPool.h
@@ -0,0 +1,33 @@
+/*******************************************************************************
+* Copyright 2009-2015 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#pragma once
+
+#include <Python.h>
+#include "Audaspace.h"
+
+typedef void Reference_ThreadPool;
+
+typedef struct {
+ PyObject_HEAD
+ Reference_ThreadPool* threadPool;
+} ThreadPoolP;
+
+extern AUD_API PyObject* ThreadPool_empty();
+extern AUD_API ThreadPoolP* checkThreadPool(PyObject* ThreadPool);
+
+bool initializeThreadPool();
+void addThreadPoolToModule(PyObject* module); \ No newline at end of file
diff --git a/extern/audaspace/bindings/python/examples/binaural.py b/extern/audaspace/bindings/python/examples/binaural.py
new file mode 100644
index 00000000000..e7a2f6cf6d9
--- /dev/null
+++ b/extern/audaspace/bindings/python/examples/binaural.py
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+import aud, sys, time, multiprocessing
+device = aud.Device()
+hrtf = aud.HRTF().loadLeftHrtfSet(".wav", sys.argv[2])
+threadPool = aud.ThreadPool(multiprocessing.cpu_count())
+source = aud.Source(0, 0, 0)
+sound = aud.Sound.file(sys.argv[1]).rechannel(1).binaural(hrtf, source, threadPool)
+handle = device.play(sound)
+
+while handle.status:
+ source.azimuth += 1
+ print("Azimuth: " + str(source.azimuth))
+ time.sleep(0.1) \ No newline at end of file
diff --git a/extern/audaspace/bindings/python/examples/convolution.py b/extern/audaspace/bindings/python/examples/convolution.py
new file mode 100644
index 00000000000..4de25b0336a
--- /dev/null
+++ b/extern/audaspace/bindings/python/examples/convolution.py
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+import aud, sys, time, multiprocessing
+device = aud.Device()
+ir = aud.ImpulseResponse(aud.Sound.file(sys.argv[2]))
+threadPool = aud.ThreadPool(multiprocessing.cpu_count())
+sound = aud.Sound.file(sys.argv[1]).convolver(ir, threadPool)
+handle = device.play(sound)
+handle.volume = 0.1
+while handle.status:
+ time.sleep(0.1) \ No newline at end of file
diff --git a/extern/audaspace/bindings/python/examples/dynamicmusic.py b/extern/audaspace/bindings/python/examples/dynamicmusic.py
new file mode 100644
index 00000000000..348e2496c0a
--- /dev/null
+++ b/extern/audaspace/bindings/python/examples/dynamicmusic.py
@@ -0,0 +1,20 @@
+import aud, sys, time
+
+device=aud.Device()
+dMusic = aud.DynamicMusic(device)
+sound1 = aud.Sound.file(sys.argv[1])
+sound2 = aud.Sound.file(sys.argv[2])
+effect = aud.Sound.file(sys.argv[3])
+
+dMusic.addScene(sound1)
+dMusic.addScene(sound2)
+dMusic.addTransition(1,2,effect)
+
+dMusic.fadeTime=3
+dMusic.volume=0.5
+
+dMusic.scene=1
+time.sleep(5)
+dMusic.scene=2
+
+time.sleep(500) \ No newline at end of file
diff --git a/extern/audaspace/bindings/python/examples/playbackmanager.py b/extern/audaspace/bindings/python/examples/playbackmanager.py
new file mode 100644
index 00000000000..2aa1c283545
--- /dev/null
+++ b/extern/audaspace/bindings/python/examples/playbackmanager.py
@@ -0,0 +1,27 @@
+import aud, sys, time
+
+device=aud.Device()
+manager = aud.PlaybackManager(device)
+sound1 = aud.Sound.file(sys.argv[1])
+sound2 = aud.Sound.file(sys.argv[2])
+sound3 = aud.Sound.file(sys.argv[3])
+sound4 = aud.Sound.file(sys.argv[4])
+
+manager.play(sound1, 0)
+manager.play(sound2, 0)
+manager.play(sound3, 1)
+manager.play(sound4, 1)
+
+manager.setVolume(0.2, 0)
+time.sleep(5)
+manager.setVolume(0.0, 1)
+time.sleep(5)
+manager.pause(0)
+time.sleep(5)
+manager.setVolume(0.5, 1)
+manager.setVolume(1.0, 0)
+time.sleep(5)
+manager.stop(1)
+manager.resume(0)
+
+time.sleep(500) \ No newline at end of file
diff --git a/extern/audaspace/bindings/python/examples/player.py b/extern/audaspace/bindings/python/examples/player.py
new file mode 100644
index 00000000000..8acf4ac833f
--- /dev/null
+++ b/extern/audaspace/bindings/python/examples/player.py
@@ -0,0 +1,7 @@
+#!/usr/bin/python
+import aud, sys, time
+device = aud.Device()
+sound = aud.Sound.file(sys.argv[1])
+handle = device.play(sound)
+while handle.status:
+ time.sleep(0.1)
diff --git a/extern/audaspace/bindings/python/examples/randomSounds.py b/extern/audaspace/bindings/python/examples/randomSounds.py
new file mode 100644
index 00000000000..113b0921f09
--- /dev/null
+++ b/extern/audaspace/bindings/python/examples/randomSounds.py
@@ -0,0 +1,21 @@
+import aud, sys, time
+
+device=aud.Device()
+sound1 = aud.Sound.file(sys.argv[1])
+sound2 = aud.Sound.file(sys.argv[2])
+sound3 = aud.Sound.file(sys.argv[3])
+sound4 = aud.Sound.file(sys.argv[4])
+list=aud.Sound.list(True)
+
+list.addSound(sound1)
+list.addSound(sound2)
+list.addSound(sound3)
+list.addSound(sound4)
+mutable=aud.Sound.mutable(list)
+
+device.lock()
+handle=device.play(mutable)
+handle.loop_count=2
+device.unlock()
+
+time.sleep(500) \ No newline at end of file
diff --git a/extern/audaspace/bindings/python/examples/simple.py b/extern/audaspace/bindings/python/examples/simple.py
new file mode 100644
index 00000000000..7aa45b41042
--- /dev/null
+++ b/extern/audaspace/bindings/python/examples/simple.py
@@ -0,0 +1,7 @@
+#!/usr/bin/python
+import aud, time
+device = aud.Device()
+sine = aud.Sound.sine(440)
+square = sine.threshold()
+handle = device.play(square)
+time.sleep(3)
diff --git a/extern/audaspace/bindings/python/examples/siren.py b/extern/audaspace/bindings/python/examples/siren.py
new file mode 100644
index 00000000000..071279b162d
--- /dev/null
+++ b/extern/audaspace/bindings/python/examples/siren.py
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+import aud, math, time
+length = 0.5
+fadelength = 0.05
+
+device = aud.Device()
+high = aud.Sound.sine(880).limit(0, length).fadein(0, fadelength).fadeout(length - fadelength, length)
+low = aud.Sound.sine(700).limit(0, length).fadein(0, fadelength).fadeout(length - fadelength, length).volume(0.6)
+sound = high.join(low)
+handle = device.play(sound)
+handle.loop_count = -1
+
+start = time.time()
+
+while time.time() - start < 10:
+ angle = time.time() - start
+
+ handle.location = [math.sin(angle), 0, -math.cos(angle)]
+
diff --git a/extern/audaspace/bindings/python/examples/siren2.py b/extern/audaspace/bindings/python/examples/siren2.py
new file mode 100644
index 00000000000..35e1a600581
--- /dev/null
+++ b/extern/audaspace/bindings/python/examples/siren2.py
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+import aud, math, time
+length = 0.5
+fadelength = 0.05
+runtime = 10
+distance = 100
+velocity = 2 * distance / runtime
+
+device = aud.Device()
+high = aud.Sound.sine(880).limit(0, length).fadein(0, fadelength).fadeout(length - fadelength, length)
+low = aud.Sound.sine(700).limit(0, length).fadein(0, fadelength).fadeout(length - fadelength, length).volume(0.6)
+sound = high.join(low)
+handle = device.play(sound)
+handle.loop_count = -1
+
+handle.velocity = [velocity, 0, 0]
+
+start = time.time()
+
+while time.time() - start < runtime:
+ location = -distance + velocity * (time.time() - start)
+
+ handle.location = [location, 10, 0]
diff --git a/extern/audaspace/bindings/python/examples/tetris.py b/extern/audaspace/bindings/python/examples/tetris.py
new file mode 100644
index 00000000000..236a6fa59c1
--- /dev/null
+++ b/extern/audaspace/bindings/python/examples/tetris.py
@@ -0,0 +1,66 @@
+#!/usr/bin/python
+import aud, math, time
+
+def parseNotes(notes, bpm, basefreq, rate = 44100,
+ notechars = "XXXCXDXEFXGXAXHcXdXefXgXaXhp"):
+ pos = 0
+ fadelength = 60/bpm/10
+ halfchars = "#b"
+ durationchars = "2345678"
+ sound = None
+
+ while pos < len(notes):
+ char = notes[pos]
+ mod = None
+ dur = 1
+ pos += 1
+ while pos < len(notes) and notes[pos] not in notechars:
+ if notes[pos] in halfchars:
+ mod = notes[pos]
+ elif notes[pos] in durationchars:
+ dur = notes[pos]
+ pos += 1
+
+ freq = notechars.find(char)
+ if mod == '#':
+ freq += 1
+ elif mod == 'b':
+ freq -= 1
+
+ freq = math.pow(2, freq/12)*basefreq
+ length = float(dur)*60/bpm
+
+ snd = aud.Sound.square(freq, rate)
+ if char == 'p':
+ snd = snd.volume(0)
+ snd = snd.limit(0, length)
+ snd = snd.fadein(0, fadelength)
+ snd = snd.fadeout(length - fadelength, fadelength)
+
+ if sound:
+ sound = sound.join(snd)
+ else:
+ sound = snd
+ return sound
+
+def tetris(bpm = 300, freq = 220, rate = 44100):
+ notes = "e2Hcd2cH A2Ace2dc H3cd2e2 c2A2A4 pd2fa2gf e3ce2dc H2Hcd2e2 c2A2A2p2"
+ s11 = parseNotes(notes, bpm, freq, rate)
+
+ notes = "e4c4 d4H4 c4A4 G#4p4 e4c4 d4H4 A2c2a4 g#4p4"
+ s12 = parseNotes(notes, bpm, freq, rate)
+
+ notes = "EeEeEeEe AaAaAaAa AbabAbabAbabAbab AaAaAAHC DdDdDdDd CcCcCcCc HhHhHhHh AaAaA2p2"
+ s21 = parseNotes(notes, bpm, freq, rate, notechars = "AXHCXDXEFXGXaXhcXdXefXgXp")
+
+ notes = "aeaeaeae g#dg#dg#dg#d aeaeaeae g#dg#dg#2p2 aeaeaeae g#dg#dg#dg#d aeaeaeae g#dg#dg#2p2"
+ s22 = parseNotes(notes, bpm, freq/2, rate)
+
+ return s11.join(s12).join(s11).volume(0.5).mix(s21.join(s22).join(s21).volume(0.3))
+
+if __name__ == "__main__":
+ dev = aud.Device()
+ handle = dev.play(tetris(300, 220, dev.rate))
+ while handle.status:
+ time.sleep(0.1)
+
diff --git a/extern/audaspace/bindings/python/examples/tetris2.py b/extern/audaspace/bindings/python/examples/tetris2.py
new file mode 100644
index 00000000000..08708581af6
--- /dev/null
+++ b/extern/audaspace/bindings/python/examples/tetris2.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+import aud, math, time
+
+def parseNotes(notes, bpm, basefreq, rate = 44100,
+ notechars = "XXXCXDXEFXGXAXHcXdXefXgXaXhp"):
+ pos = 0
+ fadelength = 60/bpm/10
+ halfchars = "#b"
+ durationchars = "2345678"
+ position = 0
+ sequence = aud.Sequence()
+
+ while pos < len(notes):
+ char = notes[pos]
+ mod = None
+ dur = 1
+ pos += 1
+ while pos < len(notes) and notes[pos] not in notechars:
+ if notes[pos] in halfchars:
+ mod = notes[pos]
+ elif notes[pos] in durationchars:
+ dur = notes[pos]
+ pos += 1
+
+ freq = notechars.find(char)
+ if mod == '#':
+ freq += 1
+ elif mod == 'b':
+ freq -= 1
+
+ freq = math.pow(2, freq/12)*basefreq
+ length = float(dur)*60/bpm
+
+ note = aud.Sound.square(freq, rate).fadein(0, fadelength).fadeout(length - fadelength, fadelength)
+
+ entry = sequence.add(note, position, position + length, 0)
+ if char == 'p':
+ entry.muted = True
+
+ position += length
+
+ return sequence.limit(0, position)
+
+def tetris(bpm = 300, freq = 220, rate = 44100):
+ notes = "e2Hcd2cH A2Ace2dc H3cd2e2 c2A2A4 pd2fa2gf e3ce2dc H2Hcd2e2 c2A2A2p2"
+ s11 = parseNotes(notes, bpm, freq, rate)
+
+ notes = "e4c4 d4H4 c4A4 G#4p4 e4c4 d4H4 A2c2a4 g#4p4"
+ s12 = parseNotes(notes, bpm, freq, rate)
+
+ notes = "EeEeEeEe AaAaAaAa AbabAbabAbabAbab AaAaAAHC DdDdDdDd CcCcCcCc HhHhHhHh AaAaA2p2"
+ s21 = parseNotes(notes, bpm, freq, rate, notechars = "AXHCXDXEFXGXaXhcXdXefXgXp")
+
+ notes = "aeaeaeae g#dg#dg#dg#d aeaeaeae g#dg#dg#2p2 aeaeaeae g#dg#dg#dg#d aeaeaeae g#dg#dg#2p2"
+ s22 = parseNotes(notes, bpm, freq/2, rate)
+
+ return s11.join(s12).join(s11).volume(0.5).mix(s21.join(s22).join(s21).volume(0.3))
+
+if __name__ == "__main__":
+ dev = aud.Device()
+ handle = dev.play(tetris(300, 220, dev.rate))
+ while handle.status:
+ time.sleep(0.1)
+
diff --git a/extern/audaspace/bindings/python/examples/tetris3.py b/extern/audaspace/bindings/python/examples/tetris3.py
new file mode 100644
index 00000000000..aa66d5457d3
--- /dev/null
+++ b/extern/audaspace/bindings/python/examples/tetris3.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+import aud, math, time
+
+def parseNotes(notes, bpm, basefreq, rate = 44100,
+ notechars = "XXXCXDXEFXGXAXHcXdXefXgXaXhp"):
+ pos = 0
+ fadelength = 60/bpm/10
+ halfchars = "#b"
+ durationchars = "2345678"
+ position = 0
+ sequence = aud.Sequence()
+
+ while pos < len(notes):
+ char = notes[pos]
+ mod = None
+ dur = 1
+ pos += 1
+ while pos < len(notes) and notes[pos] not in notechars:
+ if notes[pos] in halfchars:
+ mod = notes[pos]
+ elif notes[pos] in durationchars:
+ dur = notes[pos]
+ pos += 1
+
+ freq = notechars.find(char)
+ if mod == '#':
+ freq += 1
+ elif mod == 'b':
+ freq -= 1
+
+ freq = math.pow(2, freq/12)*basefreq
+ length = float(dur)*60/bpm
+
+ if char != 'p':
+ note = aud.Sound.square(freq, rate).fadein(0, fadelength).fadeout(length - fadelength, fadelength)
+
+ sequence.add(note, position, position + length, 0)
+
+ position += length
+
+ return sequence.limit(0, position)
+
+def tetris(bpm = 300, freq = 220, rate = 44100):
+ notes = "e2Hcd2cH A2Ace2dc H3cd2e2 c2A2A4 pd2fa2gf e3ce2dc H2Hcd2e2 c2A2A2p2"
+ s11 = parseNotes(notes, bpm, freq, rate)
+
+ notes = "e4c4 d4H4 c4A4 G#4p4 e4c4 d4H4 A2c2a4 g#4p4"
+ s12 = parseNotes(notes, bpm, freq, rate)
+
+ notes = "EeEeEeEe AaAaAaAa AbabAbabAbabAbab AaAaAAHC DdDdDdDd CcCcCcCc HhHhHhHh AaAaA2p2"
+ s21 = parseNotes(notes, bpm, freq, rate, notechars = "AXHCXDXEFXGXaXhcXdXefXgXp")
+
+ notes = "aeaeaeae g#dg#dg#dg#d aeaeaeae g#dg#dg#2p2 aeaeaeae g#dg#dg#dg#d aeaeaeae g#dg#dg#2p2"
+ s22 = parseNotes(notes, bpm, freq/2, rate)
+
+ return s11.join(s12).join(s11).volume(0.5).mix(s21.join(s22).join(s21).volume(0.3))
+
+if __name__ == "__main__":
+ dev = aud.Device()
+ handle = dev.play(tetris(300, 220, dev.rate))
+ while handle.status:
+ time.sleep(0.1)
+
diff --git a/extern/audaspace/bindings/python/setup.py.in b/extern/audaspace/bindings/python/setup.py.in
new file mode 100644
index 00000000000..add1a2d1475
--- /dev/null
+++ b/extern/audaspace/bindings/python/setup.py.in
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+
+import sys
+import os
+import codecs
+import numpy
+
+from distutils.core import setup, Extension
+
+if len(sys.argv) > 2 and sys.argv[1] == '--build-docs':
+ import subprocess
+ from distutils.core import Distribution
+ from distutils.command.build import build
+
+ dist = Distribution()
+ cmd = build(dist)
+ cmd.finalize_options()
+ #print(cmd.build_platlib)
+
+ os.environ['PYTHONPATH'] = os.path.join(os.getcwd(), cmd.build_platlib)
+ os.environ['LD_LIBRARY_PATH'] = os.getcwd()
+
+ ret = subprocess.call(sys.argv[2:])
+ sys.exit(ret)
+
+
+# the following line is not working due to https://bugs.python.org/issue9023
+#source_directory = os.path.relpath('@PYTHON_SOURCE_DIRECTORY@')
+source_directory = '@PYTHON_SOURCE_DIRECTORY@'
+
+extra_args = []
+
+if sys.platform == 'win32':
+ extra_args.append('/EHsc')
+ extra_args.append('/DAUD_BUILD_SHARED_LIBRARY')
+else:
+ extra_args.append('-std=c++11')
+
+audaspace = Extension(
+ 'aud',
+ include_dirs = ['@CMAKE_CURRENT_BINARY_DIR@', '@FFTW_INCLUDE_DIR@', os.path.join(source_directory, '../../include'), numpy.get_include()],
+ libraries = ['audaspace'],
+ library_dirs = ['.', 'Release', 'Debug'],
+ language = 'c++',
+ extra_compile_args = extra_args,
+ sources = [os.path.join(source_directory, file) for file in ['PyAPI.cpp', 'PyDevice.cpp', 'PyHandle.cpp', 'PySound.cpp', 'PySequenceEntry.cpp', 'PySequence.cpp', 'PyPlaybackManager.cpp', 'PyDynamicMusic.cpp', 'PyThreadPool.cpp', 'PySource.cpp'] + (['PyImpulseResponse.cpp', 'PyHRTF.cpp'] if '@WITH_FFTW@' == 'ON' else [])]
+)
+
+setup(
+ name = 'audaspace',
+ version = '@AUDASPACE_LONG_VERSION@',
+ description = 'Audaspace is a high level audio library.',
+ author = 'Jörg Müller',
+ author_email = 'nexyon@gmail.com',
+ url = 'https://github.com/audaspace/audaspace',
+ license = 'Apache License 2.0',
+ long_description = codecs.open(os.path.join(source_directory, '../../README.md'), 'r', 'utf-8').read(),
+ ext_modules = [audaspace],
+ headers = [os.path.join(source_directory, file) for file in ['PyAPI.h', 'PyDevice.h', 'PyHandle.h', 'PySound.h', 'PySequenceEntry.h', 'PySequence.h', 'PyPlaybackManager.h', 'PyDynamicMusic.h', 'PyThreadPool.h', 'PySource.h'] + (['PyImpulseResponse.h', 'PyHRTF.h'] if '@WITH_FFTW@' == 'ON' else [])] + ['Audaspace.h']
+)
+