Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,249 @@
/*******************************************************************************
* 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 "PyAnimateableProperty.h"
#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
#ifdef WITH_RUBBERBAND
#include "fx/TimeStretchPitchScale.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;
if(!initializeAnimateableProperty())
return nullptr;
#ifdef WITH_CONVOLUTION
if(!initializeImpulseResponse())
return nullptr;
if(!initializeHRTF())
return nullptr;
#endif
module = PyModule_Create(&audmodule);
if(module == nullptr)
return nullptr;
addAnimateablePropertyToModule(module);
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);
PY_MODULE_ADD_CONSTANT(module, AP_TIME_STRETCH);
PY_MODULE_ADD_CONSTANT(module, AP_PITCH_SCALE);
// 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);
PY_MODULE_ADD_CONSTANT(module, CONTAINER_AAC);
// 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);
#ifdef WITH_RUBBERBAND
// stretcher quality
PyModule_AddIntConstant(module, "STRETCHER_QUALITY_HIGH", static_cast<int>(StretcherQuality::HIGH));
PyModule_AddIntConstant(module, "STRETCHER_QUALITY_FAST", static_cast<int>(StretcherQuality::FAST));
PyModule_AddIntConstant(module, "STRETCHER_QUALITY_CONSISTENT", static_cast<int>(StretcherQuality::CONSISTENT));
#endif
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));
}

View File

@@ -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

View File

@@ -0,0 +1,404 @@
/*******************************************************************************
* Copyright 2009-2025 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 "PyAnimateableProperty.h"
#include "Exception.h"
#include "sequence/AnimateableProperty.h"
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <memory>
#include <numpy/ndarrayobject.h>
using namespace aud;
extern PyObject* AUDError;
static PyObject* AnimateableProperty_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
{
AnimateablePropertyP* self = (AnimateablePropertyP*) type->tp_alloc(type, 0);
int count;
float value;
if(self != nullptr)
{
if(!PyArg_ParseTuple(args, "i|f:animateableProperty", &count, &value))
return nullptr;
try
{
if(PyTuple_Size(args) == 1)
{
self->animateableProperty = new std::shared_ptr<aud::AnimateableProperty>(new aud::AnimateableProperty(count));
}
else
{
self->animateableProperty = new std::shared_ptr<aud::AnimateableProperty>(new aud::AnimateableProperty(count, value));
}
}
catch(aud::Exception& e)
{
Py_DECREF(self);
PyErr_SetString(AUDError, e.what());
return nullptr;
}
}
return (PyObject*) self;
}
static void AnimateableProperty_dealloc(AnimateablePropertyP* self)
{
if(self->animateableProperty)
delete reinterpret_cast<std::shared_ptr<aud::AnimateableProperty>*>(self->animateableProperty);
Py_TYPE(self)->tp_free((PyObject*) self);
}
static PyObject* AnimateableProperty_read(AnimateablePropertyP* self, PyObject* args)
{
float position;
if(!PyArg_ParseTuple(args, "f", &position))
return nullptr;
int count = (*reinterpret_cast<std::shared_ptr<aud::AnimateableProperty>*>(self->animateableProperty))->getCount();
npy_intp dims[1] = {count};
PyObject* np_array = PyArray_SimpleNew(1, dims, NPY_FLOAT32);
if(!np_array)
return nullptr;
float* out = static_cast<float*>(PyArray_DATA(reinterpret_cast<PyArrayObject*>(np_array)));
try
{
(*reinterpret_cast<std::shared_ptr<aud::AnimateableProperty>*>(self->animateableProperty))->read(position, out);
return np_array;
}
catch(aud::Exception& e)
{
Py_DECREF(np_array);
PyErr_SetString(AUDError, e.what());
return nullptr;
}
}
PyDoc_STRVAR(M_aud_AnimateableProperty_read_doc, ".. method:: read(position)\n\n"
" Reads the properties value at the given position.\n\n"
" :param position: The position in the animation in frames.\n"
" :type position: float\n"
" :return: A numpy array of values representing the properties value.\n"
" :rtype: :class:`numpy.ndarray`\n");
static PyObject* AnimateableProperty_readSingle(AnimateablePropertyP* self, PyObject* args)
{
float position;
if(!PyArg_ParseTuple(args, "f", &position))
return nullptr;
try
{
float value = (*reinterpret_cast<std::shared_ptr<aud::AnimateableProperty>*>(self->animateableProperty))->readSingle(position);
return Py_BuildValue("f", value);
}
catch(aud::Exception& e)
{
PyErr_SetString(AUDError, e.what());
return nullptr;
}
}
PyDoc_STRVAR(M_aud_AnimateableProperty_readSingle_doc, ".. method:: readSingle(position)\n\n"
" Reads the properties value at the given position, assuming there is exactly one value.\n\n"
" :param position: The position in the animation in frames.\n"
" :type position: float\n"
" :return: The value at that position.\n"
" :rtype: float\n\n");
static PyObject* AnimateableProperty_write(AnimateablePropertyP* self, PyObject* args)
{
PyObject* array_obj;
int position = -1;
if(!PyArg_ParseTuple(args, "O|i", &array_obj, &position))
return nullptr;
PyArrayObject* np_array = reinterpret_cast<PyArrayObject*>(PyArray_FROM_OTF(array_obj, NPY_FLOAT32, NPY_ARRAY_IN_ARRAY | NPY_ARRAY_FORCECAST));
if(!np_array)
{
PyErr_SetString(PyExc_TypeError, "data must be a numpy array of dtype float32");
return nullptr;
}
auto& prop = *reinterpret_cast<std::shared_ptr<aud::AnimateableProperty>*>(self->animateableProperty);
int prop_count = prop->getCount();
npy_intp size = PyArray_SIZE(np_array);
int ndim = PyArray_NDIM(np_array);
bool valid_shape = false;
// For 1D arrays, the total number of elements must be a multiple of the property count
if(ndim == 1)
{
valid_shape = (size % prop_count == 0);
}
// For 2D arrays, the number of elements in the second dimension must be the property count
else if(ndim == 2)
{
npy_intp* shape = PyArray_DIMS(np_array);
valid_shape = (shape[1] == prop_count);
}
if(!valid_shape)
{
PyErr_SetString(PyExc_ValueError, "array shape is invalid: must be 1D with length multiple of property count or 2D with the last dimension equal to property count");
Py_DECREF(np_array);
return nullptr;
}
int count = static_cast<int>(size / prop_count);
if(count < 1)
{
PyErr_SetString(PyExc_ValueError, "input array must have at least 1 element");
Py_DECREF(np_array);
return nullptr;
}
float* data_ptr = reinterpret_cast<float*>(PyArray_DATA(np_array));
try
{
if(position == -1)
{
if(count != 1)
{
PyErr_SetString(PyExc_ValueError, "input array must have exactly 1 element when position is not specified");
Py_DECREF(np_array);
return nullptr;
}
prop->write(data_ptr);
}
else
{
prop->write(data_ptr, position, count);
}
}
catch(aud::Exception& e)
{
PyErr_SetString(AUDError, e.what());
}
Py_DECREF(np_array);
Py_RETURN_NONE;
}
PyDoc_STRVAR(M_aud_AnimateableProperty_write_doc, ".. method:: write(data[, position])\n\n"
" Writes the properties value.\n\n"
" If `position` is also given, the property is marked animated and\n"
" the values are written starting at `position`.\n\n"
" :param data: numpy array of float32 values.\n"
" :type data: numpy.ndarray\n"
" :param position: The starting position in frames.\n"
" :type position: int\n\n");
static PyObject* AnimateableProperty_writeConstantRange(AnimateablePropertyP* self, PyObject* args)
{
PyObject* array_obj;
int position_start;
int position_end;
if(!PyArg_ParseTuple(args, "Oii", &array_obj, &position_start, &position_end))
return nullptr;
PyArrayObject* np_array = reinterpret_cast<PyArrayObject*>(PyArray_FROM_OTF(array_obj, NPY_FLOAT32, NPY_ARRAY_IN_ARRAY | NPY_ARRAY_FORCECAST));
if(!np_array)
{
PyErr_SetString(PyExc_TypeError, "data must be a numpy array of dtype float32");
return nullptr;
}
int ndim = PyArray_NDIM(np_array);
if(ndim != 1)
{
PyErr_SetString(PyExc_ValueError, "data must be a 1D numpy array");
Py_DECREF(np_array);
return nullptr;
}
float* data_ptr = reinterpret_cast<float*>(PyArray_DATA(np_array));
auto& prop = *reinterpret_cast<std::shared_ptr<aud::AnimateableProperty>*>(self->animateableProperty);
int prop_count = prop->getCount();
npy_intp size = PyArray_SIZE(np_array);
if(size != prop_count)
{
PyErr_Format(PyExc_ValueError, "input array length (%lld) does not match property count (%d)", size, prop_count);
Py_DECREF(np_array);
return nullptr;
}
try
{
prop->writeConstantRange(data_ptr, position_start, position_end);
}
catch(aud::Exception& e)
{
PyErr_SetString(AUDError, e.what());
return nullptr;
}
Py_DECREF(np_array);
Py_RETURN_NONE;
}
PyDoc_STRVAR(M_aud_AnimateableProperty_writeConstantRange_doc, ".. method:: writeConstantRange(data, position_start, position_end)\n\n"
" Fills the properties frame range with a constant value and marks it animated.\n\n"
" :param data: numpy array of float values representing the constant value.\n"
" :type data: numpy.ndarray\n"
" :param position_start: The start position in frames.\n"
" :type position_start: int\n"
" :param position_end: The end position in frames.\n"
" :type position_end: int\n\n");
static PyMethodDef AnimateableProperty_methods[] = {
{(char*) "read", (PyCFunction) AnimateableProperty_read, METH_VARARGS, M_aud_AnimateableProperty_read_doc},
{(char*) "readSingle", (PyCFunction) AnimateableProperty_readSingle, METH_VARARGS, M_aud_AnimateableProperty_readSingle_doc},
{(char*) "write", (PyCFunction) AnimateableProperty_write, METH_VARARGS, M_aud_AnimateableProperty_write_doc},
{(char*) "writeConstantRange", (PyCFunction) AnimateableProperty_writeConstantRange, METH_VARARGS, M_aud_AnimateableProperty_writeConstantRange_doc},
{nullptr} /* Sentinel */
};
static PyObject* AnimateableProperty_get_count(AnimateablePropertyP* self, void* nothing)
{
try
{
int count = (*reinterpret_cast<std::shared_ptr<aud::AnimateableProperty>*>(self->animateableProperty))->getCount();
return Py_BuildValue("i", count);
}
catch(aud::Exception& e)
{
PyErr_SetString(AUDError, e.what());
return nullptr;
}
}
PyDoc_STRVAR(M_aud_AnimateableProperty_count_doc, "The count of floats for a property.");
static PyObject* AnimateableProperty_get_animated(AnimateablePropertyP* self, void* nothing)
{
try
{
bool animated = (*reinterpret_cast<std::shared_ptr<aud::AnimateableProperty>*>(self->animateableProperty))->isAnimated();
return PyBool_FromLong(animated);
}
catch(aud::Exception& e)
{
PyErr_SetString(AUDError, e.what());
return nullptr;
}
}
PyDoc_STRVAR(M_aud_AnimateableProperty_animated_doc, "Whether the property is animated.");
static PyGetSetDef AnimateableProperty_properties[] = {
{(char*) "count", (getter) AnimateableProperty_get_count, nullptr, M_aud_AnimateableProperty_count_doc, nullptr},
{(char*) "animated", (getter) AnimateableProperty_get_animated, nullptr, M_aud_AnimateableProperty_animated_doc, nullptr},
{nullptr} /* Sentinel */
};
PyDoc_STRVAR(M_aud_AnimateableProperty_doc,
".. class:: AnimateableProperty(count, value=0.0, /)\n\n"
" An AnimateableProperty object stores an array of float values for animating sound properties (e.g. pan, volume, pitch-scale).\n\n"
" :arg count: The number of float values to store per frame.\n"
" :type count: int\n"
" :arg value: The initial value for all elements.\n"
" :type value: float\n");
// Note that AnimateablePropertyType name is already taken
PyTypeObject AnimateablePropertyPyType = {
PyVarObject_HEAD_INIT(nullptr, 0) "aud.AnimateableProperty", /* tp_name */
sizeof(AnimateablePropertyP), /* tp_basicsize */
0, /* tp_itemsize */
(destructor) AnimateableProperty_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_AnimateableProperty_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
AnimateableProperty_methods, /* tp_methods */
0, /* tp_members */
AnimateableProperty_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 */
AnimateableProperty_new, /* tp_new */
};
AUD_API PyObject* AnimateableProperty_empty()
{
return AnimateablePropertyPyType.tp_alloc(&AnimateablePropertyPyType, 0);
}
AUD_API AnimateablePropertyP* checkAnimateableProperty(PyObject* animateableProperty)
{
if(!PyObject_TypeCheck(animateableProperty, &AnimateablePropertyPyType))
{
PyErr_SetString(PyExc_TypeError, "Object is not of type AnimateableProperty!");
return nullptr;
}
return (AnimateablePropertyP*) animateableProperty;
}
bool initializeAnimateableProperty()
{
import_array1(false);
return PyType_Ready(&AnimateablePropertyPyType) >= 0;
}
void addAnimateablePropertyToModule(PyObject* module)
{
Py_INCREF(&AnimateablePropertyPyType);
PyModule_AddObject(module, "AnimateableProperty", (PyObject*) &AnimateablePropertyPyType);
}

View File

@@ -0,0 +1,34 @@
/*******************************************************************************
* Copyright 2009-2025 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_AnimateableProperty;
typedef struct
{
PyObject_HEAD Reference_AnimateableProperty* animateableProperty;
} AnimateablePropertyP;
extern AUD_API PyObject* AnimateableProperty_empty();
extern AUD_API AnimateablePropertyP* checkAnimateableProperty(PyObject* animateableProperty);
bool initializeAnimateableProperty();
void addAnimateablePropertyToModule(PyObject* module);

View File

@@ -0,0 +1,800 @@
/*******************************************************************************
* 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,
".. method:: lock()\n\n"
" Locks the device so that it's guaranteed, that no samples are\n"
" read from the streams until :meth:`unlock` is called.\n"
" This is useful if you want to do start/stop/pause/resume some\n"
" sounds at the same time.\n\n"
" .. note::\n\n"
" The device has to be unlocked as often as locked to be\n"
" able to continue playback.\n\n"
" .. warning::\n\n"
" Make sure the time between locking and unlocking is\n"
" 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,
".. method:: 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\n"
" 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,
".. method:: 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,
".. method:: unlock()\n\n"
" Unlocks the device after a lock call, see :meth:`lock` for\n"
" 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:: `OpenAL Documentation <https://www.openal.org/documentation/>`__");
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,
".. class:: Device(type='', rate=48000.0, channels=2, format=36, buffer_size=1024, name='')\n\n"
" Device objects represent an audio output backend like OpenAL or "
"SDL, but might also represent a file output or RAM buffer "
"output.\n\n"
" :arg type: The device type. An empty string means the default device.\n"
" :type type: string\n"
" :arg rate: The sample rate in Hz.\n"
" :type rate: double\n"
" :arg channels: The number of channels.\n"
" :type channels: int\n"
" :arg format: The sample format.\n"
" :type format: int\n"
" :arg buffer_size: The size of the audio buffer in samples.\n"
" :type buffer_size: int\n"
" :arg name: The name of the device.\n"
" :type name: string\n");
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);
}

View File

@@ -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);

View File

@@ -0,0 +1,470 @@
/*******************************************************************************
* 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,
".. method:: 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,
".. method:: 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 otherwise.\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,
".. method:: 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,
".. method:: 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,
".. method:: 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)
{
double position;
if(!PyArg_Parse(args, "d: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("d", (*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,
".. class:: DynamicMusic(device, /)\n\n"
" 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.\n\n"
" :arg device: The device that will be used to play sounds.\n"
" :type device: :class:`Device`\n");
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);
}

View File

@@ -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);

View File

@@ -0,0 +1,248 @@
/*******************************************************************************
* 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,
".. method:: 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,
".. method:: 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,
".. method:: loadRightHrtfSet(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,
".. class:: HRTF()\n\n"
" An HRTF object represents a set of head related transfer functions as impulse responses. It's used for binaural sound.\n");
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);
}

View File

@@ -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);

File diff suppressed because it is too large Load Diff

View File

@@ -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);

View File

@@ -0,0 +1,140 @@
/*******************************************************************************
* 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,
".. class:: ImpulseResponse(sound, /)\n\n"
" An ImpulseResponse object represents a filter with which to convolve a sound.\n\n"
" :arg sound: The sound to use as the impulse response.\n"
" :type sound: :class:`Sound`\n");
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);
}

View File

@@ -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);

View File

@@ -0,0 +1,393 @@
/*******************************************************************************
* 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,
".. method:: play(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,\n"
" 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,
".. method:: 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,
".. method:: 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,
".. method:: 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,
".. method:: 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 category.\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,
".. method:: 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,
".. method:: 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,
".. method:: 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,
".. class:: PlaybackManager(device, /)\n\n"
" A PlaybackManager object allows to easily control groups of sounds organized in categories.\n\n"
" :arg device: The device that will be used to play sounds.\n"
" :type device: :class:`Device`\n");
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);
}

View File

@@ -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);

View File

@@ -0,0 +1,664 @@
/*******************************************************************************
* 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,
".. method:: add()\n\n"
" Adds a new entry to the sequence.\n\n"
" :arg sound: The sound this entry should play.\n"
" :type sound: :class:`Sound`\n"
" :arg begin: The start time.\n"
" :type begin: double\n"
" :arg end: The end time or a negative value if determined by the sound.\n"
" :type end: double\n"
" :arg skip: How much seconds should be skipped at the beginning.\n"
" :type skip: double\n"
" :return: The entry added.\n"
" :rtype: :class:`SequenceEntry`");
static PyObject *
Sequence_add(Sequence* self, PyObject* args, PyObject* kwds)
{
PyObject* object;
double begin;
double end = -1.0;
double skip = 0.0;
static const char* kwlist[] = {"sound", "begin", "end", "skip", nullptr};
if(!PyArg_ParseTupleAndKeywords(args, kwds, "Od|dd: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,
".. method:: remove()\n\n"
" Removes an entry from the sequence.\n\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,
".. method:: 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.reserve(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:: `OpenAL Documentation <https://www.openal.org/documentation/>`__");
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,
".. class:: Sequence(channels=2, rate=48000.0, fps=30.0, muted=False)\n\n"
" This sound represents sequenced entries to play a sound sequence.\n\n"
" :arg channels: The number of channels.\n"
" :type channels: int\n"
" :arg rate: The sample rate in Hz.\n"
" :type rate: double\n"
" :arg fps: The frames per second of the sequence.\n"
" :type fps: float\n"
" :arg muted: Whether the sequence is muted.\n"
" :type muted: bool\n");
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);
}

View File

@@ -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);

View File

@@ -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,
".. method:: move()\n\n"
" Moves the entry.\n\n"
" :arg begin: The new start time.\n"
" :type begin: double\n"
" :arg end: The new end time or a negative value if unknown.\n"
" :type end: double\n"
" :arg skip: How many seconds to skip at the beginning.\n"
" :type skip: double\n");
static PyObject *
SequenceEntry_move(SequenceEntry* self, PyObject* args)
{
double begin, end, skip;
if(!PyArg_ParseTuple(args, "ddd: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,
".. method:: 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.reserve(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);
}

View File

@@ -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);

File diff suppressed because it is too large Load Diff

View File

@@ -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);

View File

@@ -0,0 +1,267 @@
/*******************************************************************************
* 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,
".. class:: Source(azimuth, elevation, distance, /)\n\n"
" The source object represents the source position of a binaural sound.\n\n"
" :arg azimuth: The azimuth angle in degrees.\n"
" :type azimuth: float\n"
" :arg elevation: The elevation angle in degrees.\n"
" :type elevation: float\n"
" :arg distance: The distance of the source.\n"
" :type distance: float\n");
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);
}

View File

@@ -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);

View File

@@ -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 "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,
".. class:: ThreadPool(nThreads, /)\n\n"
" A ThreadPool is used to parallelize convolution efficiently.\n\n"
" :arg nThreads: The number of threads in the pool.\n"
" :type nThreads: int\n");
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);
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)]

View File

@@ -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]

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
import sys
import os
import codecs
import numpy
from setuptools import setup, Extension
if len(sys.argv) > 2 and sys.argv[1] == '--build-docs':
import subprocess
from setuptools import Distribution
from setuptools.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++17')
macros = []
if '@WITH_FFTW@' == 'ON':
macros.append(('WITH_CONVOLUTION', None))
if '@WITH_RUBBERBAND@' == 'ON':
macros.append(('WITH_RUBBERBAND', None))
audaspace = Extension(
'aud',
include_dirs = ['@CMAKE_CURRENT_BINARY_DIR@', os.path.join(source_directory, '../../include'), numpy.get_include()] + (['@FFTW_INCLUDE_DIR@'] if '@WITH_FFTW@' == 'ON' else []),
libraries = ['audaspace'],
library_dirs = ['.', 'Release', 'Debug'],
language = 'c++',
extra_compile_args = extra_args,
define_macros = macros,
sources = [os.path.join(source_directory, file) for file in ['PyAnimateableProperty.cpp', '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 ['PyAnimateableProperty.h', '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']
)