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: }