- 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:
Randy Heit 2008-04-24 04:18:49 +00:00
commit 16d18c707a
8 changed files with 174 additions and 141 deletions

View file

@ -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
{