Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package audaspace for openSUSE:Factory checked in at 2026-03-23 17:11:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/audaspace (Old) and /work/SRC/openSUSE:Factory/.audaspace.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "audaspace" Mon Mar 23 17:11:28 2026 rev:25 rq:1341585 version:1.9.0 Changes: -------- --- /work/SRC/openSUSE:Factory/audaspace/audaspace.changes 2025-11-13 17:30:38.591449511 +0100 +++ /work/SRC/openSUSE:Factory/.audaspace.new.8177/audaspace.changes 2026-03-23 17:11:45.457653857 +0100 @@ -1,0 +2,13 @@ +Fri Mar 20 17:48:37 UTC 2026 - Marcus Rueckert <[email protected]> + +- Update to release 1.9.0 + - New Echo effect (thanks AGoldenDragon) + - Bugfix for Catmull-Rom spline interpolation + - Build fixes for Mac (thanks Jonas Holzman) + - Python API documentation for class constructors (thanks Andrej + Zhilenkov) + - CMake fixes (thanks Campbell Barton) + - Sample rate type warnings (thanks Jacques Lucke and Ray + Molenkamp) + +------------------------------------------------------------------- Old: ---- audaspace-1.8.0.tar.gz New: ---- audaspace-1.9.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ audaspace.spec ++++++ --- /var/tmp/diff_new_pack.aeYK0z/_old 2026-03-23 17:11:46.145682514 +0100 +++ /var/tmp/diff_new_pack.aeYK0z/_new 2026-03-23 17:11:46.145682514 +0100 @@ -1,7 +1,7 @@ # # spec file for package audaspace # -# Copyright (c) 2025 SUSE LLC and contributors +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,8 +18,8 @@ # See also http://en.opensuse.org/openSUSE:Shared_library_packaging_policy # NOTE: sover follows version. -%define sover 1_8 -%define soversion 1.8 +%define sover 1_9 +%define soversion 1.9 %if %{pkg_vcmp pipewire-devel >= 1.4.0} %bcond_without pipewire @@ -28,7 +28,7 @@ %endif Name: audaspace -Version: 1.8.0 +Version: 1.9.0 Release: 0 Summary: A High-Level Audio Library License: Apache-2.0 ++++++ audaspace-1.8.0.tar.gz -> audaspace-1.9.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/AUTHORS new/audaspace-1.9.0/AUTHORS --- old/audaspace-1.8.0/AUTHORS 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/AUTHORS 2026-03-20 18:10:20.000000000 +0100 @@ -31,6 +31,10 @@ - Kacey La +The echo effect has been provided by + +- AGoldenDragon + Several people provided fixes: - Aaron Carlisle @@ -40,3 +44,7 @@ - Lalit Shankar Chowdhury - Nathan Burnham - Weizhen Huang +- Jonas Holzman +- Andrej Zhilenkov +- Jacques Lucke +- Ray Molenkamp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/CHANGES new/audaspace-1.9.0/CHANGES --- old/audaspace-1.8.0/CHANGES 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/CHANGES 2026-03-20 18:10:20.000000000 +0100 @@ -1,3 +1,23 @@ +Audaspace 1.9 + +- New Echo effect (thanks AGoldenDragon) +- Bugfix for Catmull-Rom spline interpolation +- Build fixes for Mac (thanks Jonas Holzman) +- Python API documentation for class constructors (thanks Andrej Zhilenkov) +- CMake fixes (thanks Campbell Barton) +- Sample rate type warnings (thanks Jacques Lucke and Ray Molenkamp) + +Detailed list of changes: + +e4a3d40 Porting fixes from blender +3348de2 PyDoc: Add constructor docstrings to aud types +7b04aa9 Build: macOS: Fix bitwise operation enum type warning in Audaspace +a931d65 Bugfix: Catmull-Rom spline interpolation was wrong. +1550e14 Fix AUD_Sound_Echo wrongly inside WITH_CONVOLUTION guard +ddda09e Echo: change wet/dry behavior. +31a59c4 Fixing Echo effect: +c3d4ba9 Implemented a new Echo effect (#63) + Audaspace 1.8 - Time stretching and pitch scaling including animation and python API added (thanks Kacey La!). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/CMakeLists.txt new/audaspace-1.9.0/CMakeLists.txt --- old/audaspace-1.8.0/CMakeLists.txt 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/CMakeLists.txt 2026-03-20 18:10:20.000000000 +0100 @@ -23,7 +23,7 @@ project(audaspace) -set(AUDASPACE_VERSION 1.8) +set(AUDASPACE_VERSION 1.9) set(AUDASPACE_LONG_VERSION ${AUDASPACE_VERSION}.0) if(DEFINED AUDASPACE_CMAKE_CFG) @@ -92,6 +92,8 @@ src/fx/VolumeReader.cpp src/fx/VolumeSound.cpp src/fx/VolumeStorage.cpp + src/fx/Echo.cpp + src/fx/EchoReader.cpp src/generator/Sawtooth.cpp src/generator/SawtoothReader.cpp src/generator/Silence.cpp @@ -206,6 +208,8 @@ include/fx/VolumeReader.h include/fx/VolumeSound.h include/fx/VolumeStorage.h + include/fx/Echo.h + include/fx/EchoReader.h include/generator/Sawtooth.h include/generator/SawtoothReader.h include/generator/Silence.h @@ -257,9 +261,9 @@ set(INCLUDE ${CMAKE_CURRENT_BINARY_DIR} include) if(WIN32) - set(LIBRARIES) + set(LIBRARIES "") if(AUDASPACE_STANDALONE) - set(DLLS) + set(DLLS "") set(LIBRARY_PATH "../lib" CACHE PATH "Path which contains the libraries.") file(GLOB LIBRARY_DIRS ${LIBRARY_PATH}/*) list(APPEND CMAKE_PREFIX_PATH ${LIBRARY_DIRS}) @@ -942,7 +946,6 @@ # directories include_directories(${INCLUDE}) -link_directories() # install configuration @@ -1216,7 +1219,14 @@ endif() add_library(audaspace-py ${LIBRARY_TYPE} ${PYTHON_SRC} ${PYTHON_HDR}) - target_link_libraries(audaspace-py audaspace ${PYTHON_LIBRARIES}) + # When Blender is built as a Python module, `PYTHON_LIBRARIES` won't be defined. + # NOTE: AUDASPACE has its own `WITH_PYTHON_MODULE` option with different meaning, + # so we check the variable is defined instead. + if(DEFINED PYTHON_LIBRARIES) + target_link_libraries(audaspace-py audaspace ${PYTHON_LIBRARIES}) + else() + target_link_libraries(audaspace-py audaspace) + endif() set_target_properties(audaspace-py PROPERTIES SOVERSION ${AUDASPACE_VERSION}) if(AUDASPACE_STANDALONE) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/bindings/C/AUD_Device.cpp new/audaspace-1.9.0/bindings/C/AUD_Device.cpp --- old/audaspace-1.8.0/bindings/C/AUD_Device.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/bindings/C/AUD_Device.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -51,7 +51,7 @@ dspecs.channels = CHANNELS_STEREO; if(dspecs.format == FORMAT_INVALID) dspecs.format = FORMAT_FLOAT32; - if(dspecs.rate == RATE_INVALID) + if(dspecs.rate == double(RATE_INVALID)) dspecs.rate = RATE_48000; if(buffersize < 128) buffersize = AUD_DEFAULT_BUFFER_SIZE; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/bindings/C/AUD_Sound.cpp new/audaspace-1.9.0/bindings/C/AUD_Sound.cpp --- old/audaspace-1.8.0/bindings/C/AUD_Sound.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/bindings/C/AUD_Sound.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -51,6 +51,8 @@ #include "util/Buffer.h" #include "Exception.h" +#include "fx/Echo.h" + #ifdef WITH_CONVOLUTION #include "fx/BinauralSound.h" #include "fx/ConvolverSound.h" @@ -172,7 +174,7 @@ DeviceSpecs specs; specs.specs = reader->getSpecs(); - if((rate != RATE_INVALID) && (specs.rate != rate)) + if((rate != double(RATE_INVALID)) && (specs.rate != rate)) { specs.rate = rate; reader = std::make_shared<JOSResampleReader>(reader, rate); @@ -782,7 +784,22 @@ return nullptr; } } +#endif +AUD_API AUD_Sound* AUD_Sound_Echo(AUD_Sound* sound, float delay, float feedback, float mix, bool resetBuffer) +{ + assert(sound); + try + { + return new AUD_Sound(new Echo(*sound, delay, feedback, mix, resetBuffer)); + } + catch(Exception&) + { + return nullptr; + } +} + +#ifdef WITH_CONVOLUTION AUD_API AUD_Sound* AUD_Sound_equalize(AUD_Sound* sound, float *definition, int size, float maxFreqEq, int sizeConversion) { assert(sound); @@ -792,7 +809,6 @@ AUD_Sound *equalizer=new AUD_Sound(new Equalizer(*sound, buf, size, maxFreqEq, sizeConversion)); return equalizer; } - #endif #ifdef WITH_RUBBERBAND diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/bindings/C/AUD_Sound.h new/audaspace-1.9.0/bindings/C/AUD_Sound.h --- old/audaspace-1.8.0/bindings/C/AUD_Sound.h 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/bindings/C/AUD_Sound.h 2026-03-20 18:10:20.000000000 +0100 @@ -394,6 +394,17 @@ */ extern AUD_API AUD_Sound* AUD_Sound_mutable(AUD_Sound* sound); + /** + * Adds Echo effect to the sound. + * \param sound The handle of the sound. + * \param delay The delay time in seconds. + * \param feedback The feedback amount (0.0 to 1.0). + * \param mix The wet/dry mix (0.0 to 1.0). + * \param resetBuffer Whether to reset the delay buffer on seek. + * \return A handle of the time-stretched, pitch scaled sound. + */ +extern AUD_API AUD_Sound* AUD_Sound_Echo(AUD_Sound* sound, float delay, float feedback, float mix, bool resetBuffer); + #ifdef WITH_CONVOLUTION extern AUD_API AUD_Sound* AUD_Sound_Convolver(AUD_Sound* sound, AUD_ImpulseResponse* filter, AUD_ThreadPool* threadPool); extern AUD_API AUD_Sound* AUD_Sound_Binaural(AUD_Sound* sound, AUD_HRTF* hrtfs, AUD_Source* source, AUD_ThreadPool* threadPool); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/bindings/python/PyAnimateableProperty.cpp new/audaspace-1.9.0/bindings/python/PyAnimateableProperty.cpp --- old/audaspace-1.8.0/bindings/python/PyAnimateableProperty.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/bindings/python/PyAnimateableProperty.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -326,7 +326,13 @@ {nullptr} /* Sentinel */ }; -PyDoc_STRVAR(M_aud_AnimateableProperty_doc, "An AnimateableProperty object stores an array of float values for animating sound properties (e.g. pan, volume, pitch-scale)"); +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 = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/bindings/python/PyDevice.cpp new/audaspace-1.9.0/bindings/python/PyDevice.cpp --- old/audaspace-1.8.0/bindings/python/PyDevice.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/bindings/python/PyDevice.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -711,9 +711,22 @@ }; PyDoc_STRVAR(M_aud_Device_doc, - "Device objects represent an audio output backend like OpenAL or " + ".. 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."); + "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) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/bindings/python/PyDynamicMusic.cpp new/audaspace-1.9.0/bindings/python/PyDynamicMusic.cpp --- old/audaspace-1.8.0/bindings/python/PyDynamicMusic.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/bindings/python/PyDynamicMusic.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -392,8 +392,11 @@ }; PyDoc_STRVAR(M_aud_DynamicMusic_doc, - "The DynamicMusic object allows to play music depending on a current scene, scene changes are managed by the class, with the possibility of custom transitions.\n" - "The default transition is a crossfade effect, and the default scene is silent and has id 0"); + ".. 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) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/bindings/python/PyHRTF.cpp new/audaspace-1.9.0/bindings/python/PyHRTF.cpp --- old/audaspace-1.8.0/bindings/python/PyHRTF.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/bindings/python/PyHRTF.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -173,7 +173,8 @@ }; PyDoc_STRVAR(M_aud_HRTF_doc, - "An HRTF object represents a set of head related transfer functions as impulse responses. It's used for binaural sound"); + ".. 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) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/bindings/python/PyImpulseResponse.cpp new/audaspace-1.9.0/bindings/python/PyImpulseResponse.cpp --- old/audaspace-1.8.0/bindings/python/PyImpulseResponse.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/bindings/python/PyImpulseResponse.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -63,7 +63,10 @@ }; PyDoc_STRVAR(M_aud_ImpulseResponse_doc, - "An ImpulseResponse object represents a filter with which to convolve a sound."); + ".. 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) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/bindings/python/PyPlaybackManager.cpp new/audaspace-1.9.0/bindings/python/PyPlaybackManager.cpp --- old/audaspace-1.8.0/bindings/python/PyPlaybackManager.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/bindings/python/PyPlaybackManager.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -316,7 +316,10 @@ }; PyDoc_STRVAR(M_aud_PlaybackManager_doc, - "A PlabackManager object allows to easily control groups os sounds organized in categories."); + ".. 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) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/bindings/python/PySequence.cpp new/audaspace-1.9.0/bindings/python/PySequence.cpp --- old/audaspace-1.8.0/bindings/python/PySequence.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/bindings/python/PySequence.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -579,7 +579,16 @@ }; PyDoc_STRVAR(M_aud_Sequence_doc, - "This sound represents sequenced entries to play a sound sequence."); + ".. 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; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/bindings/python/PySound.cpp new/audaspace-1.9.0/bindings/python/PySound.cpp --- old/audaspace-1.8.0/bindings/python/PySound.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/bindings/python/PySound.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -60,6 +60,8 @@ #include "sequence/PingPong.h" #include "sequence/Superpose.h" +#include "fx/Echo.h" + #ifdef WITH_CONVOLUTION #include "fx/BinauralSound.h" #include "fx/ConvolverSound.h" @@ -1685,6 +1687,53 @@ } } +PyDoc_STRVAR(M_aud_Sound_echo_doc, ".. method:: Echo(delay, feedback, mix)\n\n" + " Adds Echo effect to the sound.\n\n" + " :arg delay: The delay time in seconds.\n" + " :type delay: float\n" + " :arg feedback: The feedback amount (0.0 to 1.0).\n" + " :type feedback: float\n" + " :arg mix: The wet/dry mix (0.0 to 1.0).\n" + " :type mix: float\n" + " :arg reset_buffer: Whether to reset the delay buffer on seek.\n" + " :type reset_buffer: bool\n" + " :return: The created :class:`Sound` object.\n" + " :rtype: :class:`Sound`"); +static PyObject* Sound_echo(Sound* self, PyObject* args, PyObject* kwds) +{ + float delay = 0.5; + float feedback = 0.5; + float mix = 0.5; + bool reset_buffer = true; + static const char* kwlist[] = {"delay", "feedback", "mix", "reset_buffer", nullptr}; + + if(!PyArg_ParseTupleAndKeywords(args, kwds, "fff|b:echo", const_cast<char**>(kwlist), &delay, &feedback, &mix, &reset_buffer)) + { + return nullptr; + } + + PyTypeObject* type = Py_TYPE(self); + Sound* parent = (Sound*) type->tp_alloc(type, 0); + + if(parent != nullptr) + { + try + { + auto input = *reinterpret_cast<std::shared_ptr<ISound>*>(self->sound); + auto echo = std::make_shared<Echo>(input, delay, feedback, mix, reset_buffer); + parent->sound = new std::shared_ptr<ISound>(echo); + } + catch(Exception& e) + { + Py_DECREF(parent); + PyErr_SetString(AUDError, e.what()); + return nullptr; + } + } + + return (PyObject*)parent; +} + #ifdef WITH_CONVOLUTION PyDoc_STRVAR(M_aud_Sound_convolver_doc, @@ -2057,6 +2106,9 @@ { "addSound", (PyCFunction)Sound_list_addSound, METH_O, M_aud_Sound_list_addSound_doc }, + {"echo", (PyCFunction)Sound_echo, METH_VARARGS | METH_KEYWORDS, + M_aud_Sound_echo_doc}, + #ifdef WITH_CONVOLUTION { "convolver", (PyCFunction)Sound_convolver, METH_VARARGS, M_aud_Sound_convolver_doc @@ -2119,10 +2171,16 @@ }; PyDoc_STRVAR(M_aud_Sound_doc, - "Sound objects are immutable and represent a sound that can be " + ".. class:: Sound(filename, stream=0)\n\n" + " Sound objects are immutable and represent a sound that can be " "played simultaneously multiple times. They are called factories " "because they create reader objects internally that are used for " - "playback."); + "playback.\n\n" + " :arg filename: Path of the file.\n" + " :type filename: string\n" + " :arg stream: The index of the audio stream within the file if it\n" + " contains multiple audio streams, 0 by default.\n" + " :type stream: int\n"); PyTypeObject SoundType = { PyVarObject_HEAD_INIT(nullptr, 0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/bindings/python/PySource.cpp new/audaspace-1.9.0/bindings/python/PySource.cpp --- old/audaspace-1.8.0/bindings/python/PySource.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/bindings/python/PySource.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -186,7 +186,14 @@ }; PyDoc_STRVAR(M_aud_Source_doc, - "The source object represents the source position of a binaural sound."); + ".. 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) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/bindings/python/PyThreadPool.cpp new/audaspace-1.9.0/bindings/python/PyThreadPool.cpp --- old/audaspace-1.8.0/bindings/python/PyThreadPool.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/bindings/python/PyThreadPool.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -60,7 +60,10 @@ }; PyDoc_STRVAR(M_aud_ThreadPool_doc, - "A ThreadPool is used to parallelize convolution efficiently."); + ".. 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) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/include/fx/Echo.h new/audaspace-1.9.0/include/fx/Echo.h --- old/audaspace-1.8.0/include/fx/Echo.h 1970-01-01 01:00:00.000000000 +0100 +++ new/audaspace-1.9.0/include/fx/Echo.h 2026-03-20 18:10:20.000000000 +0100 @@ -0,0 +1,27 @@ +#pragma once + +/** + * @file Echo.h + * @ingroup fx + * The Echo class. + */ + +#include "fx/Effect.h" + +AUD_NAMESPACE_BEGIN + +class AUD_API Echo : public Effect +{ +private: + float m_delay; /* Delay time in seconds */ + float m_feedback; /* Feedback amount */ + float m_mix; /* Wet/dry mix */ + bool m_resetBuffer; /* Whether to reset the delay buffer */ + +public: + Echo(std::shared_ptr<ISound> sound, float delay, float feedback, float mix, bool resetBuffer = true); + + virtual std::shared_ptr<IReader> createReader(); +}; + +AUD_NAMESPACE_END diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/include/fx/EchoReader.h new/audaspace-1.9.0/include/fx/EchoReader.h --- old/audaspace-1.8.0/include/fx/EchoReader.h 1970-01-01 01:00:00.000000000 +0100 +++ new/audaspace-1.9.0/include/fx/EchoReader.h 2026-03-20 18:10:20.000000000 +0100 @@ -0,0 +1,53 @@ +/******************************************************************************* + * 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 + +/** + * @file EchoReader.h + * @ingroup fx + * The EchoReader class. + */ + +#include <memory> + +#include "fx/EffectReader.h" +#include "util/Buffer.h" + +AUD_NAMESPACE_BEGIN + +class AUD_API EchoReader : public EffectReader +{ +private: + float m_delay; + float m_feedback; + float m_mix; + bool m_resetBuffer; + + Buffer m_inBuffer; + Buffer m_delayBuffer; + + int m_writePosition{0}; + int m_samplesAvailable{0}; + +public: + EchoReader(std::shared_ptr<IReader> reader, float delay, float feedback, float mix, bool resetBuffer = true); + + virtual void read(int& length, bool& eos, sample_t* buffer) override; + virtual void seek(int position) override; +}; + +AUD_NAMESPACE_END diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/plugins/coreaudio/CoreAudioDevice.cpp new/audaspace-1.9.0/plugins/coreaudio/CoreAudioDevice.cpp --- old/audaspace-1.8.0/plugins/coreaudio/CoreAudioDevice.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/plugins/coreaudio/CoreAudioDevice.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -157,7 +157,7 @@ stream_basic_description.mSampleRate = m_specs.rate; stream_basic_description.mFormatID = kAudioFormatLinearPCM; - stream_basic_description.mFormatFlags |= kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked; + stream_basic_description.mFormatFlags |= AudioFormatFlags(kAudioFormatFlagsNativeEndian) | AudioFormatFlags(kLinearPCMFormatFlagIsPacked); stream_basic_description.mBytesPerPacket = stream_basic_description.mBytesPerFrame = AUD_DEVICE_SAMPLE_SIZE(m_specs); stream_basic_description.mFramesPerPacket = 1; stream_basic_description.mChannelsPerFrame = m_specs.channels; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/plugins/openal/OpenALDevice.cpp new/audaspace-1.9.0/plugins/openal/OpenALDevice.cpp --- old/audaspace-1.8.0/plugins/openal/OpenALDevice.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/plugins/openal/OpenALDevice.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -931,7 +931,7 @@ ALCint attribs[] = { ALC_FREQUENCY, (ALCint)specs.rate, 0 }; ALCint* attributes = attribs; - if(specs.rate == RATE_INVALID) + if(specs.rate == double(RATE_INVALID)) attributes = nullptr; m_context = alcCreateContext(m_device, attributes); @@ -1152,7 +1152,7 @@ // at least try to set the frequency ALCint attribs[] = { ALC_FREQUENCY, (ALCint)specs.rate, 0 }; ALCint* attributes = attribs; - if(specs.rate == RATE_INVALID) + if(specs.rate == double(RATE_INVALID)) attributes = nullptr; m_context = alcCreateContext(m_device, attributes); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/plugins/wasapi/WASAPIDevice.cpp new/audaspace-1.9.0/plugins/wasapi/WASAPIDevice.cpp --- old/audaspace-1.8.0/plugins/wasapi/WASAPIDevice.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/plugins/wasapi/WASAPIDevice.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -373,7 +373,7 @@ specs.channels = CHANNELS_STEREO; if(specs.format == FORMAT_INVALID) specs.format = FORMAT_FLOAT32; - if(specs.rate == RATE_INVALID) + if(int(specs.rate) == RATE_INVALID) specs.rate = RATE_48000; if(FAILED(CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, reinterpret_cast<void**>(m_imm_device_enumerator.GetAddressOf())))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/src/fx/Echo.cpp new/audaspace-1.9.0/src/fx/Echo.cpp --- old/audaspace-1.8.0/src/fx/Echo.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/audaspace-1.9.0/src/fx/Echo.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -0,0 +1,17 @@ +#include "fx/Echo.h" + +#include "fx/EchoReader.h" + +AUD_NAMESPACE_BEGIN + +Echo::Echo(std::shared_ptr<ISound> sound, float delay, float feedback, float mix, bool resetBuffer) : + Effect(sound), m_delay(delay), m_feedback(feedback), m_mix(mix), m_resetBuffer(resetBuffer) +{ +} + +std::shared_ptr<IReader> Echo::createReader() +{ + return std::make_shared<EchoReader>(getReader(), m_delay, m_feedback, m_mix, m_resetBuffer); +} + +AUD_NAMESPACE_END diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/src/fx/EchoReader.cpp new/audaspace-1.9.0/src/fx/EchoReader.cpp --- old/audaspace-1.8.0/src/fx/EchoReader.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/audaspace-1.9.0/src/fx/EchoReader.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -0,0 +1,79 @@ +/******************************************************************************* + * 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 "fx/EchoReader.h" + +#include <cstring> + +#include "IReader.h" + +#include "util/Buffer.h" + +AUD_NAMESPACE_BEGIN + +EchoReader::EchoReader(std::shared_ptr<IReader> reader, float delay, float feedback, float mix, bool resetBuffer) : + EffectReader(reader), m_delay(delay), m_feedback(feedback), m_mix(mix), m_resetBuffer(resetBuffer) +{ +} + +void EchoReader::read(int& length, bool& eos, sample_t* buffer) +{ + auto specs = m_reader->getSpecs(); + auto delaySamples = static_cast<int>(m_delay * specs.rate); + + m_inBuffer.assureSize(length * AUD_SAMPLE_SIZE(specs)); + + // Note: should this ever do something another time than in the beginning, + // it will likely cause an audible glitch, as samples are not reordered + m_delayBuffer.assureSize(delaySamples * AUD_SAMPLE_SIZE(specs)); + + m_reader->read(length, eos, m_inBuffer.getBuffer()); + + sample_t* delayBuffer = m_delayBuffer.getBuffer(); + + for(int i = 0; i < length; i++) + { + for(int channel = 0; channel < specs.channels; channel++) + { + int delayPosition = ((m_writePosition + i) % delaySamples) * specs.channels + channel; + + sample_t inSample = m_inBuffer.getBuffer()[i * specs.channels + channel]; + sample_t delayedSample = delayPosition < m_samplesAvailable * specs.channels ? delayBuffer[delayPosition] : 0; + + sample_t outSample = inSample + delayedSample * m_feedback; + buffer[i * specs.channels + channel] = inSample * (1.0f - m_mix) + outSample * m_mix; + + // Update delay buffer with feedback + delayBuffer[delayPosition] = outSample; + } + } + + m_writePosition = (m_writePosition + length) % delaySamples; + m_samplesAvailable = std::min(delaySamples, m_samplesAvailable + length); +} + +void EchoReader::seek(int position) +{ + m_reader->seek(position); + + if(m_resetBuffer) + { + m_samplesAvailable = 0; + m_writePosition = 0; + } +} + +AUD_NAMESPACE_END diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/audaspace-1.8.0/src/sequence/AnimateableProperty.cpp new/audaspace-1.9.0/src/sequence/AnimateableProperty.cpp --- old/audaspace-1.8.0/src/sequence/AnimateableProperty.cpp 2025-11-13 08:09:33.000000000 +0100 +++ new/audaspace-1.9.0/src/sequence/AnimateableProperty.cpp 2026-03-20 18:10:20.000000000 +0100 @@ -223,8 +223,7 @@ m0 = (p2[i] - p0[i]) / 2.0f; m1 = (p3[i] - p1[i]) / 2.0f; - out[i] = (2 * t3 - 3 * t2 + 1) * p0[i] + (-2 * t3 + 3 * t2) * p1[i] + - (t3 - 2 * t2 + t) * m0 + (t3 - t2) * m1; + out[i] = (2 * t3 - 3 * t2 + 1) * p1[i] + (-2 * t3 + 3 * t2) * p2[i] + (t3 - 2 * t2 + t) * m0 + (t3 - t2) * m1; } } }
