<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Where are we going, and what's with the handbasket? : audio</title><link>http://blogs.msdn.com/dcook/archive/tags/audio/default.aspx</link><description>Tags: audio</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Scritch, scratch</title><link>http://blogs.msdn.com/dcook/archive/2007/10/30/scritch-scratch.aspx</link><pubDate>Wed, 31 Oct 2007 08:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5794425</guid><dc:creator>dcook</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/dcook/comments/5794425.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dcook/commentrss.aspx?PostID=5794425</wfw:commentRss><description>&lt;P&gt;Steve Ball posted &lt;A class="" title="Steve Ball on glitching issues in Vista" href="http://windowsvistablog.com/blogs/windowsvista/archive/2007/10/29/an-overview-of-windows-sound-and-music-glitching-issues.aspx" mce_href="http://windowsvistablog.com/blogs/windowsvista/archive/2007/10/29/an-overview-of-windows-sound-and-music-glitching-issues.aspx"&gt;an article about&amp;nbsp;some "glitching" issues in Vista&lt;/A&gt;. I can't resist adding my two cents.&lt;/P&gt;
&lt;P&gt;For me, Vista definitely glitches a LOT more than previous versions of Windows. As a fairly experienced developer, I think I understand the reasons pretty well, so I can explain it away. But as a user, when my laptop audio is glitchy, I want to find the developer responsible and &lt;EM&gt;(censored for&amp;nbsp;mild descriptions of hypothetical violence)&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;I've read a lot of comments raising various theories, some&amp;nbsp;that call into question the&amp;nbsp;sanity of the Windows developers. I can't say I blame them. There is definitely some room for improvement in the way things work. However, in the interest of fairness and progress,&amp;nbsp;the&amp;nbsp;attention should be focused where it will do the most good. That means we shouldn't simply blame the Windows developers&amp;nbsp;unless there is really something they can do about the problem. And that means that before we start placing blame, we probably ought to figure out where the&amp;nbsp;problem really lies.&lt;/P&gt;
&lt;P&gt;The first complaints always mention something about the "lame" and "brain-dead"&amp;nbsp;Windows NT scheduler.&amp;nbsp;However, I'm pretty convinced that this is not the problem. In fact, my audio sounds BETTER when my system is under load (more on this later). I agree with the statement that audio glitches under CPU load are usually the fault of the OS and the scheduler, but I've seen very little correlation between CPU load and audio glitching. I haven't seen any evidence that the CPU scheduler at fault.&lt;/P&gt;
&lt;P&gt;Hard disk load is occasionally an issue, but that is generally fairly obvious and easy to fix at the application level. The application simply didn't buffer enough sound samples and ran out of music to play while waiting for the hard drive to load the next bit of music. Either tweak the buffering algorithm&amp;nbsp;of the application or get a faster hard drive (or network).&lt;/P&gt;
&lt;P&gt;Memory can also be an issue.&amp;nbsp;Some buffer or code needed to play the music might be paged out because you're running low on free memory, and it didn't get paged in quickly enough once the application tried to access it. This could possibly be&amp;nbsp;blamed on the OS&amp;nbsp;if the OS is too aggressive in trimming the working set. If an app pre-loads 60 seconds of audio, that means it doesn't won't touch the last page of the buffer for 60 seconds, which might be long enough for the OS to page out the buffer. Here, you would probably get better results by buffering only 5 seconds worth of music. In any case, I haven't had any&amp;nbsp;significant trouble with this on Vista (except once in a while when I let Firefox run too long, it eats up 1.5 GB of RAM,&amp;nbsp;and&amp;nbsp;my&amp;nbsp;system goes into memory panic mode).&lt;/P&gt;
&lt;P&gt;Drivers are a much more&amp;nbsp;significant issue. Traditional OSes (XP, Vista,&amp;nbsp;Linux)&amp;nbsp;can't really&amp;nbsp;schedule a driver's activity. Once the driver starts doing something it thinks is important, it can only be interrupted by a&amp;nbsp;higher-priority driver. On a single-CPU system, if a driver takes over, no new audio can be buffered until the driver returns. Many drivers written for XP or earlier systems (where the audio buffer was somewhat more forgiving -- more on this later) cause trouble by doing too much processing at once.&amp;nbsp;In testing (under XP), the driver's latency wasn't a problem, but on Vista, the latency requirements are much less lenient.&amp;nbsp;I've seen significant Vista audio glitch issues go away after upgrading from an XP-era driver to a newly released Vista-compiant driver.&lt;/P&gt;
&lt;P&gt;Even if the driver only does 1 millisecond of work at a time (or whatever the Vista latency recommendations are), if it has to do this 1000 times a second, it will still&amp;nbsp;use up all available CPU time. Drivers have priority over all&amp;nbsp;applications, so on a single-CPU system, this leaves no CPU for the audio application and mixer. On a multi-CPU system, this can still be a problem if the driver holds certain locks that are needed for audio processing. This is why Vista throttles network activity when the audio channel is open -- network&amp;nbsp;packet&amp;nbsp;bursts&amp;nbsp;can easily use&amp;nbsp;enough CPU to cause audio glitches.&amp;nbsp;Probably a good idea overall, though it seems that the throttling algorithm is a bit too aggressive and has some room for improvement.&lt;/P&gt;
&lt;P&gt;Another issue is power management. This turned out to be the major problem on my laptop. My laptop's motherboard (CPU and chipset) goes into sleep mode whenever it detects that it is "idle".&amp;nbsp;That's actually a pretty good thing because it means I can get 2 or 3 hours of use out of the battery instead of 20 minutes. This happens hundreds of times per second -- it sleeps for&amp;nbsp;2 milliseconds,&amp;nbsp;wakes up to handle a keystroke, sleeps for another 2 milliseconds, wakes up to handle&amp;nbsp;the calculations for an animation,&amp;nbsp;sleeps a bit more,&amp;nbsp;wakes to fill an&amp;nbsp;audio buffer,&amp;nbsp;etc.&amp;nbsp;But it sometimes doesn't wake up quickly enough to buffer the next bit of audio. If it ever takes longer than 9 ms to wake up,&amp;nbsp;there will&amp;nbsp;be a glitch. This was a real problem when my laptop was new. Recent drivers have improved this a lot, but there's still a bit of scritch-scratch during some games or media.&lt;/P&gt;
&lt;P&gt;As an experiment, I wrote a very simple application to prevent the motherboard from going to sleep. It starts a low-priority thread that does a simple busy wait in a low priority loop. A Sleep(1) loop&amp;nbsp;didn't help -- it gave the motherboard a chance to go to sleep. While&amp;nbsp;the busy&amp;nbsp;wait&amp;nbsp;makes my laptop get very hot, it also completely stops the glitching.&lt;/P&gt;
&lt;BLOCKQUOTE style="MARGIN: 0in; FONT-FAMILY: 'Courier New', 'Courier', 'Monospace'"&gt;
&lt;P style="MARGIN: 0in"&gt;&lt;SPAN style="COLOR: blue"&gt;#include&lt;/SPAN&gt; &amp;lt;windows.h&amp;gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&lt;SPAN style="COLOR: blue"&gt;#include&lt;/SPAN&gt; &amp;lt;stdio.h&amp;gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&lt;SPAN style="COLOR: green"&gt;// This probably doesn't really do anything. At such a low priority, the&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&lt;SPAN style="COLOR: green"&gt;// process usually terminates before the thread exits. But this is an easy&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&lt;SPAN style="COLOR: green"&gt;// way to avoid&amp;nbsp;certain compiler warnings. Without it, some compilers warn&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&lt;SPAN style="COLOR: green"&gt;//&amp;nbsp;that the "return 0" below is unreachable. If I remove the "return 0",&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&lt;SPAN style="COLOR: green"&gt;// other compilers warn that I don't return a value from DoNothingQuickly.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&lt;SPAN style="COLOR: blue"&gt;volatile&lt;/SPAN&gt; BOOL g_stopNow = FALSE;&lt;/P&gt;
&lt;P style="MARGIN: 0in" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;DWORD WINAPI DoNothingQuickly(LPVOID &lt;SPAN style="COLOR: green"&gt;/* unused */&lt;/SPAN&gt;)&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;{&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;while&lt;/SPAN&gt; (!g_stopNow)&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: green"&gt;// Sleep(1) didn't fix the glitching. Sleep(0) just spends all&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: green"&gt;// the time context switching, which is probably as bad or&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: green"&gt;// worse than a busy wait in terms of impact on the rest of&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: green"&gt;//&amp;nbsp;the system. So I'll just do a busy wait.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; 0; &lt;SPAN style="COLOR: green"&gt;// Usually never reached.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;}&lt;/P&gt;
&lt;P style="MARGIN: 0in" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; main()&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;{&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; returnCode;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; DWORD dwThreadId;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; HANDLE hThread;&lt;/P&gt;
&lt;P style="MARGIN: 0in" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; hThread = CreateThread(&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL,&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0,&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; DoNothingQuickly,&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; NULL,&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; CREATE_SUSPENDED,&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;amp;dwThreadId);&lt;/P&gt;
&lt;P style="MARGIN: 0in" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (hThread != NULL)&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: green"&gt;// We want to keep one CPU wide-awake and leave any other&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&lt;SPAN style="COLOR: green"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // CPU(s)&amp;nbsp;idle.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SetThreadAffinityMask(hThread, 1);&lt;/P&gt;
&lt;P style="MARGIN: 0in" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: green"&gt;// We don't want to get in the way of any useful work.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; SetThreadPriority(hThread, THREAD_BASE_PRIORITY_IDLE);&lt;/P&gt;
&lt;P style="MARGIN: 0in" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ResumeThread(hThread);&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; CloseHandle(hThread);&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; printf("Caffeine: Now running. Press &amp;lt;Enter&amp;gt; to quit...");&lt;/P&gt;
&lt;P style="MARGIN: 0in" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; getchar();&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; g_stopNow = TRUE; &lt;SPAN style="COLOR: green"&gt;// Probably useless, but might as well...&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; returnCode = 0;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;else&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; printf("Caffeine: Unable to create thread. Exiting.\n");&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; returnCode = GetLastError();&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/P&gt;
&lt;P style="MARGIN: 0in" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; returnCode;&lt;/P&gt;
&lt;P style="MARGIN: 0in"&gt;}&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P mce_keep="true"&gt;Drivers seem to be a big part of the problem here -- they either spend too much time working, or they take too long to wake up after going into a sleep state. Hopefully this means that audio problems will go away as the drivers improve. Computer retailers like Dell and HP will probably ensure that their new hardware meets the Vista latency requirements before putting it on the market. Unfortunately, owners of older hardware might be out of luck.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Hindsight is 20/20.&amp;nbsp;I've seen how these kinds of issues come up, and I've been involved in some mistakes&amp;nbsp;myself,&amp;nbsp;so I don't want to sound like I'm smarter than anybody on the Windows audio team. However, there is certainly some room for improvement in they way this issue has played out. While the&amp;nbsp;changes in the audio stack are technically admirable and the problems can generally be blamed on drivers,&amp;nbsp;that's little comfort to those enduring static on their speakers. Things work in XP and don't work in Vista. That sounds like a regression, not an improvement. It's getting better, but there really shouldn't have been a problem in the first place.&lt;/P&gt;
&lt;P mce_keep="true"&gt;What's wrong? Well, Vista aimed for a technically superior audio experience. Latency has been significantly reduced in Vista -- when you fire your machine gun in your favorite game, you'll hear the sound effect a bit more quickly. For gamers and audio professionals, this reduction in latency&amp;nbsp;can make a big difference. For people trying to listen to their MP3s, this probably doesn't matter much.&amp;nbsp;The downside to reducing latency is that it reduces the margin for error. Vista cannot tolerate any delays longer than 5 or 10 milliseconds without glitching, while XP could usually tolerate a much longer delay with no problem. Assuming all of the drivers do their part, modern hardware actually has no problem meeting the deadlines. But if anything goes wrong on Vista, you can hear it.&lt;/P&gt;
&lt;P mce_keep="true"&gt;What was the mistake? The core of the issue is that a&amp;nbsp;change was made that was detrimental to some customers. In the long term,&amp;nbsp;the change is probably a step (or two) in the right direction, but&amp;nbsp;for many people, the change causes trouble and offers no immediate benefit. Obviously the severity of the problem was underestimated (contrary to popular belief, Windows developers &lt;EM&gt;do &lt;/EM&gt;care&amp;nbsp;about their customers and would never have&amp;nbsp;done this had they known the&amp;nbsp;outcome). I've never been a big fan of taking away without giving something in return.&lt;/P&gt;
&lt;P mce_keep="true"&gt;What would have prevented the problem? I don't know how hard this would have been to implement, but I would love to&amp;nbsp;have some kind of adjustment knob to control the amount of latency I want on my system. That would have sidestepped the whole issue by allowing&amp;nbsp;the customer to&amp;nbsp;pick their priorities, i.e.&amp;nbsp;lower latency on my desktop where there aren't power issues and where I want my games to sound great, higher latency on my laptop where I want additional power savings, the drivers aren't as good (and are also optimized for power savings), and where I'm never using the audio stack for anything other than music or videos anyway. This would also have been a great mitigation for driver issues during&amp;nbsp;the transition period.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;This is probably a good lesson for developers in general -- be sure to consider the transition period between the old system and the new system when designing the new system.&lt;/P&gt;
&lt;P mce_keep="true"&gt;In the meantime, I've finally gotten my audio problems worked out. After the latest motherboard chipset upgrade,&amp;nbsp;I no longer have to run caffeine.exe anymore, and I only run into minor static when running a few specific programs. Hopefully things are improving for everybody else, too.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5794425" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dcook/archive/tags/vista/default.aspx">vista</category><category domain="http://blogs.msdn.com/dcook/archive/tags/audio/default.aspx">audio</category><category domain="http://blogs.msdn.com/dcook/archive/tags/drivers/default.aspx">drivers</category><category domain="http://blogs.msdn.com/dcook/archive/tags/software+engineering/default.aspx">software engineering</category><category domain="http://blogs.msdn.com/dcook/archive/tags/glitches/default.aspx">glitches</category></item></channel></rss>