为什么这个音频包络不能通过开关的情况?



我正在修改这里发布的一个简单的音频信封。发布的版本运行开关的简单指数攻击、衰减、维持和释放情况,并根据每个阶段的预期样本长度持续时间通过包络。

对于每种情况,我都需要更复杂、更个性化的方程式。我可以根据我的方程计算每个病例的预测长度,并保持这种基于时间的方法。然而,我认为通过基于振幅截止的案例来控制进展会更容易。即,如果等级>=1.0,则从攻击状态移动到衰退状态。

但我很难做到这一点,也很难弄清楚为什么它不会成功。

这是相关的原始代码:

enum EnvelopeStage {
ENVELOPE_STAGE_OFF = 0,
ENVELOPE_STAGE_ATTACK,
ENVELOPE_STAGE_DECAY,
ENVELOPE_STAGE_SUSTAIN,
ENVELOPE_STAGE_RELEASE,
kNumEnvelopeStages
};
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) {
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;
}
}

因此,病例的进展由double EnvelopeGenerator::nextSample()控制。

以下是我试图做的事情,以不同的方式控制它:

double EnvelopeGenerator::nextSample() {
if (currentStage = ENVELOPE_STAGE_ATTACK) {
currentLevel = pow(currentSampleIndex / 30000.0f, 2.0f);
currentSampleIndex++;
if (currentLevel >= 1.0) {
enterStage(ENVELOPE_STAGE_DECAY);
}
}
else if (currentStage = ENVELOPE_STAGE_DECAY) {
currentLevel = 1/ pow((currentSampleIndex / 30000.0f)+1, 2.0f);
currentSampleIndex++;
if (currentLevel = 0.1) {
enterStage(ENVELOPE_STAGE_RELEASE);
}   
}
else if (currentStage = ENVELOPE_STAGE_RELEASE) {
currentLevel = currentLevel = 1 / pow((currentSampleIndex / 30000.0f) + 1, 2.0f);
currentSampleIndex++;
if (currentLevel = 0.0001) {
enterStage(ENVELOPE_STAGE_OFF);
}
}
else {}

这些并不是我对每种情况所需要的最终方程式。它们只是简单的测试方程式。但目前对于nextSample函数来说,这只是一个无限期的循环攻击阶段。

我不明白为什么它在攻击时会无限循环。我想我已经明确表示,如果级别达到1.0,它应该切换到衰减情况。

我做错了什么?我该如何解决?我没有足够的C++经验,不知道如何正确地做到这一点。

您在if语句中使用了一个=,这是一个赋值。要进行比较,您需要使用==

if (currentStage == ENVELOPE_STAGE_ATTACK)

最新更新