f@5: /* f@5: f@5: Copyright (C) 2016 Queen Mary University of London f@16: Author: Fiore Martin, based on CCRMA STK ADSR.h (https://ccrma.stanford.edu/software/stk/classstk_1_1ADSR.html) f@5: f@5: This file is part of Collidoscope. f@5: f@5: Collidoscope is free software: you can redistribute it and/or modify f@5: it under the terms of the GNU General Public License as published by f@5: the Free Software Foundation, either version 3 of the License, or f@5: (at your option) any later version. f@5: f@5: This program is distributed in the hope that it will be useful, f@5: but WITHOUT ANY WARRANTY; without even the implied warranty of f@5: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the f@5: GNU General Public License for more details. f@5: f@5: You should have received a copy of the GNU General Public License f@5: along with this program. If not, see . f@16: f@16: This file incorporates work covered by the following copyright and permission notice: f@16: f@16: The Synthesis ToolKit in C++ (STK) f@16: f@16: Copyright (c) 1995--2016 Perry R. Cook and Gary P. Scavone f@16: f@16: Permission is hereby granted, free of charge, to any person obtaining f@16: a copy of this software and associated documentation files (the f@16: "Software"), to deal in the Software without restriction, including f@16: without limitation the rights to use, copy, modify, merge, publish, f@16: distribute, sublicense, and/or sell copies of the Software, and to f@16: permit persons to whom the Software is furnished to do so, subject to f@16: the following conditions: f@16: f@16: The above copyright notice and this permission notice shall be f@16: included in all copies or substantial portions of the Software. f@16: f@16: Any person wishing to distribute modifications to the Software is f@16: asked to send the modifications to the original developer so that they f@16: can be incorporated into the canonical version. This is, however, not f@16: a binding provision of this license. f@16: f@16: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, f@16: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF f@16: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. f@16: IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR f@16: ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF f@16: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION f@16: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. f@16: f@5: */ f@5: f@0: #pragma once f@0: f@0: namespace collidoscope { f@0: f@2: f@2: /* f@2: * An ASR envelope with linear shape. It is modeled after the STK envelope classes. f@2: * The tick() method advances the computation of the envelope one sample and returns the computed sample f@2: * The class is templated for the type of the samples that each tick of the envelope produces. f@2: * f@2: * Client classes can set/get the current state of the envelope with the f@2: * respective getter/setter methods f@2: * f@2: */ f@0: template f@0: class EnvASR f@0: { f@0: public: f@0: f@3: /** Possible states of the envelope. Idle means the envelope ouputs 0 */ f@0: enum class State { f@0: eAttack, f@0: eSustain, f@0: eRelease, f@0: eIdle // before attack after release f@0: }; f@0: f@0: EnvASR( T sustainLevel, T attackTime, T releaseTime, std::size_t sampleRate ) : f@0: mSustainLevel( sustainLevel ), f@0: mState( State::eIdle ), f@0: mValue( 0 ) f@0: f@0: { f@0: if ( attackTime <= 0 ) f@0: attackTime = T( 0.001 ); f@0: f@0: if ( releaseTime <= 0 ) f@0: releaseTime = T( 0.001 ); f@0: f@0: mAttackRate = T( 1.0 ) / (attackTime * sampleRate); f@0: mReleaseRate = T( 1.0 ) / (releaseTime * sampleRate); f@0: } f@0: f@3: /** Produces one sample worth of envelope */ f@0: T tick() f@0: { f@0: f@0: switch ( mState ) f@0: { f@0: f@0: case State::eIdle: { f@0: mValue = 0; f@0: }; f@0: break; f@0: f@0: case State::eAttack: { f@0: mValue += mAttackRate; f@0: if ( mValue >= mSustainLevel ){ f@0: mValue = mSustainLevel; f@0: mState = State::eSustain; f@0: } f@0: }; f@0: break; f@0: f@0: case State::eRelease: f@0: mValue -= mReleaseRate; f@0: if ( mValue <= 0 ){ f@0: mValue = 0; f@0: mState = State::eIdle; f@0: } f@0: break; f@0: default: f@0: break; f@0: } f@0: f@0: return mValue; f@0: f@0: } f@0: f@0: State getState() const f@0: { f@0: return mState; f@0: } f@0: f@0: void setState( State state ) f@0: { f@0: mState = state; f@0: } f@0: f@0: private: f@0: T mSustainLevel; f@0: T mAttackRate; f@0: T mReleaseRate; f@0: f@0: // output f@0: T mValue; f@0: f@0: State mState; f@0: f@0: }; f@0: f@0: f@2: }