- Fixed: When note_on() is called and another copy of the same note is
already playing on the channel, it should stop it with finish_note(), not kill_note(). This can be clearly heard in the final cymbal crashes of D_DM2TTL where TiMidity cuts them off because the final cymbals are played with a velocity of 1 before the preceding cymbals have finished. (I wonder if I should be setting the self_nonexclusive flag for GUS patches to disable even this behavior, though, since gf1note.c doesn't turn off duplicate notes.) - Changed envelope handling to hopefully match the GUS player's. The most egregious mistake TiMidity makes is to treat bit 6 as an envelope enable bit. This is not what it does; every sample has an envelope. Rather, this is a "no sampled release" flag. Also, despite fiddling with the PATCH_SUSTAIN flag during instrument loading, TiMidity never actually used it. Nor did it do anything at all with the PATCH_FAST_REL flag. SVN r934 (trunk)
This commit is contained in:
parent
b129ed3948
commit
16d18c707a
8 changed files with 174 additions and 141 deletions
|
|
@ -38,35 +38,35 @@ int recompute_envelope(Voice *v)
|
|||
|
||||
stage = v->envelope_stage;
|
||||
|
||||
if (stage > RELEASEC)
|
||||
if (stage >= ENVELOPES)
|
||||
{
|
||||
/* Envelope ran out. */
|
||||
v->status = VOICE_FREE;
|
||||
/* play sampled release */
|
||||
v->status &= ~(VOICE_SUSTAINING | VOICE_LPE);
|
||||
v->status |= VOICE_RELEASING | VOICE_STOPPING;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (v->sample->modes & PATCH_NO_SRELEASE)
|
||||
if (stage == RELEASE && !(v->status & VOICE_RELEASING) && (v->sample->modes & PATCH_SUSTAIN))
|
||||
{
|
||||
if (v->status == VOICE_ON || v->status == VOICE_SUSTAINED)
|
||||
{
|
||||
if (stage > DECAY)
|
||||
{
|
||||
/* Freeze envelope until note turns off. Trumpets want this. */
|
||||
v->envelope_increment = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
v->status |= VOICE_SUSTAINING;
|
||||
/* Freeze envelope until note turns off. Trumpets want this. */
|
||||
v->envelope_increment = 0;
|
||||
}
|
||||
v->envelope_stage = stage + 1;
|
||||
else
|
||||
{
|
||||
v->envelope_stage = stage + 1;
|
||||
|
||||
if (v->envelope_volume == v->sample->envelope_offset[stage])
|
||||
{
|
||||
return recompute_envelope(v);
|
||||
if (v->envelope_volume == v->sample->envelope_offset[stage])
|
||||
{
|
||||
return recompute_envelope(v);
|
||||
}
|
||||
v->envelope_target = v->sample->envelope_offset[stage];
|
||||
v->envelope_increment = v->sample->envelope_rate[stage];
|
||||
if (v->envelope_target < v->envelope_volume)
|
||||
v->envelope_increment = -v->envelope_increment;
|
||||
}
|
||||
v->envelope_target = v->sample->envelope_offset[stage];
|
||||
v->envelope_increment = v->sample->envelope_rate[stage];
|
||||
if (v->envelope_target < v->envelope_volume)
|
||||
v->envelope_increment = -v->envelope_increment;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -78,10 +78,7 @@ void apply_envelope_to_amp(Voice *v)
|
|||
{
|
||||
env_vol *= v->tremolo_volume;
|
||||
}
|
||||
if (v->sample->modes & PATCH_NO_SRELEASE)
|
||||
{
|
||||
env_vol *= v->envelope_volume / float(1 << 30);
|
||||
}
|
||||
env_vol *= v->envelope_volume / float(1 << 30);
|
||||
// Note: The pan offsets are negative.
|
||||
v->left_mix = MAX(0.f, (float)calc_gf1_amp(env_vol + v->left_offset) * final_amp);
|
||||
v->right_mix = MAX(0.f, (float)calc_gf1_amp(env_vol + v->right_offset) * final_amp);
|
||||
|
|
@ -426,13 +423,13 @@ void mix_voice(Renderer *song, float *buf, Voice *v, int c)
|
|||
{
|
||||
return;
|
||||
}
|
||||
if (v->status == VOICE_DIE)
|
||||
if (v->status & VOICE_STOPPING)
|
||||
{
|
||||
if (count >= MAX_DIE_TIME)
|
||||
count = MAX_DIE_TIME;
|
||||
sp = resample_voice(song, v, &count);
|
||||
ramp_out(sp, buf, v, count);
|
||||
v->status = VOICE_FREE;
|
||||
v->status = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue