mix.c: next_stage(), compute_mix_smoothing()

   Added new and corrected old volume-ramp related anti-popping measures.
   All volume ramps, whether from pans, expression/volume changes, or
   non-attack envelopes, now occur over a minimum window of 20 msec
   (incorrectly commented as 0.5 msec in previous versions).

Earlier today, I sent a bug fix for instruments with too-short release
envelopes.  In looking over some of the other envelope-related code I had
written in the past, I noticed that I had forgotten to take the
"control_ratio" variable (playback rate / samples per second) into
account.  At -s 44100 and the default 1000 controls per second,
control_ratio = 44.  Thus, all of my previous comments of 0.5 msec were
incorrect, and timidity was actually using an effective amp ramp window of
22 msec.  Worse yet, the window length (in time) would change with
different playback sampling rates.  While it was difficult to measure in
previous examples of pan-related and rapid volume-related popping, the new
release-related popping was easy to visualize and measure in a WAV editor.
What I thought was 0.5 msec in the code before was indeed 22 msec in
reality :(

I also noticed some possible problems with the envelope-related patch I
sent earlier today and fixed them.

I have attached a diff that replaces the diff I sent earlier today, and
fixes the other anti-popping measure I wrote many years ago as well.
Rather than use 22 msec, I shortened it to a nice round 20 msec.  Audibly,
the popping test midi I have sound the same as the prior incorrect
implementation.  Reducing the window to 15 msec causes definate pops, so I
think 20 msec is as short as it can reasonably go.

-Eric
*** mix.c.orig  Mon Jan 23 03:07:44 2006
--- mix.c       Sun Sep  6 18:49:40 2009
***************
*** 1628,1634 ****
  {
        int stage, ch, eg_stage;
        int32 offset, val;
!       FLOAT_T rate;
        Voice *vp = &voice[v];
  
        stage = vp->envelope_stage++;
--- 1628,1634 ----
  {
        int stage, ch, eg_stage;
        int32 offset, val;
!       FLOAT_T rate, temp_rate;
        Voice *vp = &voice[v];
  
        stage = vp->envelope_stage++;
***************
*** 1641,1646 ****
--- 1641,1660 ----
        /* there is some difference between GUS patch and Soundfont at 
envelope. */
        eg_stage = get_eg_stage(v, stage);
  
+       /* HACK -- force ramps to occur over 20 msec windows to avoid pops */
+       /* Do not apply to attack envelope */
+       if (eg_stage > EG_ATTACK)
+       {
+           temp_rate = control_ratio * (labs(vp->envelope_volume - offset) /
+                       (play_mode->rate * 0.02));
+           if (temp_rate < 1)
+               temp_rate = 1;
+           if (rate < 0)
+               temp_rate = -temp_rate;
+           if (fabs(temp_rate) < fabs(rate))
+               rate = temp_rate;
+       }
+ 
        /* envelope generator (see also playmidi.[ch]) */
        if (ISDRUMCHANNEL(ch))
                val = (channel[ch].drums[vp->note] != NULL)
***************
*** 1708,1713 ****
--- 1722,1742 ----
                } else if (rate < 1) {rate =  1;}       /* slowest attack */
        }
  
+       /* HACK -- force ramps to occur over 20 msec windows to avoid pops */
+       /* Do not apply to attack envelope */
+       /* Must check again in case the above conditions shortened it */
+       if (eg_stage > EG_ATTACK)
+       {
+           temp_rate = control_ratio * (labs(vp->envelope_volume - offset) /
+                       (play_mode->rate * 0.02));
+           if (temp_rate < 1)
+               temp_rate = 1;
+           if (rate < 0)
+               temp_rate = -temp_rate;
+           if (fabs(temp_rate) < fabs(rate))
+               rate = temp_rate;
+       }
+ 
        vp->envelope_increment = (int32)rate;
        vp->envelope_target = offset;
  
***************
*** 1845,1853 ****
  #endif
  {
        int32 max_win, delta;
!       
!       /* reduce popping -- ramp the amp over a <= 0.5 msec window */
!       max_win = play_mode->rate * 0.0005;
        delta = FROM_FINAL_VOLUME(vp->left_mix) - vp->old_left_mix;
        if (labs(delta) > max_win) {
                vp->left_mix_inc = delta / max_win;
--- 1874,1882 ----
  #endif
  {
        int32 max_win, delta;
! 
!       /* reduce popping -- ramp the amp over a 20 msec window */
!       max_win = (play_mode->rate * 0.02) / control_ratio;
        delta = FROM_FINAL_VOLUME(vp->left_mix) - vp->old_left_mix;
        if (labs(delta) > max_win) {
                vp->left_mix_inc = delta / max_win;
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Timidity-talk mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/timidity-talk

Reply via email to