Audio is not good

Here is a perl script for analyzing scheduling delays. It does no network or disk I/O (other than writing its log file). It simply asks to be awakened every 10 ms and compares the actual time it gets activated with the requested time. If it’s more than 30 ms late, that’s sufficient jitter to cause an audible glitch. It also logs ‘small’ delays (anything over 10 ms). A one-line summary is created every ten minutes. For each minute with at least one delay over 30 ms, it logs the number of delayed packets for each second (X means more than 9), so you can get an idea of how the trouble would affect the sound. Let this run in the background for an hour or more, then post the contents of the schedtime.log file that it writes. If you make calls during this time, keep a record so we can correlate that with the log.

#!/usr/bin/perl

use Time::HiRes qw( time sleep );

$smalld = 0.010;                # more delay than this is a "small" jitter
$badd = 0.030;                  # more delay than this is a "bad" jitter

open(LOG, ">schedtime.log") or die;
select((select(LOG), $|=1)[0]);
print LOG "time\tgood\tsmall\tbad\tmax\n";
$good = $small = $bad = $max = 0;
$duesec = 0;
for ($i = 0; $i < 60; ++$i) {
    $bads[$i] = 0;
}
$timedue = int((($timenow = time) + 61) / 60) * 60;
sleep($timedue - $timenow);
while (1) {
    $delay = ($timenow = time) - $timedue;
    $max = $delay if $delay > $max;
    if ($delay < $smalld) {
        ++$good;
    }
    elsif ($delay < $badd) {
        ++$small;
    }
    else {
        ++$bad;
        ++$bads[$duesec];
    }
    $timedue += 0.01;
    if (int($timedue * 100 + .5) % 100 == 0) {  # started new second
        $timedue = int($timedue + .5);          # set to exact integer
        if (++$duesec == 60) {  # started new minute
            $duesec = 0;
            for ($i = 0; $i < 60; ++$i) {
                last if $bads[$i]; # at least one bad in last minute
            }
            if ($i < 60) {      # one or more bad
                ($i, $mm, $hh) = gmtime($timedue);
                $badstr = sprintf("%02d:%02d  ", $hh, $mm);
                for ($i = 0; $i < 60; ++$i) {
                    $badstr .= $bads[$i] > 9 ? 'X' : $bads[$i];
                    $bads[$i] = 0; # reset for next minute
                }
                print LOG $badstr, "\n";
            }
            if ($timedue % 600 == 0) { # crossed 10 minute boundary
                ($i, $mm, $hh) = gmtime($timedue);
                printf(LOG "%02d:%02d\t%d\t%d\t%d\t%1.4f\n", $hh, $mm, $good, $small, $bad, $max);
                $good = $small = $bad = $max = 0;
            }
        }
    }
    sleep($timedue - $timenow) if $timedue > $timenow;
}