Documented the envelopes

This commit is contained in:
Paul Ferrand 2019-11-30 00:51:35 +01:00
parent 30e175f4ca
commit c31da4ef1c
3 changed files with 112 additions and 4 deletions

View file

@ -25,15 +25,55 @@
#include "LeakDetector.h" #include "LeakDetector.h"
#include <absl/types/span.h> #include <absl/types/span.h>
namespace sfz { namespace sfz {
/**
* @brief Describe an attack/delay/sustain/release envelope that can
* produce its coefficient in a blockwise manner for SIMD-type operations.
*
* @tparam Type the underlying type
*/
template <class Type> template <class Type>
class ADSREnvelope { class ADSREnvelope {
public: public:
ADSREnvelope() = default; ADSREnvelope() = default;
/**
* @brief Resets the ADSR envelope. There's alot of parameter but what can you do.
* They all match the SFZ specification.
*
* @param attack
* @param release
* @param sustain
* @param delay
* @param decay
* @param hold
* @param start
* @param depth
*/
void reset(int attack, int release, Type sustain = 1.0, int delay = 0, int decay = 0, int hold = 0, Type start = 0.0, Type depth = 1) noexcept; void reset(int attack, int release, Type sustain = 1.0, int delay = 0, int decay = 0, int hold = 0, Type start = 0.0, Type depth = 1) noexcept;
/**
* @brief Get the next value for the envelope
*
* @return Type
*/
Type getNextValue() noexcept; Type getNextValue() noexcept;
/**
* @brief Get a block of values for the envelope. This method tries hard to be efficient
* and hopefully it is.
*
* @param output
*/
void getBlock(absl::Span<Type> output) noexcept; void getBlock(absl::Span<Type> output) noexcept;
/**
* @brief Start the envelope release after a delay.
*
* @param releaseDelay the delay before releasing in samples
*/
void startRelease(int releaseDelay) noexcept; void startRelease(int releaseDelay) noexcept;
/**
* @brief Is the envelope smoothing?
*
* @return true
* @return false
*/
bool isSmoothing() noexcept; bool isSmoothing() noexcept;
private: private:

View file

@ -21,6 +21,17 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/**
* @file FloatEnvelopes.cpp
* @author Paul Ferrand (paul@ferrand.cc)
* @brief Force the instantiations of the ADSR and linear envelopes for floats
* @version 0.1
* @date 2019-11-30
*
* @copyright Copyright (c) 2019 Paul Ferrand
*
*/
#include "LinearEnvelope.h" #include "LinearEnvelope.h"
#include "ADSREnvelope.h" #include "ADSREnvelope.h"

View file

@ -30,17 +30,74 @@
#include <vector> #include <vector>
namespace sfz { namespace sfz {
/**
* @brief Describes a simple linear envelope that can be polled in a blockwise
* manner. It works by storing "events" in the immediate future and linearly
* interpolating between these events. This envelope can also transform its
* incoming target points through a lambda, although the interpolation will
* always be linear (i.e. the lambda function is applied before the interpolation).
*
* The way to use this class is by repeatedly calling `registerEvent` and then
* `getBlock` to get a block of interpolated values in between the specified events.
* You should only register events whose timestamps are below the size of the block
* you will require when calling `getBlock`.
*
* @tparam Type
*/
template <class Type> template <class Type>
class LinearEnvelope { class LinearEnvelope {
public: public:
/**
* @brief Construct a new linear envelope with a default memory size for
* incoming events.
*
*/
LinearEnvelope(); LinearEnvelope();
/**
* @brief Construct a new linear envelope with a specific memory size for
* incoming events as well as a transformation function for incoming events.
*
* @param maxCapacity
* @param function
*/
LinearEnvelope(int maxCapacity, std::function<Type(Type)> function); LinearEnvelope(int maxCapacity, std::function<Type(Type)> function);
/**
* @brief Set the maximum memory size for incoming events
*
* @param maxCapacity
*/
void setMaxCapacity(int maxCapacity); void setMaxCapacity(int maxCapacity);
/**
* @brief Set the transformation function for the value of incoming events.
*
* @param function
*/
void setFunction(std::function<Type(Type)> function); void setFunction(std::function<Type(Type)> function);
/**
* @brief Register a new event. Note that the timestamp of the new value should
* be less than the future call to `getBlock` otherwise the event will be ignored.
*
* @param timestamp
* @param inputValue
*/
void registerEvent(int timestamp, Type inputValue); void registerEvent(int timestamp, Type inputValue);
/**
* @brief Clear all events in memory
*
*/
void clear(); void clear();
/**
* @brief Reset the envelope and clears the memory.
*
* @param value
*/
void reset(Type value = 0.0); void reset(Type value = 0.0);
/**
* @brief Get a block of interpolated values between events previously registered
* using `registerEvent`.
*
* @param output
*/
void getBlock(absl::Span<Type> output); void getBlock(absl::Span<Type> output);
private: private:
std::function<Type(Type)> function { [](Type input) { return input; } }; std::function<Type(Type)> function { [](Type input) { return input; } };