diff options
Diffstat (limited to 'extern/audaspace/src/fx/ADSRReader.cpp')
-rw-r--r-- | extern/audaspace/src/fx/ADSRReader.cpp | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/extern/audaspace/src/fx/ADSRReader.cpp b/extern/audaspace/src/fx/ADSRReader.cpp new file mode 100644 index 00000000000..6499b55468e --- /dev/null +++ b/extern/audaspace/src/fx/ADSRReader.cpp @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright 2009-2016 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/ADSRReader.h" + +AUD_NAMESPACE_BEGIN + +ADSRReader::ADSRReader(std::shared_ptr<IReader> reader, float attack, float decay, float sustain, float release) : + EffectReader(reader), + m_attack(attack), m_decay(decay), m_sustain(sustain), m_release(release) +{ + nextState(ADSR_STATE_ATTACK); +} + +ADSRReader::~ADSRReader() +{ +} + +void ADSRReader::nextState(ADSRState state) +{ + m_state = state; + + switch(m_state) + { + case ADSR_STATE_ATTACK: + m_level = 0; + if(m_attack <= 0) + { + nextState(ADSR_STATE_DECAY); + return; + } + return; + case ADSR_STATE_DECAY: + if(m_decay <= 0) + { + nextState(ADSR_STATE_SUSTAIN); + return; + } + if(m_level > 1.0) + m_level = 1 - (m_level - 1) * m_attack / m_decay * (1 - m_sustain); + if(m_level <= m_sustain) + nextState(ADSR_STATE_SUSTAIN); + break; + case ADSR_STATE_SUSTAIN: + m_level = m_sustain; + break; + case ADSR_STATE_RELEASE: + if(m_release <= 0) + { + nextState(ADSR_STATE_INVALID); + return; + } + break; + case ADSR_STATE_INVALID: + break; + } +} + +void ADSRReader::read(int & length, bool &eos, sample_t* buffer) +{ + Specs specs = m_reader->getSpecs(); + m_reader->read(length, eos, buffer); + + for(int i = 0; i < length; i++) + { + for(int channel = 0; channel < specs.channels; channel++) + { + buffer[i * specs.channels + channel] *= m_level; + } + + switch(m_state) + { + case ADSR_STATE_ATTACK: + m_level += 1 / m_attack / specs.rate; + if(m_level >= 1) + nextState(ADSR_STATE_DECAY); + break; + case ADSR_STATE_DECAY: + m_level -= (1 - m_sustain) / m_decay / specs.rate; + if(m_level <= m_sustain) + nextState(ADSR_STATE_SUSTAIN); + break; + case ADSR_STATE_SUSTAIN: + break; + case ADSR_STATE_RELEASE: + m_level -= m_sustain / m_release / specs.rate ; + if(m_level <= 0) + nextState(ADSR_STATE_INVALID); + break; + case ADSR_STATE_INVALID: + length = i; + return; + } + } +} + +void ADSRReader::release() +{ + nextState(ADSR_STATE_RELEASE); +} + +AUD_NAMESPACE_END |