diff --git a/doc/openal-support.dox b/doc/openal-support.dox index f9c5c39c4..66aaad645 100644 --- a/doc/openal-support.dox +++ b/doc/openal-support.dox @@ -4,6 +4,7 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Vladimír Vondruš Copyright © 2015 Jonathan Hale + Copyright © 2019 Guillaume Jacquemin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -58,6 +59,7 @@ Extension | Status ------------------------------------------- | ------ @alc_extension{SOFTX,HRTF} | done @alc_extension{SOFT,HRTF} | done +@al_extension{SOFT,loop_points} | done */ } diff --git a/src/Magnum/Audio/Buffer.cpp b/src/Magnum/Audio/Buffer.cpp new file mode 100644 index 000000000..0bdd685f5 --- /dev/null +++ b/src/Magnum/Audio/Buffer.cpp @@ -0,0 +1,43 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + Vladimír Vondruš + Copyright © 2019 Guillaume Jacquemin + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Buffer.h" + +#include "Magnum/Math/Functions.h" + +namespace Magnum { namespace Audio { + +Buffer& Buffer::setLoopPoints(Int loopStart, Int loopEnd) { + const Int loopPoints[2]{ + Math::max(0, loopStart), + Math::min(loopEnd, sampleCount()) + }; + + alBufferiv(_id, AL_LOOP_POINTS_SOFT, loopPoints); + return *this; +} + +}} diff --git a/src/Magnum/Audio/Buffer.h b/src/Magnum/Audio/Buffer.h index d9606f5e9..40b5ebb1e 100644 --- a/src/Magnum/Audio/Buffer.h +++ b/src/Magnum/Audio/Buffer.h @@ -30,6 +30,7 @@ * @brief Class @ref Magnum::Audio::Buffer */ +#include #include #include #include @@ -49,7 +50,7 @@ namespace Magnum { namespace Audio { /** @brief Sample buffer */ -class Buffer { +class MAGNUM_AUDIO_EXPORT Buffer { public: #ifdef MAGNUM_BUILD_DEPRECATED /** @brief @copybrief BufferFormat @@ -141,6 +142,71 @@ class Buffer { return size() * 8 / (channels() * bitDepth()); } + /** + * @brief Get buffer loop points + * @return A @ref std::pair containing the start and end loop points + * + * @requires_al_extension Extension @al_extension{SOFT,loop_points} + */ + std::pair loopPoints() { + std::pair points{0, 0}; + alGetBufferiv(_id, AL_LOOP_POINTS_SOFT, &(points.first)); + return points; + } + + /** + * @brief Set buffer loop points + * @param loopStart The loop's start point in samples + * @param loopEnd The loop's end point in samples + * @return Reference to self (for method chaining) + * + * The buffer needs to not be attached to a source for this operation to + * succeed. + * @requires_al_extension Extension @al_extension{SOFT,loop_points} + */ + Buffer& setLoopPoints(Int loopStart, Int loopEnd); + + /** + * @brief Set buffer to loop from the beginning until a certain point + * @param loopEnd The loop's end point in samples + * @return Reference to self (for method chaining) + * + * Equivalent to calling @ref setLoopPoints() with @p loopStart equal to + * 0. + * + * @requires_al_extension Extension @al_extension{SOFT,loop_points} + */ + Buffer& setLoopUntil(Int loopEnd) { + return setLoopPoints(0, loopEnd); + } + + /** + * @brief Set buffer to loop from the a certain point until the end + * @param loopStart The loop's start point in samples + * @return Reference to self (for method chaining) + * + * Equivalent to calling @ref setLoopPoints() with @p loopEnd equal to + * @p INT_MAX. + * + * @requires_al_extension Extension @al_extension{SOFT,loop_points} + */ + Buffer& setLoopSince(Int loopStart) { + return setLoopPoints(loopStart, INT_MAX); + } + + /** + * @brief Resets the loop points + * @return Reference to self (for method chaining) + * + * Equivalent to calling @ref setLoopPoints() with @p loopStart equal to + * 0, and @p loopEnd equal to @p INT_MAX. + * + * @requires_al_extension Extension @al_extension{SOFT,loop_points} + */ + Buffer& resetLoopPoints() { + return setLoopPoints(0, INT_MAX); + } + private: ALuint _id; }; diff --git a/src/Magnum/Audio/CMakeLists.txt b/src/Magnum/Audio/CMakeLists.txt index 89512713c..f269f0c3b 100644 --- a/src/Magnum/Audio/CMakeLists.txt +++ b/src/Magnum/Audio/CMakeLists.txt @@ -29,6 +29,7 @@ find_package(OpenAL REQUIRED) set(MagnumAudio_SRCS AbstractImporter.cpp Audio.cpp + Buffer.cpp BufferFormat.cpp Context.cpp Renderer.cpp diff --git a/src/Magnum/Audio/Context.cpp b/src/Magnum/Audio/Context.cpp index 47b16a2e7..aa25c62e4 100644 --- a/src/Magnum/Audio/Context.cpp +++ b/src/Magnum/Audio/Context.cpp @@ -50,6 +50,7 @@ constexpr Extension ExtensionList[]{ _extension(AL,EXT,ALAW), _extension(AL,EXT,MULAW), _extension(AL,EXT,MCFORMATS), + _extension(AL,SOFT,loop_points), _extension(ALC,EXT,ENUMERATION), _extension(ALC,SOFTX,HRTF), _extension(ALC,SOFT,HRTF) diff --git a/src/Magnum/Audio/Extensions.h b/src/Magnum/Audio/Extensions.h index a40dc3d1f..6b8ba91d4 100644 --- a/src/Magnum/Audio/Extensions.h +++ b/src/Magnum/Audio/Extensions.h @@ -84,15 +84,18 @@ namespace AL { _extension(4,AL,EXT,MULAW) // #??? _extension(5,AL,EXT,MCFORMATS) // #??? } + namespace SOFT { + _extension(6,AL,SOFT,loop_points) // #??? + } } namespace ALC { namespace EXT { - _extension_rev(6,ALC,EXT,ENUMERATION) // #??? + _extension_rev(7,ALC,EXT,ENUMERATION) // #??? } namespace SOFTX { - _extension(7,ALC,SOFTX,HRTF) // #??? + _extension(8,ALC,SOFTX,HRTF) // #??? } namespace SOFT { - _extension(8,ALC,SOFT,HRTF) // #??? + _extension(9,ALC,SOFT,HRTF) // #??? } } #undef _extension diff --git a/src/Magnum/Audio/Test/BufferALTest.cpp b/src/Magnum/Audio/Test/BufferALTest.cpp index 234176dc8..81fddef70 100644 --- a/src/Magnum/Audio/Test/BufferALTest.cpp +++ b/src/Magnum/Audio/Test/BufferALTest.cpp @@ -29,6 +29,7 @@ #include "Magnum/Audio/Buffer.h" #include "Magnum/Audio/BufferFormat.h" #include "Magnum/Audio/Context.h" +#include "Magnum/Audio/Extensions.h" namespace Magnum { namespace Audio { namespace Test { namespace { @@ -39,13 +40,25 @@ struct BufferALTest: TestSuite::Tester { void properties(); + void loopPoints(); + void setLoopPoints(); + void setLoopSince(); + void setLoopUntil(); + void resetLoopPoints(); + Context _context; }; BufferALTest::BufferALTest() { addTests({&BufferALTest::construct, - &BufferALTest::properties}); + &BufferALTest::properties, + + &BufferALTest::loopPoints, + &BufferALTest::setLoopPoints, + &BufferALTest::setLoopSince, + &BufferALTest::setLoopUntil, + &BufferALTest::resetLoopPoints}); } void BufferALTest::construct() { @@ -65,6 +78,66 @@ void BufferALTest::properties() { CORRADE_COMPARE(buf.length(), 8); } +void BufferALTest::loopPoints() { + if(!_context.isExtensionSupported()) { + CORRADE_SKIP("Extension AL_SOFT_loop_points isn't supported on this system."); + } + + Buffer buf; + constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; + + buf.setData(BufferFormat::Mono8, data, 22050); + CORRADE_COMPARE(buf.loopPoints(), std::make_pair(0, 8)); +} + +void BufferALTest::setLoopPoints() { + if(!_context.isExtensionSupported()) { + CORRADE_SKIP("Extension AL_SOFT_loop_points isn't supported on this system."); + } + + Buffer buf; + constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; + + buf.setData(BufferFormat::Mono8, data, 22050).setLoopPoints(1, 6); + CORRADE_COMPARE(buf.loopPoints(), std::make_pair(1, 6)); +} + +void BufferALTest::setLoopSince() { + if(!_context.isExtensionSupported()) { + CORRADE_SKIP("Extension AL_SOFT_loop_points isn't supported on this system."); + } + + Buffer buf; + constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; + + buf.setData(BufferFormat::Mono8, data, 22050).setLoopSince(3); + CORRADE_COMPARE(buf.loopPoints(), std::make_pair(3, 8)); +} + +void BufferALTest::setLoopUntil() { + if(!_context.isExtensionSupported()) { + CORRADE_SKIP("Extension AL_SOFT_loop_points isn't supported on this system."); + } + + Buffer buf; + constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; + + buf.setData(BufferFormat::Mono8, data, 22050).setLoopUntil(5); + CORRADE_COMPARE(buf.loopPoints(), std::make_pair(0, 5)); +} + +void BufferALTest::resetLoopPoints() { + if(!_context.isExtensionSupported()) { + CORRADE_SKIP("Extension AL_SOFT_loop_points isn't supported on this system."); + } + + Buffer buf; + constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; + + buf.setData(BufferFormat::Mono8, data, 22050).resetLoopPoints(); + CORRADE_COMPARE(buf.loopPoints(), std::make_pair(0, 8)); +} + }}}} CORRADE_TEST_MAIN(Magnum::Audio::Test::BufferALTest) diff --git a/src/MagnumExternal/OpenAL/extensions.h b/src/MagnumExternal/OpenAL/extensions.h index 3bb99bfa4..1a00a5f44 100644 --- a/src/MagnumExternal/OpenAL/extensions.h +++ b/src/MagnumExternal/OpenAL/extensions.h @@ -6,6 +6,7 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 Vladimír Vondruš Copyright © 2015 Jonathan Hale + Copyright © 2019 Guillaume Jacquemin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -88,6 +89,12 @@ extern "C" { #define AL_FORMAT_71CHN32 0x1212 #endif +/* AL_SOFT_loop_points */ +#ifndef AL_SOFT_loop_points +#define AL_SOFT_loop_points 1 +#define AL_LOOP_POINTS_SOFT 0x2015 +#endif + /* ALC_SOFTX_HRTF */ #ifndef ALC_SOFTX_HRTF #define ALC_SOFTX_HRTF 1