4 Star 2 Fork 1

BLumia / PineappleSynth

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
EnvelopeGenerator.cpp 3.58 KB
一键复制 编辑 原始数据 按行查看 历史
#include "EnvelopeGenerator.h"
double EnvelopeGenerator::sampleRate = 44100.0;
double EnvelopeGenerator::nextSample() {
if (currentStage != ENVELOPE_STAGE_OFF &&
currentStage != ENVELOPE_STAGE_SUSTAIN) {
if (currentSampleIndex == nextStageSampleIndex) {
EnvelopeStage newStage = static_cast<EnvelopeStage>(
(currentStage + 1) % kNumEnvelopeStages
);
enterStage(newStage);
}
currentLevel *= multiplier;
currentSampleIndex++;
}
return currentLevel;
}
void EnvelopeGenerator::calculateMultiplier(double startLevel,
double endLevel,
unsigned long long lengthInSamples) {
multiplier = 1.0 + (log(endLevel) - log(startLevel)) / (lengthInSamples);
}
void EnvelopeGenerator::enterStage(EnvelopeStage newStage) {
if (currentStage == newStage) return;
if (currentStage == ENVELOPE_STAGE_OFF) {
beganEnvelopeCycle();
}
if (newStage == ENVELOPE_STAGE_OFF) {
finishedEnvelopeCycle();
}
currentStage = newStage;
currentSampleIndex = 0;
if (currentStage == ENVELOPE_STAGE_OFF ||
currentStage == ENVELOPE_STAGE_SUSTAIN) {
nextStageSampleIndex = 0;
}
else {
nextStageSampleIndex = stageValue[currentStage] * sampleRate;
}
switch (newStage) {
case ENVELOPE_STAGE_OFF:
currentLevel = 0.0;
multiplier = 1.0;
break;
case ENVELOPE_STAGE_ATTACK:
currentLevel = minimumLevel;
calculateMultiplier(currentLevel,
1.0,
nextStageSampleIndex);
break;
case ENVELOPE_STAGE_DECAY:
currentLevel = 1.0;
calculateMultiplier(currentLevel,
fmax(stageValue[ENVELOPE_STAGE_SUSTAIN], minimumLevel),
nextStageSampleIndex);
break;
case ENVELOPE_STAGE_SUSTAIN:
currentLevel = stageValue[ENVELOPE_STAGE_SUSTAIN];
multiplier = 1.0;
break;
case ENVELOPE_STAGE_RELEASE:
// We could go from ATTACK/DECAY to RELEASE,
// so we're not changing currentLevel here.
calculateMultiplier(currentLevel,
minimumLevel,
nextStageSampleIndex);
break;
default:
break;
}
}
void EnvelopeGenerator::setSampleRate(double newSampleRate) {
sampleRate = newSampleRate;
}
void EnvelopeGenerator::setStageValue(EnvelopeStage stage,
double value) {
stageValue[stage] = value;
if (stage == currentStage) {
// Re-calculate the multiplier and nextStageSampleIndex
if (currentStage == ENVELOPE_STAGE_ATTACK ||
currentStage == ENVELOPE_STAGE_DECAY ||
currentStage == ENVELOPE_STAGE_RELEASE) {
double nextLevelValue;
switch (currentStage) {
case ENVELOPE_STAGE_ATTACK:
nextLevelValue = 1.0;
break;
case ENVELOPE_STAGE_DECAY:
nextLevelValue = fmax(stageValue[ENVELOPE_STAGE_SUSTAIN], minimumLevel);
break;
case ENVELOPE_STAGE_RELEASE:
nextLevelValue = minimumLevel;
break;
default:
break;
}
// How far the generator is into the current stage:
double currentStageProcess = (currentSampleIndex + 0.0) / nextStageSampleIndex;
// How much of the current stage is left:
double remainingStageProcess = 1.0 - currentStageProcess;
unsigned long long samplesUntilNextStage = remainingStageProcess * value * sampleRate;
nextStageSampleIndex = currentSampleIndex + samplesUntilNextStage;
calculateMultiplier(currentLevel, nextLevelValue, samplesUntilNextStage);
}
else if (currentStage == ENVELOPE_STAGE_SUSTAIN) {
currentLevel = value;
}
if (currentStage == ENVELOPE_STAGE_DECAY &&
stage == ENVELOPE_STAGE_SUSTAIN) {
// We have to decay to a different sustain value than before.
// Re-calculate multiplier:
unsigned long long samplesUntilNextStage = nextStageSampleIndex - currentSampleIndex;
calculateMultiplier(currentLevel,
fmax(stageValue[ENVELOPE_STAGE_SUSTAIN], minimumLevel),
samplesUntilNextStage);
}
}
}
C++
1
https://gitee.com/blumia/PineappleSynth.git
git@gitee.com:blumia/PineappleSynth.git
blumia
PineappleSynth
PineappleSynth
master

搜索帮助