<?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>Windows CE Multimedia Team Blog</title><link>http://blogs.msdn.com/medmedia/default.aspx</link><description>Multimedia, Graphics, and Audio for Windows CE, Windows Mobile, and their partner products. </description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Always think in terms of the current screen orientation</title><link>http://blogs.msdn.com/medmedia/archive/2008/07/08/Always-think-in-terms-of-the-current-screen-orientation.aspx</link><pubDate>Tue, 08 Jul 2008 07:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8706267</guid><dc:creator>yoshihito</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/8706267.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=8706267</wfw:commentRss><description>&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;Today I am going to write a short &lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'MS Mincho'; mso-fareast-theme-font: minor-fareast; mso-ansi-language: EN-US; mso-fareast-language: JA; mso-bidi-language: AR-SA"&gt;development &lt;/SPAN&gt;note on a GPE-based display driver for Windows CE as we noticed that this stuff is not clearly documented online and have confused many people including those who are writing display drivers for new platforms at MS. Hopefully this entry might save a few strands of hairs of some people out there somewhere.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;The topic is about the screen resolutions and orientations supported by the display driver. It is really a simple thing, but there are a set of rules that driver writers must know to get it right. When it is not correctly followed, your device might still boot, but you may start noticing weird glitches here and there.&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;A GPE-based display driver has to override a function called GetModeInfo() which is a pure virtual function defined by the GPE base class. What it does is very simple; It just returns the screen resolution (and some extra information such as bit depth) supported by the device at the given index. It is used in a combination with NumModes() which gives the number of modes that the GetModeInfo() supports. What is important here is that&amp;nbsp;the display driver framework requires that the GetModeInfo() returns the screen resolution relative to the current screen orientation. Not the native screen orientation. Not the boot-time screen orientation. It is always the current screen orientation.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The screen can take four possible orientations; 0 degree, 90 degrees, 180 degrees, and 270 degrees. Unless you are only dealing with square displays, then depending on the angle, the width and height have to be swapped. For example, if your screen resolution is 800 x 600 at the 0 degree and that is how your GetModeInfo() reports, then it has to return 600 x 800 when the&amp;nbsp;current orientation is at 90 or 270 degrees. Many GWES components that&amp;nbsp;deal with screen resolutions and orientations are dependent upon this behavior, but this doesn't&amp;nbsp;become a problem until you actually try to rotate the screen. So, initially it may look like it is working perfectly, but once you try to rotate it, then you start seeing some&amp;nbsp;issues.&lt;/P&gt;
&lt;P mce_keep="true"&gt;As far as I can think of off the top of my head, most APIs (if not all) that deal with resolutions such as ChangeDisplaySettingsEx() and SetDisplayMode() all expect&amp;nbsp;resolution parameters to be relative to the current screen orientation. So, the rule of the thumb&amp;nbsp;appears to be this:&amp;nbsp;Always think in terms of the current screen orientation.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8706267" width="1" height="1"&gt;</description></item><item><title>Keeping your module section count below 16 on Windows CE</title><link>http://blogs.msdn.com/medmedia/archive/2008/02/22/keeping-your-module-section-count-below-16-and-understanding-why-this-is-important.aspx</link><pubDate>Sat, 23 Feb 2008 04:13:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7852841</guid><dc:creator>Andy Raffman</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/7852841.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=7852841</wfw:commentRss><description>&lt;P&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;Here's a quick blog about an issue that we just hit today; most will merely find it interesting, but I hope it saves someone somewhere a little time, effort, and confusion.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;We recently got a new codec library drop which we integrated into our mainline code tree. The codec team spends alot of time developing optimized ARM-versions of windows media&amp;nbsp;codecs, and every once in&amp;nbsp;awhile we get a new library&amp;nbsp;that we need to integrate into our build system.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;When we checked the libary into our source tree&amp;nbsp;and ran a Smartphone build, we got roughly this error from one of our build tools:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wmvdmod.dll(0) : fatal error RM0024 : Input File has more than 16 sections&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;In the ensuing investigation we discovered two things we hadn't previously known:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;1. Our codec team has been subdividing their C/C++/Assembly language routines into multiple sections to keep certain code paths together and improve cache/page hit rates. As a result, they had created about 14 extra sections with names like ".decodeX_Pass1" (names changed to protect the innocent ;-). In general, one can view this type of information for any lib or dll by running "dumpbin -headers" on it.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;2. Windows CE has some limitations on the number of sections that a module can contain (due to design decisions in the kernel and ROM image filesystems).&amp;nbsp;Ultimately this results in a limit of 16 sections for some scenarios, which is the case we hit in our build tools.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;The simplest short-term solution to this problem was to use the merge linker directive to force the linker to merge the different sections in the library back into the .text section. To accomplish this, we added something like the following to the appropriate sources file. This solved the build error without the need to rebuild the library (at the expense of removing all the goodness of using multiple sections to control code placement). &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;LDEFINES=$(LDEFINES) \&lt;BR&gt;&amp;nbsp;-merge:.decodeX_Pass1=.text \&lt;BR&gt;&amp;nbsp;-merge:.decodeX_Pass2=.text \&lt;BR&gt;&amp;nbsp;-merge:.decodeY_Pass1=.text \&lt;BR&gt;&amp;nbsp;-merge:.decodeY_Pass2=.text \&lt;BR&gt;...&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;Note: I'm told one can accomplish the same feature within c/cpp files using #pragma comment(linker,"-merge:.foo=.bar")&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;In the ensuing discussion of how to fix this in the correct way (e.g. removing the restriction on the number of sections, or using fewer sections in the codec lib), our compiler/linker guru came down firmly on the side that there's no reason to need more than 16 sections (or really more than four or five), and noted th&lt;FONT color=#000000&gt;at this whole situation could have been easily avoided using the following techniques:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 11pt; COLOR: #1f497d; FONT-FAMILY: 'Calibri','sans-serif'"&gt;&lt;FONT color=#000000&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT size=2&gt;For performance, if you want page alignment, use __declspec(align).&amp;nbsp; If you need to control code layout, use the linker’s /ORDER switch with a file containing the symbol ordering you need.&amp;nbsp; Alternatively, use the linker’s automatic sorting of section suffixes, e.g. .text$FOO_A, .text$FOO_B, and .text$FOO_C are automatically merged with .text in alphabetical order.&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 11pt; COLOR: #1f497d; FONT-FAMILY: 'Calibri','sans-serif'"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=2&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;We didn't previously know about the linker options to automatically sort and merge sections using the $ delimiter, and I suspect that most other people don't either. We'll now go back to the codec team and suggest that future drops can just use the automatic sorting mechanism to ensure that code is grouped as needed while keeping all the code in the .text section. As a nice side benefit, grouping code into the same section saves on the amount of ROM required for the code. Each section must start on a 4k boundary, so on average each section will waste 2k or ROM. Note that section names are case sensitive, so .TEXT is not the same as .text.&amp;nbsp;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;Here are some other related details about sections which I've shamelessly stolen from some other developers here at MS:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=arial,helvetica,sans-serif color=#0000cc&gt;&lt;STRONG&gt;Paging:&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;Code may be paged into a size-limited RAM buffer called a "page pool". The page pool helps limit the RAM impact of code by keeping resident only the code pages currently in use.&amp;nbsp;Code that must always stay resident in RAM can be marked as non-pageable, but this will cause the full extent of that code section to be copied into RAM for as long as the module is loaded.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;To limit the footprint of a module in the page pool, it’s best to group the functions and constant data that are in the working set together.&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;This will allow the working set of code to exist in the page pool in the smallest number of pages. You can group them together using custom section naming. If section names are unique they will each be page-aligned (4k), so unless they truly need unique attributes, it’s best to name them such that automatic section merging can take place. Automatic section merging happens on sections named using a “section_name$subsection_name” convention, such that they all merge into one section named “section_name”.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;For readability, give the subsection a name related to the grouping reason, such as “initialization”, “debug”, or “core”. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#4f81bd size=2&gt;Example&lt;/FONT&gt;&lt;/H2&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;To group function1 and function3 together in a custom subsection, you can do the following.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 1pt; MARGIN-LEFT: 0.5in; BORDER-LEFT: windowtext 1pt solid; MARGIN-RIGHT: 0in; PADDING-TOP: 1pt; BORDER-BOTTOM: windowtext 1pt solid; mso-element: para-border-div"&gt;
&lt;P class=MsoNormal style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0in; BORDER-TOP: medium none; PADDING-LEFT: 0in; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 0in; MARGIN: 0in 0in 0pt; BORDER-LEFT: medium none; PADDING-TOP: 0in; BORDER-BOTTOM: medium none"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT size=2&gt;&lt;SPAN style="FONT-SIZE: 8pt; BACKGROUND: yellow; FONT-FAMILY: Consolas"&gt;#pragma code_seg(".text$initialization")&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Consolas"&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;// Code that follows goes into named subsection&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0in; BORDER-TOP: medium none; PADDING-LEFT: 0in; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 0in; MARGIN: 0in 0in 0pt; BORDER-LEFT: medium none; PADDING-TOP: 0in; BORDER-BOTTOM: medium none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Consolas"&gt;&lt;FONT face=arial,helvetica,sans-serif size=2&gt;void function1(void)&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;{return;}&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0in; BORDER-TOP: medium none; PADDING-LEFT: 0in; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 0in; MARGIN: 0in 0in 0pt; BORDER-LEFT: medium none; PADDING-TOP: 0in; BORDER-BOTTOM: medium none"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT size=2&gt;&lt;SPAN style="FONT-SIZE: 8pt; BACKGROUND: lime; FONT-FAMILY: Consolas"&gt;#pragma code_seg()&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Consolas"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;// Code that follows goes into default .text section&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0in; BORDER-TOP: medium none; PADDING-LEFT: 0in; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 0in; MARGIN: 0in 0in 0pt; BORDER-LEFT: medium none; PADDING-TOP: 0in; BORDER-BOTTOM: medium none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Consolas"&gt;&lt;FONT face=arial,helvetica,sans-serif size=2&gt;void function2(void)&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;{return;}&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0in; BORDER-TOP: medium none; PADDING-LEFT: 0in; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 0in; MARGIN: 0in 0in 0pt; BORDER-LEFT: medium none; PADDING-TOP: 0in; BORDER-BOTTOM: medium none"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT size=2&gt;&lt;SPAN style="FONT-SIZE: 8pt; BACKGROUND: yellow; FONT-FAMILY: Consolas"&gt;#pragma code_seg(".text$initialization")&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Consolas"&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;// Code that follows goes into named subsection&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0in; BORDER-TOP: medium none; PADDING-LEFT: 0in; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 0in; MARGIN: 0in 0in 0pt; BORDER-LEFT: medium none; PADDING-TOP: 0in; BORDER-BOTTOM: medium none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Consolas"&gt;&lt;FONT face=arial,helvetica,sans-serif size=2&gt;void function3(void)&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;{return;}&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0in; BORDER-TOP: medium none; PADDING-LEFT: 0in; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 0in; MARGIN: 0in 0in 0pt; BORDER-LEFT: medium none; PADDING-TOP: 0in; BORDER-BOTTOM: medium none"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT size=2&gt;&lt;SPAN style="FONT-SIZE: 8pt; BACKGROUND: lime; FONT-FAMILY: Consolas"&gt;#pragma code_seg()&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Consolas"&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;// Code that follows goes into default .text section&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#4f81bd size=2&gt;Non-Pageable Sections&lt;/FONT&gt;&lt;/H2&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;If you need only a small bit of the code to stay in RAM always for performance or reliability reasons (like time-critical driver code), you can make the module &lt;I&gt;partially&lt;/I&gt; pageable by creating a completely new section with custom attributes.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;The following pragma defines a section called "NonPageableCode" which is set to non-pageable.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 1pt; MARGIN-LEFT: 0.5in; BORDER-LEFT: windowtext 1pt solid; MARGIN-RIGHT: 0in; PADDING-TOP: 1pt; BORDER-BOTTOM: windowtext 1pt solid; mso-element: para-border-div"&gt;
&lt;P class=MsoNormal style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0in; BORDER-TOP: medium none; PADDING-LEFT: 0in; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 0in; MARGIN: 0in 0in 0pt; BORDER-LEFT: medium none; PADDING-TOP: 0in; BORDER-BOTTOM: medium none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Consolas"&gt;&lt;FONT face=arial,helvetica,sans-serif size=2&gt;#pragma comment(linker, "/SECTION: NonPageableCode,ER!P")&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;There is also an newer, more readable&amp;nbsp;way of specifying the section properties which has been available since CE5:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 1pt; MARGIN-LEFT: 0.5in; BORDER-LEFT: windowtext 1pt solid; MARGIN-RIGHT: 0in; PADDING-TOP: 1pt; BORDER-BOTTOM: windowtext 1pt solid; mso-element: para-border-div"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Consolas"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT size=2&gt;&lt;FONT color=#000000&gt;#pragma &lt;/FONT&gt;&lt;SPAN style="FONT-SIZE: 11pt; COLOR: #1f497d; FONT-FAMILY: 'Calibri','sans-serif'; mso-fareast-font-family: Calibri; mso-bidi-font-family: 'Times New Roman'; mso-fareast-theme-font: minor-latin; mso-ansi-language: EN-US; mso-fareast-language: EN-US; mso-bidi-language: AR-SA"&gt;&lt;FONT color=#000000&gt;section("NonPageableCode", execute, read, nopage)&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;Now, in the source code, to make a section of code non-pageable, put the following line before the code:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 1pt; MARGIN-LEFT: 0.5in; BORDER-LEFT: windowtext 1pt solid; MARGIN-RIGHT: 0in; PADDING-TOP: 1pt; BORDER-BOTTOM: windowtext 1pt solid; mso-element: para-border-div"&gt;
&lt;P class=MsoNormal style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0in; BORDER-TOP: medium none; PADDING-LEFT: 0in; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 0in; MARGIN: 0in 0in 0pt; BORDER-LEFT: medium none; PADDING-TOP: 0in; BORDER-BOTTOM: medium none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Consolas"&gt;&lt;FONT face=arial,helvetica,sans-serif size=2&gt;#pragma code_seg("NonPageableCode")&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;Afterward, you may use the following line to force following code to be placed back in the default .text section:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;DIV style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 1pt; MARGIN-LEFT: 0.5in; BORDER-LEFT: windowtext 1pt solid; MARGIN-RIGHT: 0in; PADDING-TOP: 1pt; BORDER-BOTTOM: windowtext 1pt solid; mso-element: para-border-div"&gt;
&lt;P class=MsoNormal style="BORDER-RIGHT: medium none; PADDING-RIGHT: 0in; BORDER-TOP: medium none; PADDING-LEFT: 0in; BACKGROUND: #f2f2f2; PADDING-BOTTOM: 0in; MARGIN: 0in 0in 0pt; BORDER-LEFT: medium none; PADDING-TOP: 0in; BORDER-BOTTOM: medium none"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Consolas"&gt;&lt;FONT face=arial,helvetica,sans-serif size=2&gt;#pragma code_seg()&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#4f81bd size=2&gt;Tools&lt;/FONT&gt;&lt;/H2&gt;
&lt;P class=MsoListParagraph style="BACKGROUND: white; MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in"&gt;&lt;SPAN style="FONT-FAMILY: Consolas"&gt;&lt;A href="http://support.microsoft.com/kb/177429" mce_href="http://support.microsoft.com/kb/177429"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;DUMPBIN&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&amp;nbsp;/HEADERS FOO.DLL (to see what sections exist in the module)&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 11pt; COLOR: #1f497d; FONT-FAMILY: 'Calibri','sans-serif'"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 11pt; COLOR: #1f497d; FONT-FAMILY: 'Calibri','sans-serif'"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=2&gt;That's it for now.&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 11pt; COLOR: #1f497d; FONT-FAMILY: 'Calibri','sans-serif'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7852841" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Andy+Raffman/default.aspx">Author: Andy Raffman</category></item><item><title>DLL Forwarders in Windows CE</title><link>http://blogs.msdn.com/medmedia/archive/2008/01/29/dll-forwarders-in-windows-ce.aspx</link><pubDate>Tue, 29 Jan 2008 20:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7310314</guid><dc:creator>Andy Raffman</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/7310314.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=7310314</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;I haven't seen this information&amp;nbsp;consolidated online, so here it is:&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;A DLL Forwarder is used&amp;nbsp;if you want to export an entry point from one DLL (or,&amp;nbsp;more likely, for historical purposes you've already exported it from&amp;nbsp;one dll), but you want to actually implement it in a different DLL.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;For example, suppose you want to implement a function Foo() in a DLL I'll call impl.dll, but for whatever reason you need to export it from a DLL I'll call export.dll. Of&amp;nbsp;course, one simple solution is to&amp;nbsp;add code to export.dll to explicitly call into impl.dll. However, there are a couple of issues with this:&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;-&amp;nbsp;There's an additional&amp;nbsp;function call/return&amp;nbsp;overhead.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;- If the functions exported from the two DLLs have the same name, you might have some trouble convincing the linker to call the the Foo() in impl.dll from the Foo() in export.dll.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;A forwarder solves this problem by directly interacting with the loader to forward exports from one DLL to another DLL without actually adding anything to the code path.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;Forwarders are implemented in the .def file of the DLL you're forwarding through, and have the following syntax:&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&lt;FONT face=verdana,geneva&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT face=verdana,geneva&gt;EXPORTS&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT face=verdana,geneva&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;A href="mailto:SHIM_ORD_1861=COREDLX.@1861" mce_href="mailto:SHIM_ORD_1861=COREDLX.@1861"&gt;&lt;SPAN style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"&gt;&lt;FONT face=verdana,geneva&gt;&amp;lt;&lt;STRONG&gt;FuncName&lt;/STRONG&gt;&amp;gt;=&amp;lt;&lt;STRONG&gt;ForwardedDll&lt;/STRONG&gt;&amp;gt;.&amp;lt;&lt;STRONG&gt;ForwardedFuncName&lt;/STRONG&gt;&amp;gt;|#&amp;lt;&lt;STRONG&gt;ForwardedOrdinal&lt;/STRONG&gt;&amp;gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/A&gt;&lt;FONT face=verdana,geneva&gt; @&amp;lt;&lt;STRONG&gt;FuncOrdinal&lt;/STRONG&gt;&amp;gt; NONAME&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;FONT face=verdana,geneva&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT face=verdana,geneva&gt;Where:&lt;/FONT&gt;&lt;/SPAN&gt;&lt;o:p&gt;&lt;FONT face=verdana,geneva&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=verdana,geneva&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&amp;lt;FuncName&amp;gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt; is the name of the function as exported (e.g. from export.dll).&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=verdana,geneva&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;@&amp;lt;FuncOrdinal&amp;gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt; is the ordinal of the function as exported (e.g. from export.dll). Note the use of the '@' symbol. Optional.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/B&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=verdana,geneva&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&amp;lt;ForwardedDll&amp;gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt; is the name of the DLL into which you're forwarding the call (e.g. into impl.dll).&amp;nbsp;Optional; if not specified, the forwarded function is assumed to be in this dll.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;FONT face=verdana,geneva&gt;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=verdana,geneva&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&amp;lt;ForwardedFuncName&amp;gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt; is the name of the function in the ForwardedDll.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=verdana,geneva&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;#&amp;lt;ForwardedOrdinal&amp;gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt; is the ordinal of the function in the ForwardedDll. Note the use of the '#' symbol.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=verdana,geneva&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;&lt;FONT face=verdana,geneva&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=verdana,geneva&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;NONAME&lt;/SPAN&gt;&lt;/B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&amp;nbsp;is the keyword that causes the linker to throw away the name of the function you're exporting so that it can only be referenced by its ordinal. This saves some space in the DLL and forces all callers to use the ordinal to link or GetProcAddress on the function. Optional.&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;FONT face=verdana,geneva&gt;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;Note: You need to specify the forwarded function name or ordinal (not both). You'll get slightly better load perf and smaller code size by specifying the ordinal. The ordinal is also necessary if the function in the DLL you're forwarding to is specified as NONAME in its def file.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;FONT face=verdana,geneva&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;Using our example, to forward Foo() from export.dll to impl.dll, the export.def file would have a line that looks like this:&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;EXPORTS&amp;nbsp;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=verdana,geneva&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Foo = impl.Foo&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=Verdana&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=Verdana&gt;If you run "dumpbin /exports" against export.dll, you should see an entry for showing the forward that looks something like this:&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=Verdana&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="courier new,courier"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ordinal&amp;nbsp; hint &amp;nbsp; RVA&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; name&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; nnnn&amp;nbsp;&amp;nbsp;&amp;nbsp; mm&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Foo (forwarded to Impl.Foo)&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=verdana,geneva&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;o:p&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="COLOR: #1f497d"&gt;&lt;FONT color=#000000&gt;&lt;FONT face=verdana,geneva&gt;Tricky detail 1: When linking export.dll, the linker needs to figure out that the function you're exporting is a "C" style function, which it would normally do by looking at the function signature in the code implementation of the function. I've found that the easiest way to work around this is to implement a code stub that is linked into export.dll so it can get the right name in the export.lib file (e.g. decorated/undecorated).&amp;nbsp;The actual code is thrown away at link time, so it doesn't contribute to the size of the Dll. For example, one would need to implement&amp;nbsp;the following and link it into export.dll to make the linker happy. &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="COLOR: #1f497d"&gt;&lt;o:p&gt;&lt;FONT face=verdana,geneva color=#000000&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="COLOR: #1f497d"&gt;&lt;FONT color=#000000&gt;&lt;FONT face=verdana,geneva&gt;#define FORWARD(fn) extern "C" void fn(){}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN style="COLOR: #1f497d"&gt;&lt;FONT face=verdana,geneva color=#000000&gt;FORWARD(Foo)&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="COLOR: #1f497d"&gt;&lt;o:p&gt;&lt;FONT face=verdana,geneva color=#000000&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="COLOR: #1f497d"&gt;&lt;o:p&gt;&lt;FONT color=#000000&gt;&lt;FONT color=#000000&gt;&lt;FONT face=verdana,geneva&gt;Tricky detail 2: I've run into&amp;nbsp;one issue with ROMIMAGE:&amp;nbsp;if&amp;nbsp;export.dll is in the modules section of the .bib file, but impl.dll is in the files section, ROMIMAGE will generate an error when it tries to resolve the import at makeimg time. This will likely be fixed in the future, but for now it's just something that needs to be avoided.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="COLOR: #1f497d"&gt;&lt;o:p&gt;&lt;FONT color=#000000&gt;&lt;FONT face=verdana,geneva&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/o:p&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Tricky detail 3:&amp;nbsp;Forwarders&amp;nbsp;are used at load time to forward references between DLLs. The linker will not use forwarders at link time to resolve&amp;nbsp;links within your DLL. Therefore, if the DLL you're forwarding from includes&amp;nbsp;code with references to the function you're forwarding, the link phase of you DLL will fail with an unresolved extern error.&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;Tricky example: &lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;If you want to&amp;nbsp;export it a&amp;nbsp;function at&amp;nbsp;ordinal 1000 (and not export it by name), and want to forward it to&amp;nbsp; DLL&amp;nbsp;which&amp;nbsp;exports it at ordinal&amp;nbsp;2000 (without a name), the syntax in your .def file is:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;EXPORTS&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;A href="mailto:SHIM_ORD_1000=IMPL.@2000"&gt;&lt;SPAN style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"&gt;SHIM_ORD_1000=IMPL.@2000&lt;/SPAN&gt;&lt;/A&gt; @1000 NONAME&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;The SHIM_ORD_1000 is an &lt;EM&gt;arbitrary name&lt;/EM&gt;; it's only there to satisfy the&amp;nbsp;def file syntax rules. It&amp;nbsp;doesn't really matter what you call it as long as it doesn't alias to anther function exported in your .def. If you then run dumpbin /exports on the resulting dll, you'll see something like:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1000 [NONAME] (forwarded to &lt;A href="mailto:IMPL.@2000"&gt;&lt;SPAN style="COLOR: windowtext; TEXT-DECORATION: none; text-underline: none"&gt;IMPL.@2000&lt;/SPAN&gt;&lt;/A&gt;)&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7310314" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Andy+Raffman/default.aspx">Author: Andy Raffman</category></item><item><title>More about A/V synchronization in DShow</title><link>http://blogs.msdn.com/medmedia/archive/2007/10/02/more-about-a-v-synchronization-in-dshow.aspx</link><pubDate>Wed, 03 Oct 2007 00:47:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5266757</guid><dc:creator>luciad</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/5266757.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=5266757</wfw:commentRss><description>&lt;P&gt;In our previous entry, we talked about how video is synchronized to audio. In this short entry, we will talk&amp;nbsp;about&amp;nbsp;time stamps, master clocks, how adjustments to the master clock are made and&amp;nbsp;how to deal with live streams.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;About Reference Clocks and Stream Time&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;All fiters in a filter graph are synchronized to the same clock, the reference clock. The stream time is based off the reference time, but it is relative, and depends on which state the graph is. For instance, stream time doesn't move when the graph is paused; stream time goes back to 0 after a seek.&lt;/P&gt;
&lt;P&gt;DirectShow provides a base class CBaseReferenceClock that implements the IReferenceClock interface.&amp;nbsp;The base class clock object maintains two &lt;EM&gt;times &lt;/EM&gt;internally:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;internal private time&lt;/LI&gt;
&lt;LI&gt;reference time&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The internal private time is the actual time kept by the clock, and can be accessed through GetPrivateTime(). The internal private time can go backwards for brief periods of time. The reference time is based off the private time, and cannot go backwards.&lt;/P&gt;
&lt;P&gt;Whenever a filter provides the reference clock, it will usually inherit from CBaseReferenceClock. It can either override the GetPrivateTime() function to return directly the time from the device (if available), or it can issue adjustments to the stream time through the SetTimeDelta() function.&amp;nbsp;If it chooses the second method, it will need to monitor the difference between the system time and the time provided by the device.&lt;/P&gt;
&lt;P&gt;The default reference clock in WindowsCE is provided by our audio renderer. It uses the SetTimeDelta() method to issue adjustments to the stream time. To change the reference clock in a filter graph, the interface IMediaFilter needs to be queried from the filter graph. Then use SetSyncSource() to change the reference clock.&lt;/P&gt;
&lt;P&gt;All filters can access both the reference time and the stream time. The base filter class CBaseFilter has a m_pClock member. The reference time can be accessed by doing m_pClock-&amp;gt;GetTime(), and the stream time is a member function of CBaseFilter, StreamTime().&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;About Time Stamps &amp;amp; Stream Time&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The samples&amp;nbsp;being processed in the filter graph may or may not have a time stamp, which is the media sample start and finish time. The time stamps are used in conjuction with the stream time. If a sample has a time stamp that is&amp;nbsp;greater than the current stream time, it means that the sample is &lt;EM&gt;early&lt;/EM&gt;. If a sample has a time stamp that is&amp;nbsp;smaller than the current stream time, it is &lt;EM&gt;late&lt;/EM&gt;. In a playback scenario, usually&amp;nbsp;a splitter is the one that attaches time stamps to the samples. Filters may use time stamps for different reasons. For instance, time stamps may be used for presentation purposes, or to control the amount of buffering. The video renderer will use time stamps to schedule the samples for presentation, and thus, will end up throttling the video playback pipeline. When a sample arrives at the video renderer, there are several possibilities:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;no timestamp - sample is scheduled immediately&lt;/LI&gt;
&lt;LI&gt;in the future&amp;nbsp;(timestamp&amp;nbsp;&amp;gt; stream time)&amp;nbsp;- video renderer needs to schedule the sample, and will usually call m_pClock-&amp;gt;AdviseTime()&lt;/LI&gt;
&lt;LI&gt;in the past&amp;nbsp;(timestamp&amp;nbsp;&amp;lt; stream time) - may render immediately, or not render at all.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;STRONG&gt;The&amp;nbsp;Reference Clock &amp;amp; The Audio Renderer&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Let's assume in this section that the default Windows CE audio renderer is the reference clock. The audio renderer uses time stamps and stream time in a different way. Being the&amp;nbsp;reference clock implies that the stream time is controlled by this component, so it will not follow a behavior similar to the video renderer. &lt;/P&gt;
&lt;P&gt;In this case, as soon as the audio renderer receives a sample, it is ready to send it out to the audio driver. If the sample is late, it will drop it. Otherwise,&amp;nbsp;it will send&amp;nbsp;them immediately if there's buffer availability from the audio driver. It will never wait for the time to be &lt;EM&gt;right&lt;/EM&gt;. For cases where the media sample times are not contiguous, that is, the end time of a sample is smaller than the start time of the next sample, then the audio renderer will write silence to the driver, and will wait until the start time for the second sample has arrived. In the normal scenario, there is going to be no space between media samples, so the audio renderer will write samples as fast as it can.&lt;/P&gt;
&lt;P&gt;When the default audio renderer has finished processing a sample, it will read the device clock and the system clock, and compute the difference between them. Unfortunately, there is no way to get to the device clock directly, so the audio renderer uses the &lt;FONT size=2&gt;amsndOutGetPosition(), which can be imprecise.&amp;nbsp;The audio renderer will accumulate differences, and will use a low pass filter on these differences. Whenever the average difference has gone above a certain threshold, then it will issue an adjustment to the stream time, through the usage of the SetTimeDelta() function. As soon as it does that, all filters calling GetTime() will receive the adjusted time - so the stream time will not be continuous. Note that all other filters that used m_pClock-&amp;gt;AdviseTime() to get notified when a certain stream time has arrived (such as the video renderer) will not have to know of the stream time "change" that happened because of an adjustment. They will be advised when the stream time reached the desired value.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;Live Sources &amp;amp; Clock Slaving&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;If the default Windows CE audio renderer is not the&amp;nbsp;reference clock, it will write samples as it receives them. There's no automatic slave mode in WindowsCE, so the audio renderer will not wait for the time to be right before it sends the next sample.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;For the case of live streams, there is one interface in our audio renderer that causes a speed up or slow down in the audio driver so that we try to match against the live source. The source filter will usually be using the IAudioRenderer-&amp;gt;SetDriftRate() to control the audio matching speed. In this case, the audio renderer continues to be the master clock.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Another possibility when the audio renderer can't be the master clock is to simulate a &lt;EM&gt;slaving&lt;/EM&gt; mode by&amp;nbsp;inserting a filter in front of the audio renderer. This filter's responsibility would be to throttle the samples, so that they will be delivered just when it is &lt;EM&gt;almost&lt;/EM&gt; time to send them to the audio driver. Of course, more complicated schemes are possible to try to match the rate of the incoming samples, but we will not go there here...&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5266757" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/medmedia/archive/tags/DShow/default.aspx">DShow</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Lucia+Darsa/default.aspx">Author: Lucia Darsa</category></item><item><title>Wavedev2 Porting Guide</title><link>http://blogs.msdn.com/medmedia/archive/2007/09/19/wavedev2-porting-guide.aspx</link><pubDate>Thu, 20 Sep 2007 04:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5003691</guid><dc:creator>Andy Raffman</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/5003691.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=5003691</wfw:commentRss><description>&lt;P style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=5&gt;Foreword&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;I've been working on a wavedev2 porting guide over the last few weeks and decided that it's better to post what I've go so far rather than wait&amp;nbsp;until&amp;nbsp;it's what I would consider finished.&amp;nbsp;Expect future updates/additions as time allows, and feel free to ask&amp;nbsp;for specific information in the comments.&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=5&gt;Overview&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;This whitepaper gives an overview of porting the wavedev2 audio driver to new hardware. For additional background on the history and features of wavedev2, please refer to other articles on &lt;/FONT&gt;&lt;A href="http://blogs.msdn.com/medmedia" mce_href="http://blogs.msdn.com/medmedia"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;http://blogs.msdn.com/medmedia&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;.&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;
&lt;P style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT size=5&gt;Different Versions&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;Like most software, each release of Windows CE includes new features and bug fixes. For this article I’ll be referring to the version of wavedev2 which shipped with Windows CE 6 (AKA Yamazaki) under public\COMMON\oak\drivers\wavedev\wavedev2\ensoniq. This version is backward compatible with previous versions and the porting process is comparable. I’ve included some notes on the differences between Windows CE 6 and previous implementations at the end.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&lt;FONT size=5&gt;File Layout&lt;/FONT&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;All the files needed to build wavedev2 are in a single directory. For porting purposes, these files can be grouped into the following categories:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraph style="MARGIN: 0in 0in 10pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l1 level1 lfo1"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;1.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Files which are device independent, and which you should not need to touch during the porting process beyond just copying them:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;audiosys.h: Proprietary wave message definitions used by wavedev2.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;devctxt.cpp: Implementation of device context class.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;devctxt.h: Definition of device context class.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;input.cpp: Implementation of audio input streams.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;makefile: Used by build system&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;midinote.cpp: Implementation of tone generator.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;midistrm.cpp: Implementation of MIDI stream and MIDI parser.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;midistrm.h: Definition of MIDI note and stream classes.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;mixerdrv.cpp: Implementation of Mixer API classes (* may need to change if you want to take advantages of mixer API extensions).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;mixerdrv.h: Definition of MIXER API classes.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;output.cpp: Implementation of audio output streams.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;strmctxt.cpp: Implementation of base audio stream class.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;strmctxt.h: Definition of base, input, output stream classes.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;wavemain.cpp: Device driver interface.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;wavemain.h: Common include header used by all source files.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;wavepdd.h: Basic PCM sample definitions.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;wfmtmidi.h: MIDI structure definitions.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l1 level1 lfo1; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;2.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Files which are device dependent but are logically part of the wavedev2 driver infrastructure. These files will need to be copied and modified during the port. These files are:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 0pt 0.5in; mso-add-space: auto"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;hwctxt.cpp: Implementation of hardware context class.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;hwctxt.h: Definition of hardware context class.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;oemsettings.h: HW-specific definitions used by hw-independent code.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;sources: Used by build system.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;wavedev2_ensoniq.def: Driver exports. Probably just need to rename.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;wavedev2_ensoniq.reg: Registry entries used to install driver.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l1 level1 lfo1; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;3.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Files which are device dependent and are not logically part of the driver infrastructure. You can ignore these files in your port (unless they happen to be appropriate to your hardware). For the Ensoniq sample driver, these are:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 0pt 1in; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;AC97.H: AC97 codec-specific definitions.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;Es1371.cpp: Ensoniq 1371-specific functions.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;Es1371.h: Ensoniq 1371-specific header.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;Hw_ac97.cpp: AC97 codec-specific functions.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;In the above list, note that the vast majority of files shouldn’t need to be touched, and there is really only one source file and two headers you will need to modify to bring up a driver. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif size=5&gt;Class Descriptions&lt;/FONT&gt;&lt;/P&gt;
&lt;H1 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=4&gt;Class Overview&lt;/FONT&gt;&lt;/H1&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;The wavedev2 driver largely consists of three main base classes:&lt;/FONT&gt;&lt;/P&gt;
&lt;H2 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=4&gt;HardwareContext&lt;/FONT&gt;&lt;/H2&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;This class represents the actual audio hardware. This is the only class you will typically need to modify to port the driver. It is the only device dependent class, and takes care of hardware initialization, power management, DMA and Codec control, handling audio interrupts, and any other proprietary features the driver may implement. There is one instantiated HardwareContext object in the driver which is pointed to by the g_pHWContext global variable. I’ll go into detail about each HardwareContext’s methods later.&lt;/FONT&gt;&lt;/P&gt;
&lt;H2 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=4&gt;DeviceContext&lt;/FONT&gt;&lt;/H2&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;This class represents a specific audio device. You should not have to modify anything in this class to port the driver. There is a DeviceContext virtual base class, from which are derived an InputDeviceContext and an OutputDeviceContext. A typical wavedev2 audio driver (such as the Ensoniq driver) implements a single input device represented by an InputDeviceContext; and a single output device represented by an OutputDeviceContext. In the Ensoniq sample, these objects are directly embedded within HardwareContext class as member variables. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;DeviceContext methods include:&lt;/FONT&gt;&lt;/P&gt;
&lt;H2 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=4&gt;StreamContext&lt;/FONT&gt;&lt;/H2&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;This class represents a specific audio stream. You should not have to modify anything in this class to port the driver. There is a StreamContext virtual base class from which are derived a variety of stream classes for various flavors of PCM audio and MIDI data. Each stream is associated with a specific device context. This association is implemented as a linked list of stream contexts hanging off of each device context. In addition, each stream context includes a pointer back to its associated device context.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;The class hierarchy is roughly as follows:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;StreamContext&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; CMidiStream&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaveStreamContext&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InputStreamContext&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OutputStreamContext&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; OutputStreamContextM8&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OutputStreamContextM16&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OutputStreamContextS8&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OutputStreamContextS16&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;The reason for the multitude of output contexts is that the mixing/sample-rate-conversion code on the output side is optimized for each type of PCM data (Stereo/Mono, 8/16-bit samples). This avoids some tests in the inner loop. The same optimization wasn’t done for the input side (input isn’t typically used as often as output, and the code is a little simpler).&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;StreamContextMethods include:&lt;/FONT&gt;&lt;/P&gt;
&lt;H1 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=5&gt;Porting HardwareContext&lt;/FONT&gt;&lt;/H1&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;In this section, I’ll go over each of the methods in HardwareContext and describe what they do.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::CreateHWContext&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 0.25in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;This is a static method which is called during driver initialization (from the WAV_Init code in wavemain.cpp). This function should create and initialize the global g_pHWContext with a new HardwareContext object and call g_pHWContext-&amp;gt;Init. You probably won’t need to change this function, as most changes will be in the Init method.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::Init&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;This method is only called by CreateHWContext, and is where initialization of the Hardware is typically implemented.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Portions of this function may need to be modified for new hardware. Its role is to initialize any hardware, allocate DMA buffers, and startup the interrupt service thread. In addition, during initialization it needs to call into some of the device independent sections to initialize them; specificially:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l3 level1 lfo2; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;-&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Call SetBaseSampleRate on each device context to tell it what sample rate the hardware is running at. Note that these functions can be called at any time to tell the device context that the hardware sample rate has changed, but for devices with a fixed sample rate setting this up during initialization makes sense.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 10pt 0.75in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l3 level1 lfo2; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;-&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Call InitMixerControls to initialize the Mixer API support.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::Deinit&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;This method is called when the driver is unloaded and the system calls WAV_Deinit. In the current design, wave drivers are never unloaded so this method has limited usefulness.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::UpdateOutputGain&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::UpdateInputGain&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::SetOutputGain&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::SetOutputMute&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::GetOutputGain&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::GetOutputMute&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::GetInputMute&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::SetInputMute&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::GetInputGain&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::SetInputGain&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;These methods are associated with the master input and output gain controls provided by the default mixer API implementation and the device gain waveOutSetVolume API. In the Ensoniq implementation these defer processing to the DeviceContext SetGain methods, which automatically handle volume control in software. There is no need to modify the existing code unless you want to handle some aspects of volume control in hardware. However, keep in mind that individual stream gain controls are still handled in software, and there is no additional overhead in handling device gain as well. Therefore, there is no performance advantage in modifying this code to use hardware gain controls.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::StartOutputDMA&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;This method starts the DMA controller for audio output. This includes:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l2 level1 lfo3; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;1.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Check to see if output dma is already running and ignore the call if it is.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l2 level1 lfo3; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;2.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Clear the variables that track how much “live” data is in each DMA buffer.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.75in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l2 level1 lfo3; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;3.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;“Prime” the output DMA buffer with data.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 10pt 0.75in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l2 level1 lfo3; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;4.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Start the DMA channel if (and only if) data was available to be transferred.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;The only line you should need to change is the one that specifically turns on the DMA channel, which in the Ensoniq implementation is:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 0.5in; TEXT-INDENT: 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;m_CES1371.StartDMAChannel( ES1371_DAC0 );&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::StopOutputDMA&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT size=3&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;This method stops the audio output DMA controller. The only line you should need to change is:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 0.5in; TEXT-INDENT: 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;m_CES1371.StopDMAChannel( ES1371_DAC0 );&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::StartInputDMA&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::StopInputDMA&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;These methods are analogous to the methods described above for the output DMA. However, note that the code to start the input DMA doesn’t need to “prime” the buffer or keep track of how much application data is in the buffer, and is therefore somewhat simpler than the output case.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::GetDriverRegValue&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::SetDriverRegValue&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;These methods relate to reading driver-specific registry keys. You should not need to change them.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::InitInterruptThread&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;This method initializes the audio driver’s IST thread and sets it to a realtime priority. If your driver has a single IST thread shared by both input and output you will not need to modify this code.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::PowerUp&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::PowerDown&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;These methods are called by the system’s power management subsystem. In the Ensoniq driver they are stubbed out. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::TransferInputBuffer&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::TransferOutputBuffer&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;This method is called from the IST to transfer one data into our out of the DMA buffers. The code determines the starting address and size of the DMA buffer and passes the information to the device context, which performs the actual transfer. You will not need to modify this code unless you change the organization or data structures representing the DMA buffers.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::InterruptThread&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;This method implements the Interrupt Service Thread which is shared by both input and output DMA. It’s operation is basically:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l3 level2 lfo2; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;1.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Wait for an input or output DMA done interrupt.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l3 level2 lfo2; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;2.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Determine whether an input or output (or both) DMA interrupt occurred.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l3 level2 lfo2; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;3.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;If an output DMA interrupt occurred:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l3 level3 lfo2; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;§&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Transfer/mix application data into the DMA buffer that was just completed.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l3 level3 lfo2; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;§&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;If there is no application data remaining in either DMA buffer, halt output DMA&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l3 level2 lfo2; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;4.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;If an input DMA interrupt occurred:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l3 level3 lfo2; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;§&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Transfer data out of the DMA buffer that was just completed into application buffers.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l3 level3 lfo2; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-FAMILY: Wingdings; mso-fareast-font-family: Wingdings; mso-bidi-font-family: Wingdings"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;§&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;If we were unable to transfer any data (due to no application buffer being available), halt input DMA.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l3 level2 lfo2; mso-add-space: auto"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;5.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Go back to step 1.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::SetSpeakerEnable&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::RecalcSpeakerEnable&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::ForceSpeaker&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;These methods handle the WODM_FORCESPEAKER message which may be used to request that audio data be routed to an auxiliary speaker on the back of the phone (this speaker is typically larger and more powerful than the earpiece speaker, and is used for ringtones). If you hardware supports this functionality, you will need to add code to the SetSpeakerEnable to switch the speaker on or off.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::PmControlMessage&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;This method receives messages from the Power Manager IOCTL calls:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;IOCTL_POWER_CAPABILITIES&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;IOCTL_POWER_QUERY&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 1in"&gt;&lt;FONT size=3&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;IOCTL_POWER_SET&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 1in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;IOCTL_POWER_GET&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 1in"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=3&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;You probably will not need to modify this code.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;HardwareContext::IsSupportedOutputFormat&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;This method is called during waveOutOpen to allow the OEM to support additional custom audio formats beyond the standard PCM functionality. Normally this method should just return FALSE. The Ensoniq driver supports directly playing WMAPro compressed audio content over its S/PDIF interface and therefore returns TRUE for this specific case.&lt;/FONT&gt;&lt;/P&gt;
&lt;H1 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=5&gt;DMA Buffer Organization and Data Transfer&lt;/FONT&gt;&lt;/H1&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;In the Ensoniq implementation, which is fairly typical, input and output are each allocated a DMA buffer using HalAllocateCommonBuffer. The size of each buffer is only 4k (the same as a memory page), so it’s unlikely that the allocation will fail (especially since it takes place during boot). Other implementations may choose to preallocate a fixed area of memory for the audio DMA buffers.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;During audio transfer, each DMA buffer is logically subdivided into equally-sized DMA pages 0 and 1, and the hardware is programmed to:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l0 level1 lfo4"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;a.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Transfer nonstop from the DMA buffer to the codec, and automatically reload the DMA address register with the start address of the buffer when it reaches the end. &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 10pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: 115%; mso-list: l0 level1 lfo4"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-fareast-font-family: Calibri; mso-bidi-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-bidi-theme-font: minor-latin"&gt;&lt;SPAN style="mso-list: Ignore"&gt;&lt;FONT size=3&gt;b.&lt;/FONT&gt;&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;FONT size=3&gt;Generate an interrupt to the audio system whenever the DMA address moves either past the midpoint of the buffer (e.g. from page 0 to page 1), or reaches the end and restarts itself (e.g. from page 1 to page 0).&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;On each DMA interrupt, the HardwareContext code needs to determine which DMA page the DMA controller has just finished copying data into/out of and call the DeviceContext’s TransferBuffer method to copy application data into/out of that buffer.&lt;/FONT&gt;&lt;/P&gt;
&lt;H1 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=5&gt;Buffer Security/Copying&lt;/FONT&gt;&lt;/H1&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;(Still working on this section)&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;H1 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=5&gt;Support for S/PDIF&lt;/FONT&gt;&lt;/H1&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;(Still working on this section)&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=5&gt;Differences between Windows CE 5 &amp;amp; Windows CE 6&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;All current versions of Windows Mobile (including Windows Mobile 6) are based on Windows CE 5 or earlier OS releases. However, the most recent version of wavedev2 is shipped with Windows CE 6, and that’s the version I’m examining for this guide. Therefore, it’s important to touch on differences between how the two OS’es interact with wave drivers.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;For the most part, the audio driver architecture between CE5 and CE6 is the same. Audio drivers written for CE5 can generally run with little or no modification on CE6. &lt;/FONT&gt;&lt;/P&gt;
&lt;H2 style="MARGIN: 10pt 0in 0pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=4&gt;Virtual Addressing Differences&lt;/FONT&gt;&lt;/H2&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;When porting the Ensoniq wavedev2 driver from CE5 to CE6, the only change specifically related to moving between operating systems was to surround the call to SetProcPermissions in hwctxt.cpp as follows:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNoSpacing style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;#if (_WINCEOSVER &amp;lt; 600)&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNoSpacing style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT size=3&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;SetProcPermissions((DWORD)-1);&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNoSpacing style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;#endif&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNoSpacing style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;On Windows CE6, the API’s SetProcPermissions and GetProcPermissions are no longer supported due to changes in the virtual memory architecture. They are still exported for backward-compatibility purposes, but they will have no affect (other than printing out a nasty warning message on the debugger). This change bears a little explanation:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;On pre-Windows CE6 systems there is a limit of 32 processes, and all processes run in a shared virtual memory space. The system provides cross-process protection to ensure that processes don’t access each other’s memory, and this protection is enforced on a per-thread basis. Device drivers (such as the wave driver) run inside device.exe, which is one of these 32 processes. The Interrupt Service Thread (IST) in the driver is responsible for accessing audio data in various application buffers residing in multiple processes. The audio driver’s IST overrides this protection by calling SetProcPermissions(0xFFFFFFFF); each bit in the parameter represents one of 32 processes in the system, so 0xFFFFFFFF enables access to all of them.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;Windows CE 6 adopts a more traditional memory architecture, with the kernel taking the upper 2GB of virtual space and each user process occupying the same lower 2GB region. Switching between user processes involves swapping a new process into the lower 2GB. While this greatly expands the amount of virtual memory available to each user process, it also means that the IST thread (now running in the kernel) may no longer freely access other arbitrary process’ address space.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;FONT size=3&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;To solve this problem, the waveapi middleware (which sits above the audio driver on the stack) now takes care of mapping each application data buffer into a kernel (via CeAllocAsynchronousBuffer). The memory mapping/unmapping take place during waveOutPrepareHeader/waveOutUnprepareHeader, so the cost of memory management doesn’t impact performance.&lt;SPAN style="FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=3&gt;&lt;/FONT&gt;&lt;/o:p&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5003691" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/medmedia/archive/tags/WaveAPI/default.aspx">WaveAPI</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Andy+Raffman/default.aspx">Author: Andy Raffman</category></item><item><title>The Video Renderer Connection Process</title><link>http://blogs.msdn.com/medmedia/archive/2007/06/11/the-video-renderer-connection-process.aspx</link><pubDate>Mon, 11 Jun 2007 19:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3232201</guid><dc:creator>luciad</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/3232201.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=3232201</wfw:commentRss><description>&lt;P&gt;The video renderer is the last filter in the video pipe, and it is&amp;nbsp;responsible for displaying the output of upstream filters.&amp;nbsp;The video renderer&amp;nbsp;is just a controller for the underlying display driver, and does not do any processing on the image samples themselves. &lt;/P&gt;
&lt;P&gt;The video renderer operates in&amp;nbsp;two distinct modes:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;GDI&lt;/LI&gt;
&lt;LI&gt;DirectDraw&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;When the graph is first connected, the video renderer always tries to connect using GDI, and for that, it will need a connection with an RGB media type that matches the display format of the primary monitor. Just when it goes into &lt;EM&gt;Paused &lt;/EM&gt;mode, the video renderer will try to allocate surfaces using DirectDraw. This dual mode of operation was envisioned so as to always have a fall back plan in case DirectDraw surfaces were not available in some circumstances. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Choosing an Accelerated Media Type&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;When the video renderer goes into Paused mode, it is time to allocate the DirectDraw surfaces. The video renderer will do so by enumerating all media types of the upstream filter, and then trying to allocate a surface matching that media type. For instance, let's assume the upstream filter is the &lt;EM&gt;WMV DMO&lt;/EM&gt;. It currently supports the following output media types (the preferred media type is the first one):&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;YV12&lt;/LI&gt;
&lt;LI&gt;NV12&lt;/LI&gt;
&lt;LI&gt;YUY2&lt;/LI&gt;
&lt;LI&gt;I420&lt;/LI&gt;
&lt;LI&gt;IYUV&lt;/LI&gt;
&lt;LI&gt;UYVY&lt;/LI&gt;
&lt;LI&gt;YVYU&lt;/LI&gt;
&lt;LI&gt;RGB565&lt;/LI&gt;
&lt;LI&gt;RGB555&lt;/LI&gt;
&lt;LI&gt;RGB32&lt;/LI&gt;
&lt;LI&gt;RGB24&lt;/LI&gt;
&lt;LI&gt;RGB8&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;The video renderer will try to allocate flipping overlay surfaces first, then non-flipping surfaces:&lt;/P&gt;
&lt;UL&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;For each media type of the upstream filter, in the order dictated by the upstream filter&lt;/DIV&gt;&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;try to allocate a flipping surface of that media type&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;If it succeeds, call QueryAccept on the upstream filter's output pin&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;If it succeeds, use it&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;If the previous didn't succeed, try to allocate a primary flipping surface (if enabled)&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;If it succeeds, call QueryAccept on the upstream filter's output pin&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;If it succeeds, use it&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;If the previous didn't succeed, for each media type of the upstream filter, in the order dictated by the upstream filter&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;try to allocate a surface (not flipping) of that media type&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;If it succeeds, call QueryAccept on the upstream filter's output pin&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;If it succeeds, use it&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt;&lt;/UL&gt;
&lt;P&gt;In&amp;nbsp;this way, if the upstream filter has optimized for certain YUV formats, it can control the choice of media type. In case the display driver can also provide a surface of that type, the accelerated media type is chosen. The whole process is driven by the upstream filter, with the display driver in a passive role.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;Dynamic Format Changes from the Video Renderer&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Of course, for an optimal pipe, we would like to always have overlay flipping surfaces available. Nevertheless, that may not be the case in some situations. For instance, depending on the display driver capabilities, the flipping overlay may just be available when the user is watching the video at its original size. When the user is stretching or shrinking, overlays might not be available. This is controlled by the DirectDraw hardware capabilities dwMinOverlayStretch and dwMaxOverlayStretch (see &lt;A href="http://msdn2.microsoft.com/en-us/library/aa915204.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa915204.aspx"&gt;http://msdn2.microsoft.com/en-us/library/aa915204.aspx&lt;/A&gt;). So, if the display driver doesn't support overlay stretching, and the video renderer is currently using overlays, it will need to swap to GDI (and thus to RGB format), so that GDI will do the necessary scaling.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Note that every time the upstream filter&amp;nbsp;requests a new buffer from the video renderer,&amp;nbsp;the video renderer will try to return a DirectDraw buffer.&amp;nbsp;If all the conditions to use the DirectDraw buffer are OK (clipping, stretching, video memory, etc.), then it will use it.&amp;nbsp;Just in case one of the conditions fail it will resort to using GDI.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;&lt;U&gt;Debugging&amp;nbsp;Video Renderer Connection Problems&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;We have seen some common connection problems when initially bringing up new decoder filters and/or capture drivers:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Color space converter is inserted in the graph&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Video renderer doesn't connect&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;YUV surfaces are not being used, just GDI&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;U&gt;Analyzing the DirectShow logs&lt;/U&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The&amp;nbsp;first step in this case is to turn on the debug zones for the DirectShow DLL, quartz.dll, and observe the connection and video renderer messages.&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Set it on the &lt;STRONG&gt;client&lt;/STRONG&gt;&amp;nbsp;when quartz.dll is already loaded (my preferred method ;-):&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Go to Target/CE debug zones, choose quartz.dll, and check the first four zones&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;Set it on the &lt;STRONG&gt;host-side registry&lt;/STRONG&gt;&amp;nbsp;if you want to start with the zones turned on:&lt;/LI&gt;
&lt;UL&gt;
&lt;LI&gt;Go to [HKEY_CURRENT_USER\Pegasus\Zones]&lt;/LI&gt;
&lt;LI&gt;Add a DWORD value with the name quartz and set it to 0xf.&lt;/LI&gt;
&lt;LI&gt;(see more information on debug zones at: &lt;A href="http://blogs.msdn.com/ce_base/archive/2006/12/18/debug-messages-and-debug-zones-in-windows-ce.aspx"&gt;http://blogs.msdn.com/ce_base/archive/2006/12/18/debug-messages-and-debug-zones-in-windows-ce.aspx&lt;/A&gt;)&lt;/LI&gt;&lt;/UL&gt;&lt;/UL&gt;
&lt;P&gt;Run your test scenario, and save the debug output. Look for the section that says "Filter Graph Dump", and verify which filters got inserted in the graph. Here's an example of a filter graph dump:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P mce_keep="true"&gt;Filter graph dump&lt;BR&gt;Filter 1a199a30 'Video Renderer' Iunknown 1a199a20&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pin 1a199f10 Input (Input) connected to 1a0e1880&lt;BR&gt;Filter 1a0e1200 'WMVideo &amp;amp; MPEG4 Decoder DMO' Iunknown 1a0e11f0&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pin 1a0e16e0 in0 (Input) connected to 1a0e0600&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pin 1a0e1880 out0 (PINDIR_OUTPUT) connected to 1a199f10&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pin 1a0e1a00 ~out1 (PINDIR_OUTPUT) connected to 0&lt;BR&gt;Filter 1a0ecc60 'ASF ICM Handler' Iunknown 1a0ecc50&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pin 1a0ecd70 In (Input) connected to 1a0aa3a0&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pin 1a0e0600 Out (PINDIR_OUTPUT) connected to 1a0e16e0&lt;BR&gt;Filter 1a0ec240 'Audio Renderer' Iunknown 1a0ec230&lt;BR&gt;wo: GetPin, 0&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pin 1a0ec4e0 Audio Input pin (rendered) (Input) connected to 1a0eb880&lt;BR&gt;Filter 1a0eb220 'WMAudio Decoder DMO' Iunknown 1a0eb210&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pin 1a0eb660 in0 (Input) connected to 1a0ea800&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pin 1a0eb880 out0 (PINDIR_OUTPUT) connected to 1a0ec4e0&lt;BR&gt;Filter 1a0e9380 'ASF ACM Handler' Iunknown 1a0e9370&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pin 1a0e9490 In (Input) connected to 1a0aa000&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pin 1a0ea800 Out (PINDIR_OUTPUT) connected to 1a0eb660&lt;BR&gt;Filter 1a0a2ae0 '\Hard Disk2\clips\wmv\0-1.asf' Iunknown 1a0a2ad0&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pin 1a0aa000 Stream 1 (PINDIR_OUTPUT) connected to 1a0e9490&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Pin 1a0aa3a0 Stream 2 (PINDIR_OUTPUT) connected to 1a0ecd70&lt;BR&gt;End of filter graph dump&lt;BR&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;After that, verify which media type the video renderer is using when trying accelerated mode (and if it succeeded). Search for "Allocating video resources":&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Allocating video resources&lt;BR&gt;Initialising DCI/DirectDraw&lt;BR&gt;Searching for direct format&lt;BR&gt;Entering ReleaseSurfaces&lt;BR&gt;Entering HideOverlaySurface&lt;BR&gt;Enumerated 32315659&lt;BR&gt;Entering FindSurface&lt;BR&gt;Entering GetMediaType&lt;BR&gt;Not a RGB format&lt;BR&gt;Entering CreateYUVFlipping&lt;BR&gt;Entering CheckCreateOverlay&lt;BR&gt;GWES Hook fails surface creation. IDirectDraw::CreateSurface fails.&lt;BR&gt;No surface&lt;BR&gt;Entering ReleaseSurfaces&lt;BR&gt;Entering HideOverlaySurface&lt;BR&gt;Enumerated 3231564e&lt;BR&gt;Entering FindSurface&lt;BR&gt;Entering GetMediaType&lt;BR&gt;Not a RGB format&lt;BR&gt;Entering CreateYUVFlipping&lt;BR&gt;Entering CheckCreateOverlay&lt;BR&gt;GWES Hook fails surface creation. IDirectDraw::CreateSurface fails.&lt;BR&gt;No surface&lt;BR&gt;Entering ReleaseSurfaces&lt;BR&gt;Entering HideOverlaySurface&lt;BR&gt;Enumerated 32595559&lt;BR&gt;Entering FindSurface&lt;BR&gt;Entering GetMediaType&lt;BR&gt;Not a RGB format&lt;BR&gt;Entering CreateYUVFlipping&lt;BR&gt;Entering CheckCreateOverlay&lt;BR&gt;Entering InitOverlaySurface&lt;BR&gt;Entering InitDrawFormat&lt;BR&gt;Entering InitDrawFormat&lt;BR&gt;Entering GetDefaultColorKey&lt;BR&gt;Returning default colour key&lt;BR&gt;Entering InitDefaultColourKey&lt;BR&gt;Entering SetSurfaceSize&lt;BR&gt;Preparing source and destination rectangles&lt;BR&gt;Entering ClipPrepare&lt;BR&gt;Entering InitialiseClipper&lt;BR&gt;Entering InitialiseColourKey&lt;BR&gt;overlay color key on&lt;BR&gt;Colour key&lt;BR&gt;No palette&lt;BR&gt;&lt;STRONG&gt;Found AMDDS_YUVFLP surface&lt;/STRONG&gt;&lt;BR&gt;Proposing output type&amp;nbsp; M type MEDIATYPE_Video&amp;nbsp; S type &lt;STRONG&gt;MEDIASUBTYPE_YUY2&lt;/STRONG&gt;&lt;BR&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Note in the above log that the video renderer tried to create surfaces in the order&amp;nbsp;specified by the WMV DMO. For the display driver in use for the above log, it managed to create a YUY2 surface, the third option for the WMV decoder. The last section in this blog entry has more information about FourCC codes.&lt;/P&gt;
&lt;P&gt;Here are some solutions for common connection problems we have faced in the past.&lt;/P&gt;
&lt;P&gt;&lt;U&gt;Color Space Converter is inserted in the graph&lt;/U&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The number one problem is that the upstream filter doesn't&amp;nbsp;report any RGB format, just YUV formats. If that's the case, the video renderer can't connect directly to the filter since it requires a matching RGB format. Usually, the color space converter will be inserted in the graph in these cases. We don't want this to happen, as it will imply a memory copy of each frame buffer, so we want to make sure the upstream filter does provide RGB formats.&lt;/P&gt;
&lt;P&gt;Sometimes the color converted gets inserted in the graph even though the upstream filter does support the needed RGB format. This can happen because the upstream filter is requiring an alignment different than 1 when the allocator is being decided. Currently, the video renderer will just accept 1-byte alignments.&lt;/P&gt;
&lt;P&gt;Another common reason for the color converter to be inserted in the graph is when the BITMAPINFOHEADER supplied by the upstream filter doesn't contain the bitmasks correctly at the end of BITMAPINFOHEADER that is passed when getting the output media types. Please make sure that the bitmasks are inserted correctly. For instance, for RGB565, we should have:&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: left" align=left&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; *pdwBitfield++&amp;nbsp; = 0xF800;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: green"&gt;// Red – 5&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in; TEXT-ALIGN: left" align=left&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;*pdwBitfield++&amp;nbsp; = 0x07E0;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: green"&gt;// Green - 6&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in; TEXT-ALIGN: left" align=left&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;*pdwBitfield&amp;nbsp;&amp;nbsp;&amp;nbsp; = 0x001F;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style="COLOR: green"&gt;// Blue - 5&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;U&gt;Graph doesn't connect at all&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;If the upstream filter just supports a subset of YUV formats, and none of these are recognized by the color space converter, then it won't be possible at all to connect the video renderer. Again, in this case the solution is for the upstream filter to provide RGB formats.&lt;/P&gt;
&lt;P&gt;&lt;U&gt;YUV Surfaces are not used, just GDI&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;Another common occurrence is for the upstream filters to provide allocators. If this is the case, the video renderer will be tied to not using DirectDraw (as it can't pass upstream memory buffers to DirectDraw). If we want the optimal overlay flipping path, the video renderer *needs* to be the allocator, so that it is possible for it to provide DirectDraw surfaces upstream.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;Surface Types: Controlling Which Surfaces the Video Renderer Creates&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;There are ways to control which accelerated surfaces the video renderer is allowed or not to create that are useful when debugging the connection process, specially to reduce the number of options and the number of tries in the display driver. This is controlled via a registry key (see &lt;A href="http://msdn2.microsoft.com/en-us/library/aa930626.aspx"&gt;http://msdn2.microsoft.com/en-us/library/aa930626.aspx&lt;/A&gt;):&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;HKEY_LOCAL_MACHINE\Software\Microsoft\DirectX\DirectShow\Video Renderer\SurfaceTypes&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The following table shows the AMDDS values for use with the &lt;B&gt;SurfaceTypes&lt;/B&gt; named value.&lt;/P&gt;
&lt;H3 class=subHeading&gt;&lt;!----&gt;&lt;/H3&gt;
&lt;TABLE class="" style="BACKGROUND-COLOR: #cccccc" width="100%" border=1&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TH class=""&gt;Flag &lt;/TH&gt;
&lt;TH class=""&gt;Hexadecimal value &lt;/TH&gt;
&lt;TH class=""&gt;Description &lt;/TH&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_NONE&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0x00&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;No support for Device Control Interface (DCI) or DirectDraw.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_DCIPS&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0x01&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;Use DCI primary surface.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_PS&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0x02&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;Use DirectDraw primary surface.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_RGBOVR&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0x04&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;RGB overlay surfaces.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_YUVOVR&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0x08&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;YUV overlay surfaces.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_RGBOFF&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0x10&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;RGB off-screen surfaces.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_YUVOFF &lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0x20&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;YUV off-screen surfaces.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_RGBFLP&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0x40&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;RGB flipping surfaces.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_YUVFLP&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0x80&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;YUV flipping surfaces.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_ALL&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0xFF&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;Use all available surfaces.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_DEFAULT&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0xFF&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;Use all available surfaces.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_YUV &lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0xA8&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;(AMDDS_YUVOFF | AMDDS_YUVOVR | AMDDS_YUVFLP)&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_RGB&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0x58&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;(AMDDS_RGBOFF | AMDDS_RGBOVR | AMDDS_RGBFLP)&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;
&lt;P&gt;AMDDS_PRIMARY&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;0x03&lt;/P&gt;&lt;/TD&gt;
&lt;TD class=""&gt;
&lt;P&gt;(AMDDS_DCIPS | AMDDS_PS)&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P mce_keep="true"&gt;If you just want to enable YUV overlay flipping surfaces for debugging purposes, you should set the SurfaceTypes registry key to AMDDS_YUVFLP. Remember to turn on all surfaces back on after you finished debugging your problem...&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;About FourCC codes:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Note that in the example log we list the FOURCC codes that are being used in the line &lt;EM&gt;"Enumerated 32315659"&lt;/EM&gt;. Here's how to map this hex number into a character sequence that&amp;nbsp;will help identify&amp;nbsp;the code:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Enumerated 32315659 &lt;/P&gt;
&lt;P&gt;0x32 = '2', 0x31 = '1', 0x56 = 'V', 0x59 = 'Y' ===&amp;gt; &lt;STRONG&gt;0x32315659 = YV12&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Enumerated 3231564e&lt;/P&gt;
&lt;P&gt;0x32 = '2', 0x31 = '1', 0x56 = 'V', 0x4e = 'N'&amp;nbsp;===&amp;gt; &lt;STRONG&gt;0x3231564e = NV12&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Enumerated 32595559&lt;/P&gt;
&lt;P&gt;0x32 = '2', 0x59 = 'Y', 0x55 = 'U', 0x59 = 'Y' ===&amp;gt; &lt;STRONG&gt;0x32595559 = YUY2&lt;/STRONG&gt;&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Enumerated 56555949&lt;/P&gt;
&lt;P&gt;0x56 = 'V', 0x55 = 'U', 0x59 = 'Y', 0x49 = 'I' ===&amp;gt; &lt;STRONG&gt;0x56555949 = IYUV&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Enumerated 59565955&lt;/P&gt;
&lt;P&gt;0x59 = 'Y', 0x56 = 'V', 0x59 = 'Y', 0x55 = 'U' ===&amp;gt; &lt;STRONG&gt;0x59565955 = UYVY&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Enumerated 55595659&lt;/P&gt;
&lt;P&gt;0x55 = 'U', 0x59 = 'Y', 0x56 = 'V', 0x59 = 'Y' ===&amp;gt; &lt;STRONG&gt;0x55595659 = YVYU&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Also, the file in public\directx\sdk\inc\uuids.h contains&amp;nbsp;several FOURCC media subtypes definitions:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT color=#008000 size=1&gt;// 32595559-0000-0010-8000-00AA00389B71 'YUY2' == MEDIASUBTYPE_YUY2&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;LI&gt;OUR_GUID_ENTRY(MEDIASUBTYPE_YUY2,&lt;/LI&gt;
&lt;LI&gt;0x32595559, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=1&gt;
&lt;LI&gt;// 55595659-0000-0010-8000-00AA00389B71 'YVYU' == MEDIASUBTYPE_YVYU&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;LI&gt;OUR_GUID_ENTRY(MEDIASUBTYPE_YVYU,&lt;/LI&gt;
&lt;LI&gt;0x55595659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=1&gt;
&lt;LI&gt;// 59565955-0000-0010-8000-00AA00389B71 'UYVY' == MEDIASUBTYPE_UYVY&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;LI&gt;OUR_GUID_ENTRY(MEDIASUBTYPE_UYVY,&lt;/LI&gt;
&lt;LI&gt;0x59565955, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=1&gt;
&lt;LI&gt;// 31313259-0000-0010-8000-00AA00389B71 'Y211' == MEDIASUBTYPE_Y211&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;LI&gt;OUR_GUID_ENTRY(MEDIASUBTYPE_Y211,&lt;/LI&gt;
&lt;LI&gt;0x31313259, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=1&gt;
&lt;LI&gt;// 32315659-0000-0010-8000-00AA00389B71 'YV12' == MEDIASUBTYPE_YV12&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;LI&gt;OUR_GUID_ENTRY(MEDIASUBTYPE_YV12,&lt;/LI&gt;
&lt;LI&gt;0x32315659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=1&gt;
&lt;LI&gt;// 36313259-0000-0010-8000-00AA00389B71 'YV16' == MEDIASUBTYPE_YV16&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;LI&gt;OUR_GUID_ENTRY(MEDIASUBTYPE_YV16,&lt;/LI&gt;
&lt;LI&gt;0x36315659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=1&gt;
&lt;LI&gt;// 56595549-0000-0010-8000-00AA00389B71 'IUYV' == MEDIASUBTYPE_IUYV&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;LI&gt;OUR_GUID_ENTRY(MEDIASUBTYPE_IUYV,&lt;/LI&gt;
&lt;LI&gt;0x56595549, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=1&gt;
&lt;LI&gt;// 3231564E-0000-0010-8000-00AA00389B71 'NV12' == MEDIASUBTYPE_NV12&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;LI&gt;OUR_GUID_ENTRY(MEDIASUBTYPE_NV12,&lt;/LI&gt;
&lt;LI&gt;0x3231564E, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=1&gt;
&lt;LI&gt;// 30323449-0000-0010-8000-00AA00389B71 'I420' == MEDIASUBTYPE_I420&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;LI&gt;OUR_GUID_ENTRY(MEDIASUBTYPE_I420,&lt;/LI&gt;
&lt;LI&gt;0x30323449, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT color=#008000 size=1&gt;
&lt;LI&gt;// 56555949-0000-0010-8000-00AA00389B71 'IYUV' == MEDIASUBTYPE_IYUV&lt;/LI&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;
&lt;LI&gt;OUR_GUID_ENTRY(MEDIASUBTYPE_IYUV,&lt;/LI&gt;
&lt;LI&gt;0x56555949, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&lt;/FONT&gt;Please do leave feedback, and let us know if this has been useful. Thanks,&lt;/P&gt;
&lt;P mce_keep="true"&gt;Lucia&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3232201" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/medmedia/archive/tags/DShow/default.aspx">DShow</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Lucia+Darsa/default.aspx">Author: Lucia Darsa</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Video+Renderer/default.aspx">Video Renderer</category></item><item><title>Basics of A/V synchronization in DirectShow</title><link>http://blogs.msdn.com/medmedia/archive/2007/03/05/basics-of-a-v-synchronization-in-directshow.aspx</link><pubDate>Tue, 06 Mar 2007 02:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1813475</guid><dc:creator>luciad</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/1813475.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=1813475</wfw:commentRss><description>&lt;P&gt;All filters in a DirectShow graph should be synchronized to the same clock, the &lt;EM&gt;reference clock&lt;/EM&gt;. The filter graph manager makes sure that it finds one component that will be the reference clock, in the following simplified order: user-specified clock, renderer (usually audio renderer), or system clock if none available before.&lt;/P&gt;
&lt;P&gt;The &lt;EM&gt;stream time&lt;/EM&gt; is based off the reference clock, but relative to the time the graph last started running (so the stream time doesn't move if the graph is paused). If a media sample that enters a renderer has a time stamp &lt;EM&gt;t, &lt;/EM&gt;then it means it should be rendered at stream time &lt;EM&gt;t. &lt;/EM&gt;This is the basic mechanism by which a/v synchronization occurs. &lt;/P&gt;
&lt;P&gt;There is usually a crystal in the audio hardware though, and no guarantees that the hardware timer will match the system clock. That's why usually we have the audio renderer being the reference clock for the whole DirectShow graph. If the audio renderer receives a sample late, or if the audio clock is consistently drifting from the system clock, then the audio renderer will issue stream time adjustments. &lt;/P&gt;
&lt;P&gt;An audio renderer implementation will usually inherit from the CBaseReferenceClock class, and will call SetTimeDelta() function whenever it needs to&amp;nbsp;do an adjustment to the stream time. Note that it should use a low pass filter before sending adjustments to the master clock so that no unnecessary jittering is introduced.&lt;/P&gt;
&lt;P&gt;As the video renderer uses the incoming timestamps to schedule samples for presentation, the scheduler is based off stream time, and the audio renderer has control to change the stream time, the video and audio renderer will be using the same timeline.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;About the Video Renderer &amp;amp; Frame Dropping&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;If the video is running slow, and all video frames are being rendered, then theoretically the video renderer will receive samples with timestamps in the past and schedule them for immediate rendering. If this situation continues to happen, what will happen is that the video is going to be behind audio. This shows the need for frame dropping.&lt;/P&gt;
&lt;P&gt;In fact, audio and video synchronization in DirectShow works by a combination of two elements:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Audio renderer controlling the DirectShow stream time;&lt;/LI&gt;
&lt;LI&gt;IQualityControl and IDMOQualityControl interfaces guiding frame dropping algorithm&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Dropping frames at the video renderer level is of course not very effective. If using overlay flipping surfaces, for instance, dropping a frame doesn't get you much farther trying to catch up (because the flipping itself is very cheap). Even in the case of Blits, it is still going to help very little (rendering time is small compared to decoding time). That's why there is the need&amp;nbsp;to indicate the state and lateness of the renderer to upstream filters/DMOs, which is done through the quality notification messages.&lt;/P&gt;
&lt;P&gt;The video renderer originates the notification messages (since it is &lt;STRONG&gt;the&lt;/STRONG&gt;&amp;nbsp;filter that needs to run in real time), and sends&amp;nbsp;them upstream.&amp;nbsp;If the upstream filter is a decoder, and it can handle it, it doesn't pass the message upstream. If it can't handle, then&amp;nbsp;it passes it upstream. Note that the video renderer will drop frames anyway if it is very late.&lt;/P&gt;
&lt;P&gt;Here's a coarse&amp;nbsp;example of how to use the Quality interface to be able to drop frames in a decoder filter:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;HRESULT CDecoderFilterPin::Notify(IBaseFilter *pSender, Quality q)&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (quality sink has been set)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // m_pQSink&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; status = Pass Notify on the quality sink&amp;nbsp;&amp;nbsp; (base sender is the decoder filter now)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;else&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;if (has frame dropping algorithm)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; status = Call decoder filter to do frame dropping &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (upstreamQualityControl)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; status = Pass Notify() on to upstream quality control interface (base sender is the decoder filter now)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; status = not handled;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;return status&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;}&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT size=2&gt;The decoder needs to decide, given what the current time is (given by the IQualityControl/IDMOQualityControl interface) if it needs or not to drop frames. Algorithms for frame dropping can vary from the extremely simple to very complicate. An example of an extremely&amp;nbsp;simple one follows:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;FONT size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT size=2&gt;The quality notification message will indicate how late we were when we last rendered a video frame. A very simple algorithm would be to drop all frames until you arrive at that "time", so that catch-up happens fast:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/o:p&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;CatchupPTS = q.Late + q.Timestamp&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;Drop all frames until PTS_frame &amp;gt;= Catchup_PTS&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT size=2&gt;Of course, there are many variations for this. If B-frames are available, start trying to catch up by dropping B-frames. If the decoder has decoding decoupled from output generation (or color conversion etc.), a first step when you're late is to start dropping the output generation, and try to catch up. If neither is working, then you may have to drop P-frames, in which case you'll have to wait until the next I-frame, which is never a good user experience because the spacing between I-frames may be large.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;FONT size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT size=2&gt;When doing trick modes, the algorithm for dropping frames will usually be more forgiving, since frames are arriving at rates other than 1.0. In fact,&amp;nbsp;at high-rates, all samples that the decoder receives are probably going to be key frames anyway. In this case,&amp;nbsp;you may drop any frame without a significant penalty, making catch up much easier.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1813475" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/medmedia/archive/tags/DShow/default.aspx">DShow</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Lucia+Darsa/default.aspx">Author: Lucia Darsa</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Video+Renderer/default.aspx">Video Renderer</category></item><item><title>The Wavedev2 ForceSpeaker API</title><link>http://blogs.msdn.com/medmedia/archive/2007/01/16/the-wavedev2-forcespeaker-api.aspx</link><pubDate>Wed, 17 Jan 2007 03:54:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1481153</guid><dc:creator>Andy Raffman</dc:creator><slash:comments>13</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/1481153.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=1481153</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;This is just a&amp;nbsp;quick note describing the behavior of the MM_WOM_FORCESPEAKER API built into the wavedev2 wave driver.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;One issue in Smartphone devices is determining where to route ringtones and other high-priority notifications. This is driven by two scenarios:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;1. A fairly common design feature of&amp;nbsp;Smartphone devices is a separate&amp;nbsp;"high-volume" speaker on the rear of the device to play ringtones or fairly loud notifications. The OEM may want most system sounds to play through the normal handset speaker, but to have incoming call ringtones routed through the rear speaker.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;2. When the user has a headset plugged in, all audio is routed to that headset. However, what about the situation where the headset is plugged in but the user isn't wearing it? For this reason, some OEMs &lt;U&gt;may&lt;/U&gt; choose to play ringtones through the device speaker even if a headset is attached.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;The common thread to each of these scenarios is that the audio device driver needs to make some decision about where to route the audio based on w&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;hether the sound being played is a ringtone (or other high-priority notification), or is just normal audio such as music being played through media player. &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;The wave API doesn't include any built-in provision for the wave driver to determine who is trying to play a sound or where it should be routed. One might use the mixer API to address this, but the&amp;nbsp;mixer&amp;nbsp;API is somewhat complicated and doesn't lend itself to handling this on a per-wave-stream basis. Instead, when we first developed the wavedev2 driver back in 2000,&amp;nbsp;we defined a proprietary wave message, MM_WOM_FORCESPEAKER, which&amp;nbsp;is sent to the driver as a hint that the associated wave stream is a ringtone or notification that&amp;nbsp;should possibly&amp;nbsp;be played over over the device's speaker.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;The format of this call is:&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; waveOutMessage(&amp;lt;DeviceID | hWaveOut &amp;gt;, MM_WOM_FORCESPEAKER, bSpeaker, 0);&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;The first parameter can be either a Device ID (e.g. 0 through N-1 if there are N devices in the system), or the handle of an open wave device.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;The third param tells the driver whether to route sound to the speaker (TRUE) or not (FALSE).&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;If param1 is a wave handle (and bSpeaker is TRUE), the sound will be routed to the speaker until you either call the API again with the same handle and bSpeaker==FALSE, or you close the wave handle (or your app exits). If an application calls this API with bSpeaker==FALSE, audio should be routed to the earpiece rather than the speaker.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;If param1 is a&amp;nbsp;device ID and bSpeaker==TRUE, all audio is routed to the speaker until there's a matching call to the API with that device ID and bSpeaker==FALSE. This behavior will persist even if the application that made the original call exits. We generally never use this form of the API.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;Other&amp;nbsp;design details:&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;-&amp;nbsp;&amp;nbsp;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;This API is more of a hint than a command to the driver. It’s up to the OEM to decide how to interpret this message; we don’t place any requirements on how it is interpreted. Some drivers might just ignore it.&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;- The sample driver does a pretty good job of refcounting which steams have enabled the speaker, so if you turn the speaker on twice for a specific stream it won't really do any harm (we'll ignore the second call). &lt;/o:p&gt;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;- If multiple streams are playing and only one of them has turned the speaker on, all of the streams will be routed out the speaker until the stream that turned it on either goes away or turns it back off. As an example, if you're listening to music over WMP and an&amp;nbsp;a ringtone gets played,&amp;nbsp;while the incoming ring is being played you may hear both the incoming ring &lt;U&gt;and&lt;/U&gt; the music being played through the speaker. If this is objectionable, OEMs may choose to mute (in software) these other streams for the duration that the ringtone&amp;nbsp;is being played over the speaker. &lt;/o:p&gt;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;- Most of this design is geared toward hardware implementations where a single piece of audio hardware is multiplexed between one or more speakers and headset jacks (which was the only thing available when the API was designed). &lt;/o:p&gt;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;- The EventSound subsystem (which manages playback of ringtones) keeps track of which tones should be played with ForceSpeaker turned on via a set of reg keys. OEMs can therefore customize which&amp;nbsp;notifications should&amp;nbsp;play over the speaker.&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;- Don't be surprised if this goes away or gets redesigned in some future release; it's really a Smartphone/PPC proprietary feature, and after 7 years it's getting a little long in the tooth.&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;Feel free to leave feedback (does anyone read this stuff?).&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;-Andy&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;Responses to questions:&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;1.&amp;nbsp;Where is MM_WOM_FORCESPEAKER defined?&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;- It should be in audiosys.h, but that might have moved around a bit. The definitions you're looking for are:&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #define MM_WOM_SETSECONDARYGAINCLASS&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;(WM_USER)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #define MM_WOM_SETSECONDARYGAINLIMIT&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;(WM_USER+1)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #define MM_WOM_FORCESPEAKER&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;(WM_USER+2)&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=3&gt;&lt;FONT face=Consolas&gt;&lt;o:p&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;Keep in mind that these are very likely to change or go away in future release of the operating system.&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face=Consolas size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt" mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1481153" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/medmedia/archive/tags/WaveAPI/default.aspx">WaveAPI</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Andy+Raffman/default.aspx">Author: Andy Raffman</category></item><item><title>Multichannel Audio in Windows CE</title><link>http://blogs.msdn.com/medmedia/archive/2007/01/16/multichannel-audio-in-windows-ce.aspx</link><pubDate>Tue, 16 Jan 2007 20:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1479563</guid><dc:creator>Andy Raffman</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/1479563.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=1479563</wfw:commentRss><description>&lt;P&gt;Most of the infrastructure is in place to support multichannel audio in Windows CE, although the number of components that we ship to actually implement it is limited. In this blog I'll cover the varying types of multichannel audio and what features are in place in Windows CE to support it. 
&lt;P&gt;For the purposes of this blog I'll define multichannel audio to mean any audio stream containing more than two channel stereo.&amp;nbsp;We'll further subdivide multichannel audio into three types, differentiated by how the audio data gets from your CE device (e.g. Set Top Box, Smartphone/PPC, whatever) to your receiver: 
&lt;P&gt;1. &lt;STRONG&gt;Analog Matrix Decoders&lt;/STRONG&gt;:&amp;nbsp;In this type of decoding, multichannel audio is sent as&amp;nbsp;left/right stereo&amp;nbsp;data to the receiver. In a simple stereo receiver the audio can still be played through left and right speakers and will sound more-or-less correct. However, a receiver supporting the appropriate decoder can use cues placed in the audio to decode to more than two speakers and synthesize additional channels. The most well known&amp;nbsp;decoders are Dolby Pro Logic and Pro Logic II. 
&lt;P&gt;2. &lt;STRONG&gt;Compressed audio over S/PDIF&lt;/STRONG&gt;: S/PDIF was originally designed to support a maximum of 4 decompressed PCM channels. While one might use this to pass four discrete audio signals to a receiver, today's multichannel content typically has at least six channels (e.g. 5.1). There's no way to squeeze 6 decompressed audio channels across S/PDIF. The solution to this has been to pass the compressed audio over S/PDIF and let the receiver decompress it (as long as the compressed data bandwidth is less than that which would be required for four decompressed channels). Apart from enabling use of a single cable from the device to&amp;nbsp;the receiver, this has the added benefit of offloading the audio decompression processing into the receiver. The downside of this architecture is that it relies on the receiver to be able to correctly decode the audio data. This is complicated because S/PDIF is a&amp;nbsp;one-way transmission mechanism, so there's no way to query the receiver at runtime to determine what it supports. There are potential timing/latency issues with lip synch. 
&lt;P&gt;Transferring compressed audio over S/PDIF typically involves massaging the compressed audio into a format that matches the S/PDIF frame format &lt;BR&gt;(e.g. by padding the data with zero's as needed) and adding some header information that lets the receiver figure out that you're sending a &lt;BR&gt;compressed audio stream rather than PCM. Both WMAPro and Dolby AC3 have a spec for this. Almost every receiver in the world supports AC3 &lt;BR&gt;decoding. A small (but a growing number) also support WMAPro (Pioneer in particular have spread WMAPro support to even the low end of their product line).&lt;/P&gt;
&lt;P&gt;Info on WMAPro is here: &lt;BR&gt;&lt;A href="http://download.microsoft.com/download/5/b/5/5b5bec17-ea71-4653-9539-204a672f11cf/wmadrv.doc"&gt;http://download.microsoft.com/download/5/b/5/5b5bec17-ea71-4653-9539-204a672f11cf/wmadrv.doc&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Info on AC3-over-S/PDIF&amp;nbsp;is here in Appendix B: &lt;BR&gt;&lt;A href="http://www.dolby.com/assets/pdf/tech_library/46_DDEncodingGuidelines.pdf" target=_blank rel=nofollow mce_href="http://www.dolby.com/assets/pdf/tech_library/46_DDEncodingGuidelines.pdf"&gt;&lt;FONT color=#0000cc&gt;http://www.dolby.com/assets/pdf/tech_library/46_DDEncodingGuidelines.pdf&lt;/FONT&gt;&lt;/A&gt; &lt;BR&gt;&lt;BR&gt;3. &lt;STRONG&gt;Multiple discrete audio outputs&lt;/STRONG&gt;: In this type of connection multiple PCM audio channels are sent to the receiver. Until recently this has meant a separate RCA cable for each channel: a six channel (e.g. 5.1) signal would require six cables between components. HDMI has the potential to&amp;nbsp;overcome this limitation by supporting 6 or more decompressed audio channels (and video) via a single cable.&lt;/P&gt;
&lt;P&gt;Outputting to 6 DAC channels presumes that you've already&amp;nbsp;got decompressed multichannel content or you've got a compressed multichannel content that is going to get decompressed before being sent to the wave driver (e.g.&amp;nbsp;AC3 or WMAPro).&amp;nbsp;The latter case is most likely, which means you'll need the appropriate DirectShow decompression filter for CE.&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;Now, on to what CE supports (and doesn't):&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Device Drivers&lt;/STRONG&gt;&amp;nbsp; 
&lt;P&gt;If you want to support either S/PDIF or multiple discrete audio channels,&amp;nbsp;you&amp;nbsp;should probably want to start with the Ensoniq wavedev2 sample driver that &lt;BR&gt;shipped in the &lt;A class="" title="Windows CE 5.0 Networked Media Device Feature Pack" href="http://www.microsoft.com/downloads/details.aspx?FamilyID=bf17d6b0-4716-494b-9018-7deee9b91832&amp;amp;DisplayLang=en" mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyID=bf17d6b0-4716-494b-9018-7deee9b91832&amp;amp;DisplayLang=en"&gt;Windows CE 5.0 Networked Media Device Feature Pack&lt;/A&gt; for CE 5 under public\fp_nmd\common\oak\drivers\wavedev\wavedev2\ensoniq. (Note: everything in this feature pack was rolled forward to CE6 as well, so there's nothing in the feature pack that isn't available in CE6 as well, although it might be in a different place). 
&lt;P&gt;This version of the Ensoniq driver has S/PDIF support built into it (the Ensoniq 1371 chip has a sort-of-undocumented S/PDIF mode which we &lt;BR&gt;take advantage of), and supports passing WMAPro-over-S/PDIF compressed date. Support for AC3-over-S/PDIF would be a fairly trivial modification.&lt;/P&gt;
&lt;P&gt;One other issue with passing compressed data over S/PDIF is that&amp;nbsp;since the data isn't decompressed to PCM until it gets to your &lt;BR&gt;receiver, there's no way for you to programatically control the volume or mix it with other PCM audio data. The former isn't really a big &lt;BR&gt;issue (the user can always control the volume on their receiver). The latter doesn't have a really great solution. &lt;/P&gt;
&lt;P&gt;In the sample Ensoniq driver, whenever we're playing compressed WMAPro out the S/PDIF port we just throw away any PCM data that we're asked to &lt;BR&gt;play so it's never heard (although we maintain the appropriate playback timing, so from the application standpoint everything appears to behave as expected). &lt;/P&gt;
&lt;P&gt;To support multichannel discrete outputs in the wave driver one would need to modify the driver to accept a WAVEFORMATEX structure which looks like a normal PCM format but for which the nChannels field is 6 (or more). This is not be a trivial exercise, but should be pretty straightforward. As part of this, for wavedev2 one would have to rewrite the output.cpp file to add a new output stream class that accepts 6 streams, and modify the render functions that handle sample-rate-conversion to support all 6 channels. &lt;/P&gt;
&lt;P&gt;Note that the kernel software mixer only supports stereo streams, so it won't do any multichannel mixing for you. This is one reason wavedev2 is probably a good starting place, as it already has code built into it to mix stereo streams which could be extended to&amp;nbsp;more channels.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;DirectShow Filters&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;DirectShow is Windows CE's media processing infrastructure. The&amp;nbsp;architecture is media-type agnostic, meaning that there's nothing in the overall design that makes it support one type of media any better than another. A number of outside customers are working on multichannel audio products using their own DirectShow filters&amp;nbsp;(or filters they licensed from third-parties). The description below only discusses what Microsoft currently ships with CE5 and CE6.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;WMAPro-over-SPDIF filter: The abovementioned&amp;nbsp;Feature Pack also includes a WMAPro-over-SPDIF DirectShow filter to massage WMAPro data into a format which can be sent over S/PDIF. Used in conjunction with a wave driver that supports WMAPro-over-SPDIF content and a receiver which supports decoding WMAPro, this allows a the best decoding quality and performance. To be honest, this isn't currently a terribly common scenario given the limited&amp;nbsp;WMAPro receiver penetration in the market; we did this partly as a proof-of-concept, partly to support our own (Microsoft) technology, and partly because all the pieces were available to us within the company so it wasn't a major development effort. In addition, the&amp;nbsp;architecture and driver changes are applicable to other more common formats (e.g. AC3);&amp;nbsp;although we don't currently ship any explicit support for AC3 streams, OEMs have implemented AC3 support using a similar set of components based on some of this work.&lt;/P&gt;
&lt;P&gt;WMAPro decoder: Windows CE includes a WMAPro decoder to decode 5.1, 6.1, and 7.1 compressed content.&amp;nbsp;However, when CE5 was first shipped all our existing customers&amp;nbsp;were still using stereo outputs, so there was&amp;nbsp;no value in passing the discrete channels down to the wave driver. Therefore, while the version that shipped in CE5 decodes all the discrete channels internally, it downmixes them to stereo for output. Therefore, there is currently no way to get the discrete channels out of the WMAPro decoder. The NMD feature pack improved on this situation by introducing matrix-encoding into downmix algorithm: a receiver supporting&amp;nbsp;Pro Logic or Pro Logic II should be able to make use of this information to partially regenerate the discrete channels which were lost during the downmix. We'll look into improving this situation if there's sufficient customer demand. &lt;/P&gt;
&lt;P&gt;Dolby AC3: Dolby AC3 is &amp;nbsp;probably the most common/popular multichannel format. Microsoft doesn't currently ship a Dolby AC3 Directshow decoder, although there are probably lots of third party companies that produce such a thing and there may be open source versions (google "ac3filter"). &lt;BR&gt;&lt;/P&gt;
&lt;P&gt;That's all I've got for now. Please let me know if you found this useful, if there were any errors, or if you have any questions.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Responses to comments (if I misunderstood anyone's question, please let me know):&lt;/P&gt;
&lt;P mce_keep="true"&gt;1. How can I playback audio content&amp;nbsp;simultaneously to both&amp;nbsp;analog audio jacks and S/PDIF (Ianbing)&lt;/P&gt;
&lt;P mce_keep="true"&gt;If I understand correctly, you're trying to play the same audio content over two connections simultaneously (one RCA analog audio jack, and one S/PDIF jack). Assuming that's correct:&lt;BR&gt;- If your audio hardware can simultaneously send a single audio stream over both connections, have the audio driver handle it internally and just expose a single device at the waveapi level.&lt;BR&gt;- If you have two separate pieces of audio hardware (one to handle analog, the other for S/PDIF), you'll need to split the PCM output of the decoder (using a Tee filter- I think there's one under public\directx\sdk\samples\dshow\filters\inftee) and hook both outputs of the tee to the wave renderer. &lt;/P&gt;
&lt;P mce_keep="true"&gt;The latter design causes an additional problem because you'll need a way to tell each renderer which audio device to playback to. To do this, you'll need to hand-construct the graph, get pointers to each of the two audio render filters, and tell&amp;nbsp;each wave renderer&amp;nbsp;which device ID to play to. I don't believe I've ever tried this, but it should be possible by creating an IPropertyBag object (I think you'll have to roll-your-own, but it's not too difficult), setting the "WaveOutId" property to the ID you want to use, and pass that propertybag to the IPersistProperty interface on the wave renderer.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Your code would look something like this (sorry, I haven't compiled/tested this):&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT face="courier new,courier" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// CPropertyBag is your implementation of the IPropertyBag interface. &lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT face="courier new,courier" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // We might have a public sample&amp;nbsp;of this (search for cpropertybag.cpp), but I'm not sure&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;FONT face="courier new,courier" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CPropertyBag PropertyBag;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&lt;FONT size=2&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&lt;FONT size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Setup your desired device ID&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&lt;FONT face="courier new,courier" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; VARIANT var;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT face="courier new,courier"&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var.vt = VT_I4;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT face="courier new,courier"&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var.lVal = &amp;lt;desired device ID&amp;gt;;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&lt;FONT face="courier new,courier" size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&lt;FONT face="courier new,courier" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Write the desired ID to your property bag&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT size=2&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PropBag.Write( L"WaveOutId", &amp;amp;var ));&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT face="courier new,courier" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Find the waveout renderer in the graph that you want to talk to...&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT face="courier new,courier"&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT face="courier new,courier" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // QI for the IID_IPersistPropertyBag interface... something like this...&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT face="courier new,courier"&gt;&lt;FONT size=2&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT face="courier new,courier"&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IPersistPropertyBag *pPersistPropertyBag = NULL;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pWaveOutFilter-&amp;gt;QueryInterface(IID_IPersistPropertyBag, (void **)&amp;amp;pPersistPropertyBag);&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;o:p&gt;&lt;FONT face="courier new,courier" size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT size=2&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Pass the property bag into the wave renderer&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 'Courier New'"&gt;&lt;FONT face="courier new,courier"&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pPersistPropertyBag-&amp;gt;Load( &amp;amp;PropBag, NULL );&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&lt;/FONT&gt;
&lt;P mce_keep="true"&gt;Deep inside the Load call, the waveout renderer will do something like this with the PropBag pointer you passed in:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; VARIANT var;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var.vt = VT_I4;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HRESULT hr = pPropBag-&amp;gt;Read(L"WaveOutId", &amp;amp;var, 0);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(SUCCEEDED(hr))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_iWaveOutId = var.lVal;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1479563" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/medmedia/archive/tags/WaveAPI/default.aspx">WaveAPI</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Andy+Raffman/default.aspx">Author: Andy Raffman</category></item><item><title>Windows CE Audio: What does the term "mixer" mean?</title><link>http://blogs.msdn.com/medmedia/archive/2007/01/12/what-do-you-mean-by-mixer.aspx</link><pubDate>Fri, 12 Jan 2007 23:14:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1457048</guid><dc:creator>Andy Raffman</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/1457048.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=1457048</wfw:commentRss><description>&lt;P&gt;In the Windows CE audio stack, the term "mixer" is used to refer to a couple of different, unrelated components. This blog will try to define each of them and how they differ.&lt;/P&gt;
&lt;P&gt;There are usually three different contexts in which "mixer" is used: the "Software Mixer", the "WaveDev2 Mixer", and the "Mixer API". &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;The "Software Mixer"&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Inside the waveapi module there is a software mixer, sometimes also called the "kernel mixer", which can be used to mix and sample-rate-convert multiple PCM audio output streams. This software mixer was added in CE 4.2 to allow&amp;nbsp;audio drivers which only support one output stream to automagically support multiple concurrent streams at different sampling rates. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Internally, the software mixer spins off a thread for each wave device to which it's attached. This thread takes application audio buffers and mixes them together into a set of mixer buffers which are then passed down to the audio driver. During this process the software mixer performs these tasks:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Converts all data to a common 16-bit 2-channel (stereo) format. &lt;BR&gt;&lt;BR&gt;Note that this means that for an audio driver to work with the software mixer it &lt;U&gt;must&lt;/U&gt; support 16-bit stereo data. If your underlying hardware only supports mono data and you want to make use of the software mixer, your audio driver&amp;nbsp;will need to accept the stereo data and mix it down internally to mono. In this scenario if an application passes mono data down through the stack, the software mixer will&amp;nbsp;duplicate it&amp;nbsp;to the two audio channels and the driver will then remerge the data: not elegant, but the typical performance impact is trivial.&lt;BR&gt;&lt;BR&gt;The mixer only supports application buffers with PCM formats of&amp;nbsp;8/16 bit samples and mono/stereo channels. The software mixer can't handle compressed data and can't handle multichannel (e.g. 5.1) PCM data. If you need the software mixer to play any of these formats, they need to be converted to something the mixer understands (e.g. 16-bit stereo PCM) first. This is typically done at the DShow or ACM level, above the software mixer. It only becomes an issue if you want to pass compressed or multichannel audio to the driver. When the software mixer sees a format it doesn't recognize or support, it steps out of the way and passes the waveOutOpen request directly to the device driver. At that point it's totally up to the driver to decide how to handle the request.&lt;BR&gt;&lt;BR&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Sample-rate-converts all data to whatever sample rate the driver requires. &lt;BR&gt;&lt;BR&gt;The sample-rate-converter is currently a 5-point FIR. Without going into too much detail, the quality and performance have historically been a fairly good tradeoff for most devices, although there's certainly work we'd like to do in the future to improve the quality and performance.&lt;BR&gt;&lt;BR&gt;Note that to do the sample rate conversion the mixer needs to know what sample rate the wave driver requires (or pick a reasonable default). I'll cover how this works in another blog entry, along with other configuration details and some more info about the internal design.&lt;BR&gt;&lt;BR&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Performs per-stream gain control. &lt;BR&gt;&lt;BR&gt;When an application calls waveOutSetVolume and passes a wave handle, the software mixer absorbs the call and handles this, so it will never be seen by the driver (the driver will still see waveOutSetVolume calls using a device ID though).&lt;BR&gt;&lt;BR&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;Implements support for waveOutSetRate.&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;The "WaveDev2 Mixer"&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The WaveDev2 sample wave driver includes its own output mixer to mix PCM wave streams. This mixer performs basically the same function as the software mixer. Why do we have more-or-less the exact same feature in two different places? You can read&amp;nbsp;my blog &lt;A id=ctl00___ctl00___ctl01___Results___postlist___EntryItems_ctl03_PostTitle href="http://blogs.msdn.com/medmedia/archive/2007/01/03/windows-ce-audio-driver-samples.aspx" mce_href="http://blogs.msdn.com/medmedia/archive/2007/01/03/windows-ce-audio-driver-samples.aspx"&gt;&lt;FONT color=#0000cc&gt;Windows CE Audio Driver Samples&lt;/FONT&gt;&lt;/A&gt; for more background, but basically because:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;The waveapi software mixer didn't exist at the time WaveDev2 was developed (it first ran on CE 3.0).&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;The WaveDev2 mixer handles some proprietary calls that Smartphone/PPC need (see &lt;A id=ctl00___ctl00___ctl01___Results___postlist___EntryItems_ctl01_PostTitle href="http://blogs.msdn.com/medmedia/archive/2007/01/04/the-wavedev2-gainclass-implementation.aspx" mce_href="http://blogs.msdn.com/medmedia/archive/2007/01/04/the-wavedev2-gainclass-implementation.aspx"&gt;&lt;FONT color=#0000cc&gt;The Wavedev2 Gainclass Implementation&lt;/FONT&gt;&lt;/A&gt;). Someday we might fold those into the software mixer, but it hasn't happened yet.&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;The WaveDev2 mixer uses a less-cpu-intensive linear interpolation algorithm to perform mixing, and runs in the context of the driver's IST rather than a separate thread. This yields better performance in terms of CPU bandwidth, battery life, and latency (all of which are really important on battery-powered mobile devices).&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;Having the same feature in two different places and with slightly different/incompatible feature sets is generally not a good thing. Someday we'll&amp;nbsp;rationalize this&amp;nbsp;situation so the mixer only exists in one place.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The WaveDev2 sample driver also supports "input mixing"; this isn't really mixing, but it allows a single hardware input stream to be split and sample-rate-converted to multiple input clients. I'm including it here because inside the driver it shares the same architecture and alot of the same code paths.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The other difference between the Software Mixer and&amp;nbsp;the&amp;nbsp;WaveDev2 Mixer is that the former is in private code and isn't generally modifiable by OEMs, while the latter, being part of the OEM device driver, may be modified as needed. This can be a good or bad thing (depending on your desire to change the code and your expertise at not breaking it ;-)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;The "Mixer API"&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;While the Software Mixer and WaveDev2 MIxer are concerned with mixing PCM audio streams coming down through the Wave API, there's a totally different and unrelated thing called the "Mixer API". &lt;/P&gt;
&lt;P mce_keep="true"&gt;The Mixer API is an API which conceptually sits alongside other top-level APIs like the Wave API, ACM API, TAPI API, etc. The role of the Mixer API is to expose various low-level audio-related controls&amp;nbsp;at the application level (e.g. things like volume, bass/treble, surround sound, etc.). When someone talks about the Mixer API, they're talking about the set of APIs including mixerOpen, mixerClose, etc. An MSDN reference page is here &lt;A href="http://msdn2.microsoft.com/en-us/library/ms705739.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms705739.aspx"&gt;http://msdn2.microsoft.com/en-us/library/ms705739.aspx&lt;/A&gt;, and there are some interesting discussions of the Mixer API here &lt;A class=l onmousedown="return clk(this.href,'','','res','1','')" href="http://www.borg.com/~jglatt/tech/mixer.htm" mce_href="http://www.borg.com/~jglatt/tech/mixer.htm"&gt;&lt;B&gt;&lt;FONT color=#551a8b&gt;Mixer API&lt;/FONT&gt;&lt;/B&gt;&lt;/A&gt;&amp;nbsp;and here &lt;A class=l onmousedown="return clk(this.href,'','','res','6','')" href="http://blogs.msdn.com/larryosterman/archive/2005/06/14/428962.aspx" mce_href="http://blogs.msdn.com/larryosterman/archive/2005/06/14/428962.aspx"&gt;&lt;FONT color=#551a8b&gt;Larry Osterman's WebLog : Mapping audio topologies to mixer topologies&lt;/FONT&gt;&lt;/A&gt;, &lt;/P&gt;
&lt;P mce_keep="true"&gt;I believe the mixer API was first introduced as part of the Windows Sound System (WSS) DDK. The Windows Sound System was a hardware reference design that Microsoft&amp;nbsp;developed in the early 1990's to evangelize audio hardware support on the PC platform. One of the features of WSS was inclusion of a Crystal Semiconductor 4231 codec, which eventually evolved into the AC'97 codec spec. This codec had a number of hardware mixing and volume control&amp;nbsp;features to support multiple inputs and outputs (&lt;A class=l onmousedown="return clk(this.href,'','','res','3','')" href="http://web.mit.edu/afs/sipb/contrib/doc/specs/ic/audio/cs4231a.pdf"&gt;&lt;FONT color=#551a8b&gt;cs4231a multimedia audio codec&lt;/FONT&gt;&lt;/A&gt;), but there was no API defined to allow applications to access them. Thus was born the mixer API.&lt;/P&gt;
&lt;P mce_keep="true"&gt;The Mixer&amp;nbsp;API was designed to allow a mixer application with no knowledge of the underlying audio architecture to create interactive UI&amp;nbsp;for the end user. As a consequence, the Mixer API allows the application to query information suggesting what type of UI element to use to represent a control (e.g. a pushbutton, slider, multiple-select, etc.), and even query the labels that the application should display. On the desktop windows, when you run SndVol32 to bring up the mixer control panel (which uses the desktop's implementation of Mixer API), remember that SndVol32 has absolutely no a priori knowledge of what your soundcard supports. All those labels and controls are derived by calling down to the driver level.&lt;/P&gt;
&lt;P mce_keep="true"&gt;All MixerAPI calls into the audio device driver&amp;nbsp;are done via an IOCTL_MIX_MESSAGE IoControl.&amp;nbsp;An audio driver can add support for the mixer API by adding support for this call and the myriad messages that route through it. Although&amp;nbsp;Windows CE audio sample drivers typically include sample code to support for the mixer API, in general it's an optional part of the wave driver and&amp;nbsp;there are&amp;nbsp;very few&amp;nbsp;applications that make use of&amp;nbsp;it (although there are some, notably VoIP).&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1457048" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/medmedia/archive/tags/WaveAPI/default.aspx">WaveAPI</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Andy+Raffman/default.aspx">Author: Andy Raffman</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/MixerAPI/default.aspx">MixerAPI</category></item><item><title>FAT Filesystem Performance Issues for DVR</title><link>http://blogs.msdn.com/medmedia/archive/2007/01/04/fat-filesystem-performance-issues.aspx</link><pubDate>Fri, 05 Jan 2007 01:33:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1413076</guid><dc:creator>Andy Raffman</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/1413076.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=1413076</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Time to switch gears a bit away from audio...&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;First a minor digression into what we were building (which some people may find interesting, and this is still a Multimedia blog ;-). Then I'll get to how this involves the FAT filesystem.&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;One of the major components of the Tomatin feature pack was a DVR&amp;nbsp;engine to allow OEMs to develop their own digital video recorders for IP video broadcasts. At its heart, a DVR must support the ability to&amp;nbsp;write a video stream to hard disk&amp;nbsp;and&amp;nbsp;at the same time read a video stream back from hard disk for playback, all at real-time speeds and without glitches or dropouts. Other important features include the ability to fast-forward and rewind playback (while still displaying video onscreen). &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;The core DVR design was ported from another Microsoft team building an NTSC broadcast DVR. I'm never sure how much info I can give out in these blogs about other groups and project code names, so I don't mean to deny credit- those guys (IMHO) did a nice job and delivered to us exactly what they promised (how often can you say that about code that gets dropped in your lap from another team). &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;In any case, their DVR implementation included a hardware decoder which took NTSC video and encoded it to an MPEG2 Program Stream. The DVR engine handled writing/reading this stream to/from a hard disk, and also managed a myriad of other details like tracking and indexing key frames for fast forward/rewind/seek, managing&amp;nbsp;A/V synchronization, compensating for drift between the&amp;nbsp;record and playback streams, and a ton of other stuff. The output of the DVR engine was also an MPEG2 Program Stream, for which they had a hardware decoder which would generate and output the final video and audio data.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;IPTV systems typically&amp;nbsp;transmit their data as MPEG2 Transport Streams. These are somewhat different from MPEG2 Program Streams, and the two are neither subsets nor supersets of each other. To convert from one to the other you really need to do a full demultiplex/remultiplex operation. The bad news for us was that our DVR was designed to accept Program Streams, not Transport Streams; and we frankly didn't have the time or expertise to rewrite and retest that portion of the code. The good news was that IPTV hardware typically includes a Transport Stream demultiplexer which can produce demultiplexed (AKA elementary) video and audio streams, so we just needed to remultiplex the streams to get a Program Stream. The bad news was that we didn't have such a multiplexer, nor did anyone else inside of Microsoft as far as we could tell.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;To make a long story short, one of our developers&amp;nbsp;wrote, from scratch,&amp;nbsp;an MPEG2 Program Stream multiplexer which takes&amp;nbsp;elementary audio and video streams&amp;nbsp;and turns them into&amp;nbsp;an&amp;nbsp;MPEG2 Program Stream suitable for use by the DVR engine. This DShow component shipped as part of the Tomatin feature pack. &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;For testing purposes, we also ported the desktop's implementation of the MPEG2 Transport/Program Stream Demultiplexer. We used this component strictly for our own testing, and never ran it through its own system/unit test cycle, so this component didn't ship with Tomatin. However, it did turn out to be quite stable and it was made available at&amp;nbsp;&lt;A href="http://codegallery.gotdotnet.com/wincedemux" mce_href="http://codegallery.gotdotnet.com/wincedemux"&gt;&lt;SPAN style="COLOR: windowtext"&gt;http://codegallery.gotdotnet.com/wincedemux&lt;/SPAN&gt;&lt;/A&gt;. &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Back to our story...&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;At the start of the project our goal was to record and playback standard definition content (e.g. 640x480). Partway through the project&amp;nbsp;a key OEM came onboard and&amp;nbsp;added the requirement to handle HDTV content at 20Mbit/sec. Ugh.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;The hardware this had to run on was&amp;nbsp;essentially a low-end x86-compatible processor with hardware acceleration of MPEG2 TS demultiplexing and audio/video decoding and playback. Storage was on&amp;nbsp;a fairly generic 7200RPM&amp;nbsp;300GB IDE hard disk. All our code had to do (performance wise) was remultiplex the elementary streams into a program stream, write it to disk, read it from disk, demultiplex it to separate audio and video streams, and send&amp;nbsp;those streams&amp;nbsp;to the decoding/playback hardware. While this might not seem like that much work, at 20Mbits/sec it was pretty tough to do on low-end x86 hardware, and we spent alot of time optimizing our inner loops (e.g. the code to scan for the next MPEG2 packet start code).&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;The only filesystem well tested and available from within Microsoft for WinCE is the FAT filesystem. We&amp;nbsp;had heard&amp;nbsp;anecdotal stories of&amp;nbsp; performance issues&amp;nbsp;with FAT&amp;nbsp;with large hard disks,&amp;nbsp;but we didn't have time in the schedule to write our own filesystem (we did spend a bit of time looking around for something elsewhere in the company that we could reuse, but ultimately didn't find anything suitable from a risk/schedule standpoint). &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;During design and testing we did experience a&amp;nbsp;number of bottlenecks due to the FATFS design, and we got really familiar with&amp;nbsp;the FAT FS architecture and its limitations. Ultimately, working with the filesystem team, we got fixes for issues that could be fixed (which have since been released as CE 5.0 QFEs), and developed workarounds in our code for problems inherent in the filesystem. That's what this blog is about. Keep in mind that I'm a multimedia guy, so I'll probably gloss over things a bit. Feel free to comment on things I get wrong or wasn’t clear about.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;To understand FAT limitations you need a little background.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Sectors: Sectors are the smallest unit of storage on a disk. A hard disk sector is (typically) 512 bytes. A 300GB hard disk will have approximately 586 million sectors.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Clusters: The cluster is a logical grouping of sectors. For a given FAT disk format, a cluster is made up of a fixed number of&amp;nbsp;sectors which is&amp;nbsp;a power of 2. Filesystems typically organize data at the cluster level. Choosing an appropriate cluster size is a trade-off: the bookkeeping overhead for a file is going to be proportional to the number of clusters it contains, and a file always utilizes an integer number of clusters. If you choose too small a cluster size, the amount of overhead (both storage and CPU) associated with a file may be quite large. If you choose too large a cluster size, you'll end up wasting unused cluster space at the end of each file. (Note: Other non-FAT filesystems have come up with a variety of ways to alleviate this problem, but we're dealing with FAT here).&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;FAT: The FAT, or File Allocation Table, is an array at the start of the disk where each element in the array is associated with a specific cluster. There are different variants of FAT which are represented by the size of each FAT entry.&amp;nbsp;We're only interested in FAT32, where each FAT entry is a 32-bit value, and which is the only version appropriate for relatively large hard disks. &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;For FAT32 the cluster size may vary depending on how it was formatted. However, the maximum cluster size for FAT32 is 32k, which is 64 sectors. On a 300GB hard disk there will be roughly 9 million clusters. The FAT table itself will take approximately 37.5MB of disk space, spanning 73 thousand sectors. If you've enabled the backup FAT table, the FAT filesystem keeps&amp;nbsp;an additional&amp;nbsp;copy of the FAT (I'm not sure if it does this by default, or if that's controlled by the FATFS_ENABLE_BACKUP_FAT flag). &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;This is one of the first limitations of the FAT design: the 32k maximum cluster size is too small for such large hard disks, and contributes to the&amp;nbsp;overhead in a variety of ways.&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Each entry in the FAT represents a specific cluster on the disk. The set of clusters which make up a specific file are tracked by using the FAT array as a singly linked list: the FAT entry for a given cluster will contain the number of the next cluster in the file. The FAT entry of the last cluster in the file will have the FAT entry value of 0xFFFFFFFF. To seek to a specific location in a file, one must traverse the entire FAT chain of that file to find the cluster associated with that location. A 4GB file will contain 125,000 clusters, so seeking to the end of&amp;nbsp;that file&amp;nbsp;will entail traversing 125,000 FAT entries. This is one source of performance bottlenecks.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Unallocated clusters are represented by the value 0 in the cluster's associated FAT entry. There is no mechanism built into the FAT on-disk architecture to track unallocated clusters. When allocating a new cluster to a file, the filesystem code must search the FAT until it finds an unallocated cluster. On a large mostly allocated hard disk this can take an extremely large amount of time- yet another bottleneck.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;It might help to understand how FAT searches for a free cluster, which is optimized to attempt to allocate clusters contiguously: whenever FAT needs to allocate a new cluster to a file, it searches the FAT table starting at the &lt;U&gt;last&lt;/U&gt; cluster it successfully allocated. If you’re doing a single allocation of multiple clusters, it remembers (as a local variable in the loop) this last cluster it allocated to that specific file and will do a good job allocating contiguously from that point for that file. However, if you’re growing the file via individual cluster allocations (e.g. performing lots of relatively small append operations to the file to grow it), each allocation is going to start based on the last cluster allocated &lt;U&gt;on the volume&lt;/U&gt; (by any file, not just yours). In this case, if you’ve got multiple threads allocating individual clusters at the same time, there’s a higher probability the files are going to take alternating clusters, causing worse fragmentation.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Moving on to the directory structure: Each directory on a disk consists of a file entry table. Each file within a directory occupies an entry in that&amp;nbsp;table (I'll get to long file names in a bit). Each of these entries includes (among other things) the file's 8.3 filename, the index of the first cluster in the file, and a 32-bit filesize. The use of a 32-bit filesize means that individual files are limited to 4GB. This is another limitation, especially for DVR scenarios where extremely large files may be generated.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;File entries within a given directory are not kept in any particular order. When a file is opened, the table for the directory is scanned, starting at the begining, to search for the file. When a new file is created, the entire table for that directory must be scanned to determine if the file already exists. When a file is deleted, the entry for that file is cleared, but the remainder of the table is not repacked to reclaim the entry (although the entry may be reused if a new file is created). What all this means is the amount of time to open or create a file in that directory will rise linearly with the number of files in that directory. A directory with a large number of files&amp;nbsp;may&amp;nbsp;impact performance.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;The use&amp;nbsp;of long file names can impact directory performance as well:&amp;nbsp;long file names are allocated as&amp;nbsp;additional directory entries, so each normal file which also includes a long file name will&amp;nbsp;occupy additional directory entries. On WinCE, long filenames do not need to be generated if the filename is 8.3 compatible: it must contain all uppercase characters, no unicode characters, and be no longer than 8 characters long with no more than a 3 character extension. For example, FILENAME.TXT would not generate a long filename and uses only one directory entry. FileName.Txt, filename.txt, and&amp;nbsp;FILENAME0.TXT&amp;nbsp;would all genenerate&amp;nbsp;a long filename. Frankly, this wasn't something we thought of during the DVR project (I didn't think of it until I started working on this blog).&amp;nbsp;Our DVR&amp;nbsp;filenames weren't 8.3 compatible and thus did generate long filenames, but we never observed a problem caused by this that I recall.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;As an aside: during our testing we hit a bug in the FAT Filesystem code (which has since been fixed via QFE). There was an overflow in the cluster calculation when creating files which used the last cluster before the 4GB limit (i.e larger than 4GB-32K). The&amp;nbsp;result was that that when attempting to create a file of that size, the system would allocate all available clusters on the disk to the file until it ran out of disk space and returned a failure code. At that point the disk would be left in a state where the directory would show the file we created as having 0 bytes allocated to it, yet the disk would appear full. Deleting the file would correct the situation.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Now, to summarize the problems we had, and the fixes or workarounds we came up with:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Calibri"&gt;1.&amp;nbsp; The 4GB filesize limit: There's really nothing that can be done about this. For our project the DVR engine code was already&amp;nbsp;designed to record video streams as a set of relatively small files (e.g. holding a few minutes of data each),&amp;nbsp;rather than one large file. This solved a couple of different problems: it avoided the 4GB filesize limit and&amp;nbsp;it reduced the seek overhead of large files. It also solved a problem peculiar to DVR implementations: when recording to a "temporary" buffer which should only keep the last 60 minutes of video, one needs&amp;nbsp;to conceptually record to the end of the file while simultaneously truncating the file from the beginning. There's no way to do this with a single file, whereas with multiple files it can be done easily by just deleting the earliest file in the set. I believe we ended up with files in the 128MB to 256MB range (this is a registry-tunable parameter).&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Calibri"&gt;2.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Seeking within very large files: When seeking within a file, we have to traverse the file’s FAT chain to find the desired cluster. As the file grows toward the 4GB filesize limit, the number of links that need to be traversed gets very large (for 32k clusters, up to 2^17 entries). As mentioned above, we partially avoided this issue by not using the full 4GB filesize available to us. &lt;BR&gt;&lt;BR&gt;However, at the same time, the Filesystem team developed an improved algorithm which should greatly help this situation: The original FAT code we were working with included a single per-open-file 32-bit cached entry of the last cluster accessed within the file, so sequential reads/writes always hit this cache and didn’t need to retraverse the FAT chain. However, for DVR applications we were sometimes thrashing this entry by simultaneously reading and writing different locations within the file.&amp;nbsp;The recent&amp;nbsp;QFE fixed this by adding additional cache entries so multiple threads shouldn’t thrash against each other.&amp;nbsp; There are probably still pathological situations which might have perf issues (e.g. repeatedly seeking backward within a very large file). Note- the “cache” entries I’m talking about here are &lt;U&gt;not&lt;/U&gt; the same as the FAT cache I'll mention at the end of this blog: That's&amp;nbsp; a cache of&amp;nbsp;the actual sectors&amp;nbsp;comprising the&amp;nbsp;FAT table. Increasing the FAT cache size would also help this issue as well though. &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Calibri"&gt;3.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Appending to a file on a very large, almost full disk: When appending to the end of a file, we need to search the FAT table looking for a free cluster. On very large disks which are almost full this search can potentially take a very long time.&amp;nbsp;&amp;nbsp;The DVR code already had a&amp;nbsp;solution to this problem by spinning off a low-priority thread which would run&amp;nbsp;out ahead of our&amp;nbsp;disk-write thread and preallocate data files to be used later by the write thread. Since that time the filesystem team&amp;nbsp;has shipped a QFE which keeps an in-memory data structure to track free clusters; this QFE should greatly improve performance in this situation.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Calibri"&gt;4.&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Opening/creating a file in a directory filled with a large number of files: When you open or create a file, we need to search the directory looking for a file with the requested name (we need to do this even if creating a file to ensure we don’t create two files with the same name). If the directory has a very large number of files, this algorithm can take a long time. The FAT directory structure isn’t sorted and there’s no efficient way of searching it other than looking at every entry; the worst-case situation is creating a new file, since we need to search the entire list before we realize the entry doesn’t already exist.&amp;nbsp;There is no&amp;nbsp;QFE to solve this issue. Increasing the Data cache may help, but the best thing is not to create too many files within a single directory. &lt;BR&gt;&lt;BR&gt;This was a serious issue for our DVR code, which was creating hundreds of files. However, we had control over the filesystem names (which were typically something like xxxx0000.yyy, xxxx0001.yyy, xxxx0002.yyy) and where they were stored. Our solution was to generate a directory&amp;nbsp;name&amp;nbsp;hash off of the filename and divide the files across multiple subdirectories.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Other useful bits of information:&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;The FAT filesystem code keeps in-memory caches for both the disk FAT and disk data. The sizes of these caches may be configured via the registry:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;[HKEY_LOCAL_MACHINE\System\StorageManager\FATFS]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "FatCacheSize"=0xXXXXX&amp;nbsp; - Size of the FAT Table Cache&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "DataCacheSize"=0xXXXX - Size of the Data Cache&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Where XXX is the number of sectors. Must be a power of 2 and at least 16 sectors. If 0, FATFS will determine best cache size.&amp;nbsp;&amp;nbsp; The maximum size that it defaults to is 256K which is way too small for 120G disk. Pick a number&amp;nbsp;and&amp;nbsp;multiply by 512: that is the amount of memory you will take.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;If you do need to preallocate space to a file, keep in mind that the minimum set of calls to do so are something like:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;hFile = CreateFile(szFilePath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;long FileSizeLow = 0x80000000;&lt;SPAN style="mso-tab-count: 1"&gt;&amp;nbsp; &lt;/SPAN&gt;// e.g. create a 2GB file&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;long FileSizeHigh = 0;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;dwRet = SetFilePointer(hFile, FileSizeLow, &amp;amp;FileSizeHigh, FILE_BEGIN);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;bRet = SetEndOfFile(hFile);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;CloseHandle(hFile);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;You do not need to actually write any data (doing so would just be wasted overhead).&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Note that the docs on SetFilePointer are a little vague; you &lt;U&gt;must&lt;/U&gt; include the &amp;amp;FileSizeHigh param: a side-effect of including this is to force SetFilePointer to interpret FileSizeLow as an unsigned value rather than a signed value. The other caveat is that if you’re preallocating the file you’ll need to keep track of how much data you’ve actually written to the file elsewhere (you can’t rely on GetFileSize, or just seeking to the end of the file and writing to append data to the file).&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;Finally, I should note that the ExFAT filesystem&amp;nbsp;which was recently shipped with&amp;nbsp;Windows CE 6.0 should further alleviate some of these issues.&amp;nbsp;My understanding is that ExFAT supports files larger than 4GB and implements bitmap-based unallocated-cluster mechanism. I'm not intimately familiar with it though and haven't tried it yet, so I can't go into any more detail.&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;That’s about all I have in me for now. Feel free to leave any comments, good or bad.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;-Andy Raffman&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN style="FONT-SIZE: 11pt; COLOR: #1f497d; FONT-FAMILY: 'Calibri','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1413076" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Andy+Raffman/default.aspx">Author: Andy Raffman</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/FAT+Filesystem/default.aspx">FAT Filesystem</category></item><item><title>The Wavedev2 Gainclass Implementation</title><link>http://blogs.msdn.com/medmedia/archive/2007/01/04/the-wavedev2-gainclass-implementation.aspx</link><pubDate>Thu, 04 Jan 2007 21:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1411854</guid><dc:creator>Andy Raffman</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/1411854.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=1411854</wfw:commentRss><description>&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Goals&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Back in 2000, while we were defining the&amp;nbsp;requirements for the&amp;nbsp;Windows Mobile Smartphone audio design, one of our goals was to mute most audio applications while a phone call is in progress. &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman','serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman','serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;A secondary issue is the fact that most of the time the user keeps their phone in their pocket or backpack, or is holding it out in front of them looking at the screen. In this situation we need to play notifications and incoming rings loud enough to be heard. However, during a phone call the phone is being held tightly to the user's&amp;nbsp;ear, and a sound played&amp;nbsp;loudly enough to be heard in the first situation&amp;nbsp;would be far too loud.&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman','serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman','serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;A final goal was to minimize any changes at the application level. We didn't want applications to need to monitor whether we were in a call and adjust their own volume level, or even require any modifications at all to third party applications that wanted some reasonable behavior. &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman','serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman','serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Design&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;To solve these problems, the wavedev2 audio driver implements something we called gain classes. Each wave stream is associated with a specific gain class, and the driver implements an additional gain control for each of these classes. This additonal gain is separate from the controls exposed by waveOutSetVolume, and is transparent to the application. The effects of the various gain controls are cumulative: the total gain applied to a specific output stream will therefore be the product of the stream gain, the device gain, and the class gain.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;A quick digression here: there&amp;nbsp;are two standard ways that an application can control&amp;nbsp;the volume of a wave stream, each of which involves a call to waveOutSetVolume. &lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Calling waveOutSetVolume and passing in a wave device ID is used to set the device gain, and will theoretically affect all streams playing on the device. &lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Calling waveOutSetVolume and passing in a wave handle (the thing you get back from waveOutOpen) is used to set the stream volume, and will only affect that stream.&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;By the way, a common (and hard to diagnose) application error is trying to call waveOutSetVolume on a wave handle before the handle has been initialized to something other than 0. This won't generate an error: the call will be interpreted as a request to change the device volume of device ID 0 (typically the only device in the system), which will affect all the volume of all the other apps in the system.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman','serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Application Usage&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Whenever an application opens a wave stream, that stream is automatically associated with class 0. However, applications may move their stream to a different class by calling waveOutMessage with the proprietary MM_WOM_SETSECONDARYGAINCLASS. For example, to open a stream and associate it with class 2&amp;nbsp;one would do the following:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; BACKGROUND: white; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; waveOutOpen(&amp;amp;hWaveOut, ...);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; BACKGROUND: white; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; BACKGROUND: white; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;// Set gain class to 2&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; BACKGROUND: white; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; waveOutMessage(hWaveOut, MM_WOM_SETSECONDARYGAINCLASS, 2, 0);&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; BACKGROUND: white; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; BACKGROUND: white; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Classes are differentiated from each other in two ways:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraph style="MARGIN: auto 0in auto 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;During a call, the amount of attenuation is controlled on a per-class basis. Some classes may be muted; others are attenuated (made a little more quiet on the assumption that the phone is being held up to the user’s ear); and others may have no attenuation at all. The amount of attenuation is controlled by the shell based on a set of registry values.&lt;BR style="mso-special-character: line-break"&gt;&lt;BR style="mso-special-character: line-break"&gt;&lt;SPAN style="BACKGROUND: white"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraph style="MARGIN: auto 0in auto 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo1"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;Each class may or may not be affected by the “system volume”. This behavior is hard-coded in the audio device driver.&lt;SPAN style="BACKGROUND: white"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;In the currently shipping implementation there are four classes with the following behavior:&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Times New Roman','serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;TABLE class=MsoTableGrid style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; MARGIN: auto auto auto 23.4pt; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-yfti-tbllook: 1184; mso-padding-alt: 0in 5.4pt 0in 5.4pt" cellSpacing=0 cellPadding=0 border=1 class="MsoTableGrid"&gt;
&lt;TBODY&gt;
&lt;TR style="mso-yfti-irow: 0; mso-yfti-firstrow: yes"&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: black 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: black 1pt solid; WIDTH: 26.85pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1" vAlign=top width=36&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Class&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: black 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 103.5pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1" vAlign=top width=138&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Behavior During Call&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: black 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 135pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1" vAlign=top width=180&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Affected by system volume&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: black 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 2in; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1" vAlign=top width=192&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Used by&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="mso-yfti-irow: 1"&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: black 1pt solid; WIDTH: 26.85pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1" vAlign=top width=36&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;0&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 103.5pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=138&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Muted&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 135pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=180&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Yes&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 2in; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=192&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Default setting for all sounds&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="mso-yfti-irow: 2"&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: black 1pt solid; WIDTH: 26.85pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1" vAlign=top width=36&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;1&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 103.5pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=138&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Attenuated&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 135pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=180&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Yes&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 2in; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=192&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;?&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="mso-yfti-irow: 3"&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: black 1pt solid; WIDTH: 26.85pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1" vAlign=top width=36&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;2&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 103.5pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=138&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Attenuated&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 135pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=180&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;No&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 2in; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=192&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Alarm, Reminder, Notification, Ring, In-call sounds&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="mso-yfti-irow: 4; mso-yfti-lastrow: yes"&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: black 1pt solid; WIDTH: 26.85pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1" vAlign=top width=36&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;3&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 103.5pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=138&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Muted&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 135pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=180&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;No&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 2in; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=192&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;System event sounds&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;In addition, future implementations supporting VoIP may include two additional classes which have no attenuation during a call:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;
&lt;TABLE class=MsoTableGrid style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; MARGIN: auto auto auto 23.4pt; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-yfti-tbllook: 1184; mso-padding-alt: 0in 5.4pt 0in 5.4pt" cellSpacing=0 cellPadding=0 border=1 class="MsoTableGrid"&gt;
&lt;TBODY&gt;
&lt;TR style="mso-yfti-irow: 0; mso-yfti-firstrow: yes"&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: black 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: black 1pt solid; WIDTH: 0.5in; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1" vAlign=top width=48&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Class&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: black 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 103.5pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1" vAlign=top width=138&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Behavior During Call&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: black 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 135pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1" vAlign=top width=180&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Affected by system volume&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: black 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 2in; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1" vAlign=top width=192&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Used by&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="mso-yfti-irow: 1"&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: black 1pt solid; WIDTH: 0.5in; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1" vAlign=top width=48&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;4&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 103.5pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=138&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;No attenuation&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 135pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=180&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Yes&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 2in; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=192&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;?&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR style="mso-yfti-irow: 2; mso-yfti-lastrow: yes"&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: black 1pt solid; WIDTH: 0.5in; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1" vAlign=top width=48&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;5&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 103.5pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=138&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;No attenuation&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 135pt; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=180&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;No&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" style="BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #ece9d8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0in; BORDER-LEFT: #ece9d8; WIDTH: 2in; PADDING-TOP: 0in; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid black .5pt; mso-border-themecolor: text1; mso-border-left-alt: solid black .5pt; mso-border-left-themecolor: text1; mso-border-top-alt: solid black .5pt; mso-border-top-themecolor: text1; mso-border-bottom-themecolor: text1; mso-border-right-themecolor: text1" vAlign=top width=192&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;?&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Shell Usage&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Normally, the gains of all classes are set to 0xffff, meaning there’s no attenuation. At the beginning of a phone call the shell calls MM_WOM_SETSECONDARYGAINLIMIT to attenuate each class by some amount, and calls it again during hangup to reset the attenuations. The code to do this looks something like:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (iClass=0;iClass&amp;lt;NUMCLASSES;iClass++)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;waveOutMessage(&amp;lt;device ID&amp;gt;, &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;MM_WOM_SETSECONDARYGAINLIMIT,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;iClass,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;lt;volume from 0-0xffff&amp;gt;);&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;The amount of attenuation which the shell applies during a call is controlled by the following registry keys:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;[HKEY_CURRENT_USER\ControlPanel\SoundCategories\Attenuation]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;"0"=dword:0&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;"1"=dword:2&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;"2"=dword:2&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;"3"=dword:0&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;The key name is the class index, and the associated value is the amount of gain to allow during a call. The value ranges from 0 to 5, with 0 meaning totally muted and 5 meaning no attenuation.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Note that existing apps which don’t set their class will default to class 0, will be muted during a call, and will be affected by system volume (which is generally the behavior that is desired).&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri"&gt;&lt;o:p&gt;&lt;FONT face=Calibri size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri"&gt;&lt;o:p&gt;&lt;STRONG&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;A note on volume values&lt;/FONT&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri"&gt;&lt;o:p&gt;&lt;STRONG&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri"&gt;&lt;o:p&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Volume levels are typically represented as unsigned 16-bit values, with 0xFFFF being full volume and 0x0000 representing the muted state. For example, waveOutSetVolume encodes the volume parameter as a 32-bit DWORD, with the lower 16 bits holding left channel volume and the upper 16 bits holding the right channel volume. On the other hand, the gain class API only accepts a single 16 bit value which is meant to apply to both channels (we didn't think there would be a need to attenuate left and right by different amounts).&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Historically there's been alot of disagreement over how these 16 bits map to actual dB attenuation values, and how the stream and device gains interact. In the wavedev2&amp;nbsp;sample driver&amp;nbsp;the behavior is as follows:&lt;/SPAN&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Stream gains map from 0 to -100dB attenuation. The&amp;nbsp;idea here was to provide applications with a large enough range to handle any potential situation and also maintain some compatibility with the desktop's usage in DirectSound, which uses the same 0 to -100dB range.&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Device gains map from 0 to -35dB attenuation. The idea behind this was that historically the device gain has been implemented by going directly to the codec hardware, which&amp;nbsp;at the time the API was designed typically was limited to something in the -32dB range.&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Gainclass gain values map from 0 to -100dB.&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;When calculating the aggregate attenuation of the various gain values, the code converts each gain value to a dB attenuation and then adds the attenuations. For example, if the stream gain is 0x8000 (half scale), the device gain is 0x8000 (also half scale), and the gainclass gain is 0xFFFF (no attenuation), the total attenuation would be (.5 * 100) + (.5 * 35) + (0 * 100) = -67.5dB. &lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Any gain value of 0 represents&amp;nbsp;the totally muted state.&amp;nbsp;For example, if the stream gain in the above calculation started of at 0x0000, the stream would be totally muted independent of the other gain values.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;The&amp;nbsp;calculation above and the ranges that each gain type maps to are implemented inside the wavedev2 driver, and OEMs may choose to modify the values to meet their specific needs.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;FONT size=3&gt;&lt;FONT face=Calibri&gt;Areas for improvement&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;In retrospect, there are a couple of things I wish we had done differently and which we’ll keep in mind for the future:&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraph style="MARGIN: auto 0in auto 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;We should have made the number of gain classes and how they’re affected by device volume programmable, rather than hard-coding them into the sample driver. With the current design whenever we need to add a new gain class, or change whether the device volume affects a given class, we need to touch the OEMs device driver. This is typically only a one or two line change, but it still makes life difficult.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraph style="MARGIN: auto 0in auto 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;There is currently no way to query the current attenuation level for a class.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraph style="MARGIN: auto 0in auto 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;The waveapi component of the core OS implements a “gain class” infrastructure as part of the software mixer component to accomplish a similar goal. However, this was implemented after wavedev2 had shipped and its design is incompatible with the way Smartphone needs it to work. This is the main reason Smartphone/PPC-Phone devices need to use wavedev2 as a starting point for a driver. It would be nice if waveapi’s software mixer implemented the same gain class design so we could pull the code out of wavedev2 and simplify its design.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraph style="MARGIN: auto 0in auto 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoListParagraph style="MARGIN: auto 0in auto 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;Responses to questions:&lt;/SPAN&gt;&lt;/P&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;1.&amp;nbsp;Where is MM_WOM_SETSECONDARYGAINCLASS&amp;nbsp;defined?&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;- It should be in audiosys.h, but that might have moved around a bit. The definitions you're looking for are:&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #define MM_WOM_SETSECONDARYGAINCLASS&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;(WM_USER)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #define MM_WOM_SETSECONDARYGAINLIMIT&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;(WM_USER+1)&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoPlainText style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #define MM_WOM_FORCESPEAKER&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;(WM_USER+2)&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=3&gt;&lt;FONT face=Consolas&gt;&lt;o:p&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;o:p&gt;Keep in mind that these are very likely to change or go away in future release of the operating system.&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1411854" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/medmedia/archive/tags/WaveAPI/default.aspx">WaveAPI</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Andy+Raffman/default.aspx">Author: Andy Raffman</category></item><item><title>The Wavedev2 MIDI Implementation</title><link>http://blogs.msdn.com/medmedia/archive/2007/01/03/the-wavedev2-midi-implementation.aspx</link><pubDate>Thu, 04 Jan 2007 10:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1409493</guid><dc:creator>Andy Raffman</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/1409493.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=1409493</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;The wavedev2 wave driver sample code includes a fairly primitive MIDI synthesizer as part of the source code. The reason for its relative simplicity dates back to the question: "What can you implement in two weeks with no additional ROM hit to run on a 100MHz ARM processor"? &lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;Seriously, the original goal was just to provide a sample implementation, with the assumption that OEMs would replace it by licensing or developing their own synthesizer (which, in fact, many OEMs do). We also (correctly, I believe) anticipated that in the future ringtones would more likely be implemented as compressed audio files (e.g. WMA). It made little sense to pour money/development resources into developing our own high-quality MIDI synthesizer, and there are third parties who handle that quite well anyway &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;(such as Beatnik).&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;Having said that, the wavedev2 sample still includes the primitive MIDI synthesizer, and it probably ships unmodified on some platforms, so it might be interesting to know how to use it.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000&gt;The wavedev2 sample MIDI synth has the following attributes:&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000&gt;- Instruments: Only sine wave generation, no other instruments.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000&gt;- Polyphony: No limit on the number of midi streams. Number of concurrent notes per stream is limited to 32 (controlled by a #define in the driver). Realistically, the total number of notes will be limited by the amount of CPU MIPS. I don’t think we’ll have any problem with 8-10 notes.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000&gt;- Sample accurate timing&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'"&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000&gt;- Extensions to support arbitrary frequency tone generation (e.g. for things like DTMF, ringback, busy, etc.) and tempo changes.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;The OS doesn't support the standard Win32 MIDI apis, so we had to invent our own somewhat proprietary method. To do this without creating new API entry points, we implemented MIDI as a proprietary wave format. To play MIDI notes, you open the wave device using waveOutOpen with a WAVEFORMAT_MIDI format structure, which is defined in wfmtmidi.h as:&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;typedef struct _WAVEFORMAT_MIDI&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;WAVEFORMATEX wfx;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;UINT32 USecPerQuarterNote;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;UINT32 TicksPerQuarterNote;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;} WAVEFORMAT_MIDI, *LPWAVEFORMAT_MIDI;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000 size=2&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif size=2&gt;The wfx.wFormatTag field should be filled in with WAVE_FORMAT_MIDI, which is defined in the header as:&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT size=2&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;FONT size=2&gt;#define WAVE_FORMAT_MIDI 0x3000&lt;/FONT&gt;&lt;BR&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif size=2&gt;(In retrospect we should have used a WaveFormatExtensible structure, which uses a GUID, rather than arbitrarily allocating another format tag, since there's a chance we'll collide with some other OEM format tag).&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;You then start passing buffers to the driver using waveOutMessage, just as you would for wave data. The data in the buffers consists of an array of WAVEFORMAT_MIDI_MESSAGE structures, which are defined as:&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 19pt; LINE-HEIGHT: normal"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;typedef struct _WAVEFORMAT_MIDI_MESSAGE&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 19pt; LINE-HEIGHT: normal"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;{&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 19pt; LINE-HEIGHT: normal"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; UINT32 DeltaTicks;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 19pt; LINE-HEIGHT: normal"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DWORD&amp;nbsp; MidiMsg;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 19pt; LINE-HEIGHT: normal"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;} WAVEFORMAT_MIDI_MESSAGE;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;The wave driver will automatically take care of the timing of when to sequence each midi message, based on the relationship between the DeltaTicks field of the next midi event and the USecPerQuarterNote and TicksPerQuarterNote fields of the WAVEFORMAT_MIDI structure.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT size=2&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;You can send just about any MIDI message to the driver, but the sample drivers only process the midi messages for “note on”, “note off”, and the control change message for “all notes off”; any other MIDI message will be ignored by the driver. &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;The sample driver also supports proprietary messages for playing an arbitrary frequency and for changing the tempo during playback: &lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 12pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;MIDI_MESSAGE_FREQGENON and MIDI_MESSAGE_FREQGENOFF are roughly analogous to NoteOn/NoteOff, but they take a 16-bit frequency value rather than a 7-bit note value, and they always play a sine wave. This can be useful for things like DTMF, ringback, busy, and other call progress tones which require exact frequencies and which don’t map exactly to the frequencies supported by the musical scale. For these messages, the upper 8 bits of MidiMsg (which are normally 0) are set to either MIDI_MESSAGE_FREQGENON or MIDI_MESSAGE_FREQGENOFF. The next 8 bits are the 7-bit velocity (e.g. volume) (the top bit must be 0), and the lowest 16 bits are the desired frequency.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;o:p&gt;&lt;FONT face=arial,helvetica,sans-serif color=#000000&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;FONT color=#000000&gt;MIDI_MESSAGE_UPDATETEMPO can be used to update the USecPerQuarterNote parameter in the middle of a stream. For these messages, the upper 8 bits of MidiMsg (which are normally 0) are set to either MIDI_MESSAGE_ UPDATETEMPO. The low 24 bits are the updated tempo value.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;Other notes:&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;While the MIDI synth handles sequencing and&amp;nbsp;tone generation, it doesn't include any provision for MIDI file parsing. If you want to play MIDI files, you'll need to implement a MIDI file parser, extract the data and timestamp information, and feed it down the the wave driver.&lt;BR&gt;&lt;/FONT&gt;&lt;/DIV&gt;&lt;/LI&gt;
&lt;LI&gt;
&lt;DIV mce_keep="true"&gt;The sample MIDI synth only supports sine waves, and has no concept of channels, instruments, or patch changes: all instruments are going to be remapped to sine wave tones. In general this yields&amp;nbsp;a recognizable melody, with one major exception: in MIDI, percussion is considered considered a single instrument, with different types of drums, symbols, etc. mapped to different note values. If you try to play an arbitrary&amp;nbsp;MIDI stream which includes percussion, the various&amp;nbsp;percussive sounds&amp;nbsp;are going to be played as apparently random sine waves.&amp;nbsp;It's going to sound awful.&lt;/DIV&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;I've appended two samples below. The first, miditest.cpp, plays a midi scale. The second plays a&amp;nbsp;ringback tone for 30 seconds.&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;STRONG&gt;miditest.cpp (plays an 8-note midi scale):&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;#include "windows.h"&lt;BR&gt;#include "wfmtmidi.h"&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;int _tmain(int argc, TCHAR *argv[])&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Code to play a simple 8-note scale.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned char Scale[8] =&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 63,65,67,68,70,72,74,75&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; };&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Build a MIDI waveformat header&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WAVEFORMAT_MIDI wfm;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; memset(&amp;amp;wfm,0,sizeof(wfm));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wfm.wfx.wFormatTag=WAVE_FORMAT_MIDI;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wfm.wfx.nChannels=1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wfm.wfx.nBlockAlign=sizeof(WAVEFORMAT_MIDI_MESSAGE);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wfm.wfx.cbSize=WAVEFORMAT_MIDI_EXTRASIZE;&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // These fields adjust the interpretation of DeltaTicks, and thus the rate of playback&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wfm.USecPerQuarterNote=1000000;&amp;nbsp;&amp;nbsp; // Set to 1 second. Note driver will default to 500000 if we set this to 0&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wfm.TicksPerQuarterNote=100;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Set to 100. Note driver will default to 96 if we set this to 0&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HANDLE hEvent;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hEvent = CreateEvent( NULL,TRUE,FALSE,NULL);&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MMRESULT Result;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HWAVEOUT hWaveOut;&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Open the waveout device&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result = waveOutOpen(&amp;amp;hWaveOut, 0, (LPWAVEFORMATEX)&amp;amp;wfm, (DWORD)hEvent, 0, CALLBACK_EVENT);&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (Result!=MMSYSERR_NOERROR)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return -1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Build a MIDI buffer with 16 MIDI messages.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int i,j;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WAVEFORMAT_MIDI_MESSAGE MidiMessage[16];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (i=0,j=0;i&amp;lt;8;i++,j+=2)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[j].DeltaTicks=100;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Wait 1 second : (DeltaTicks * (UsecPerQuarterNote/TicksPerQuarterNote))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[j].MidiMsg=0x7F0090 | ((Scale[i])&amp;lt;&amp;lt;8);&amp;nbsp;&amp;nbsp; // Note on&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[j+1].DeltaTicks=100;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Wait 1 second&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[j+1].MidiMsg=0x7F0080 | ((Scale[i])&amp;lt;&amp;lt;8); // Note off&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WAVEHDR WaveHdr;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaveHdr.lpData = (LPSTR)MidiMessage;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaveHdr.dwBufferLength = sizeof(MidiMessage);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaveHdr.dwFlags = 0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result = waveOutPrepareHeader(hWaveOut,&amp;amp;WaveHdr,sizeof(WaveHdr));&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Play the data&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result = waveOutWrite(hWaveOut,&amp;amp;WaveHdr,sizeof(WaveHdr));&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Wait for playback to complete&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaitForSingleObject(hEvent,INFINITE);&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Cleanup&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result = waveOutUnprepareHeader(hWaveOut,&amp;amp;WaveHdr,sizeof(WaveHdr));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result = waveOutClose(hWaveOut);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 0;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face=arial,helvetica,sans-serif&gt;&lt;STRONG&gt;tonetest.cpp (Plays a 30 second ringback tone):&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;#include "windows.h"&lt;BR&gt;#include "wfmtmidi.h"&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;/*&lt;BR&gt;DTMF frequencies:&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;DTMF stands for Dual Tone Multi Frequency. These are the tones you get when&lt;BR&gt;you press a key on your telephone touchpad. The tone of the button is the&lt;BR&gt;sum of the column and row tones. The ABCD keys do not exist on standard&lt;BR&gt;telephones.&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Frequency 1&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1209&amp;nbsp; 1336&amp;nbsp; 1477&amp;nbsp; 1633&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 697&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; A&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 770&amp;nbsp;&amp;nbsp; 4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; B&lt;BR&gt;Frequency 2&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 852&amp;nbsp;&amp;nbsp; 7&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 941&amp;nbsp;&amp;nbsp; *&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; D&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;Frequencies of other telephone tones&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;Type&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Hz&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; On&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Off&lt;BR&gt;---------------------------------------------------------------------&lt;BR&gt;Dial Tone&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 350 &amp;amp; 400&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ---&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ---&lt;BR&gt;Busy Signal&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 480 &amp;amp; 620&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.5&lt;BR&gt;Toll Congestion&amp;nbsp;&amp;nbsp; 480 &amp;amp; 620&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.3&lt;BR&gt;Ringback (Normal) 440 &amp;amp; 480&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2.0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4.0&lt;BR&gt;Ringback (PBX)&amp;nbsp;&amp;nbsp;&amp;nbsp; 440 &amp;amp; 480&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1.5&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4.5&lt;BR&gt;Reorder (Local)&amp;nbsp;&amp;nbsp; 480 &amp;amp; 620&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3.0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2.0&lt;BR&gt;Invalid Number&amp;nbsp;&amp;nbsp;&amp;nbsp; 200 &amp;amp; 400&lt;BR&gt;Hang Up Warning 1400 &amp;amp; 2060&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.1&lt;BR&gt;Hang Up&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2450 &amp;amp; 2600&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ---&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ---&lt;BR&gt;*/&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;int _tmain(int argc, TCHAR *argv[])&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WAVEFORMAT_MIDI wfm = {0};&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wfm.wfx.wFormatTag=WAVE_FORMAT_MIDI;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wfm.wfx.nBlockAlign=sizeof(WAVEFORMAT_MIDI_MESSAGE);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wfm.wfx.cbSize=WAVEFORMAT_MIDI_EXTRASIZE;&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Force each tick to be 1/10 sec&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wfm.USecPerQuarterNote=100000;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; wfm.TicksPerQuarterNote=1;&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MMRESULT Result;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HWAVEOUT hWaveOut;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HANDLE hEvent=CreateEvent( NULL,TRUE,FALSE,NULL);&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result = waveOutOpen(&amp;amp;hWaveOut, 0, (LPWAVEFORMATEX)&amp;amp;wfm, (DWORD)hEvent, 0, CALLBACK_EVENT);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (Result!=MMSYSERR_NOERROR)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return -1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create a buffer for 5 midi messages&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WAVEFORMAT_MIDI_MESSAGE MidiMessage[5];&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[0].DeltaTicks=0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[0].MidiMsg=0x207F0000 | 440;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Note on 440Hz&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[1].DeltaTicks=0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[1].MidiMsg=0x207F0000 | 480;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Note on 480Hz&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[2].DeltaTicks=20;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Wait 2 sec&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[2].MidiMsg=0x307F0000 | 440;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Note off 440Hz&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[3].DeltaTicks=0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[3].MidiMsg=0x307F0000 | 480;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Note off 480Hz&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[4].DeltaTicks=40;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Wait 4 sec&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MidiMessage[4].MidiMsg=0;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Dummy msg, does nothing&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WAVEHDR WaveHdr;&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Point wave header to MIDI data&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaveHdr.lpData = (LPSTR)MidiMessage;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaveHdr.dwBufferLength = sizeof(MidiMessage);&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Loop on this buffer 20 times&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaveHdr.dwFlags = WHDR_BEGINLOOP|WHDR_ENDLOOP;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaveHdr.dwLoops = 20;&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Play it!&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result = waveOutPrepareHeader(hWaveOut,&amp;amp;WaveHdr,sizeof(WaveHdr));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result = waveOutWrite(hWaveOut,&amp;amp;WaveHdr,sizeof(WaveHdr));&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Wait for it to be done or 30 seconds, whichever comes first&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WaitForSingleObject(hEvent,30000);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result = waveOutReset(hWaveOut);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result = waveOutUnprepareHeader(hWaveOut,&amp;amp;WaveHdr,sizeof(WaveHdr));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Result = waveOutClose(hWaveOut);&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 0;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Q&amp;amp;A (I'll start moving my responses to comments here):&lt;/P&gt;
&lt;P mce_keep="true"&gt;Q. I changed the definition of MidiMessage in the above sample to make it a dynamically allocated pointer, and now the sample doesn't work.&lt;/P&gt;
&lt;P mce_keep="true"&gt;A. You need to also change the line that says "&lt;FONT face="Courier New"&gt;WaveHdr.dwBufferLength = sizeof(MidiMessage);"&lt;/FONT&gt;&lt;FONT face=arial,helvetica,sans-serif&gt; or else dwBufferLength will end up being 4 (the size of your pointer) rather than the size of the buffer. If you don't, the call to waveOutPrepareHeader will fail, as will everything else past that point. Blame me for not doing error checking in the sample code above.&lt;/FONT&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Q. wmftmidi.h is no longer present in the Windows Mobile 5 SDK.&lt;/P&gt;
&lt;P mce_keep="true"&gt;A. You should be able to grab it from an older SDK. Keep in mind that this is really a fairly "unofficial" API which was really designed solely for OEM use to play ringtones. One shouldn't expect it to be present on every device.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Q. How come the ringtones on my phone sound like high-quality MIDI, but when I use the interface described above I only get low-quality sine waves?&lt;/P&gt;
&lt;P mce_keep="true"&gt;A. There are two possibilities. The first is that the ringtone you hear is actuallly a compressed WMA file, which are supported as ring tones. The second is that the OEM may have implemented&amp;nbsp;their own proprietary MIDI synthesizer elsewhere in the system.&amp;nbsp;To elaborate on the latter situation: There's a higher-level API,&amp;nbsp;known as EventSound,&amp;nbsp;where OEMs can plug in their own MIDI synthesizer (or arbitrary audio codec) to play ringtones or other system sounds. This API isn't open to ISVs (it's &lt;U&gt;very&lt;/U&gt; subject to change from release to release). The actual implementation of this will vary greatly from device to device.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Q. Didn't Windows CE support a higher quality MIDI synth at some point in the past as part of DirectShow?&lt;/P&gt;
&lt;P mce_keep="true"&gt;A. At one point DirectMusic was ported to Windows CE and shipped to support playback of MIDI files. However, for a variety of reasons (performance, code size, RAM usage, stability) it was unacceptable. As far as I know no one ever shipped a product using it, and it was dropped from the product in successive releases. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1409493" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/medmedia/archive/tags/WaveAPI/default.aspx">WaveAPI</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/MIDI/default.aspx">MIDI</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Andy+Raffman/default.aspx">Author: Andy Raffman</category></item><item><title>Windows CE Audio Driver Samples</title><link>http://blogs.msdn.com/medmedia/archive/2007/01/03/windows-ce-audio-driver-samples.aspx</link><pubDate>Thu, 04 Jan 2007 07:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1407109</guid><dc:creator>Andy Raffman</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/1407109.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=1407109</wfw:commentRss><description>&lt;FONT face=Arial color=navy size=2&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: navy; FONT-FAMILY: Arial"&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;This is my first blog post,&amp;nbsp;so please feel free to leave feedback with questions or comments, especially if you feel I've gotten anything wrong or if there's some critical bit of infomation missing.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;Windows CE currently ships&amp;nbsp;audio driver samples descended from three distict codebases: MDD/PDD, WaveDev2, and UAM. There are historical and functional reasons for this, but the existence of different driver models that all do more-or-less the same thing has caused some confusion. I'll try to clear things up a little in this posting.&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;First off, all three sample designs adhere to the same&amp;nbsp;WaveAPI&amp;nbsp;driver interface. They all hook into the system as device drivers, export WAV_Open, WAV_IOControl, WAV_Close, etc. entry points, and handle IOCTL_WAV_MESSAGE IoControl codes to interact with the waveapi subsystem. That upper-edge is hardware independent, and all the hardware dependent code goes into the driver. The difference between the&amp;nbsp;samples is in their internal design. &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;&amp;nbsp;&lt;B&gt;MDD/PDD&lt;/B&gt;&amp;nbsp;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;The oldest design and the one most in use today among Windows CE embedded platforms is the MDD/PDD model.&amp;nbsp;The MDD/PDD implementation splits the driver into two pieces, a "sort-of hardware independent" MDD layer, and a "really hardware dependent" PDD layer.&amp;nbsp;The MDD portion is shipped as public code (in public\COMMON\oak\drivers\wavedev\mdd), and generates a library named wavemdd.lib. The PDD layer must be written (or ported from public\COMMON\oak\drivers\wavedev\pdd) by the OEM. To build a complete driver, the two layers are statically linked together. Between the MDD and PDD layers there is a functional&amp;nbsp;interface defined by public\common\oak\inc\waveddsi.h.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;The waveapi driver interface already does a pretty good job of distilling hardware dependencies down to the driver level, so one might wonder how MDD/PDD can further separate hardware independent/dependent layers. To do this, the MDD layer makes a couple of assumptions about the way the hardware works and what types of features you want to support. &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;Here are some assumptions MDD/PDD makes: &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: normal; mso-list: l1 level1 lfo1; mso-add-space: auto; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Only one device (waveOutGetNumDevs always returns 1) &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: normal; mso-list: l1 level1 lfo1; mso-add-space: auto; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Only one stream per device (e.g. one input and one output stream). Note that waveapi includes an internal “software mixer” which can virtualize the single output stream into multiple streams at the application level.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 10pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: normal; mso-list: l1 level1 lfo1; mso-add-space: auto; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol; mso-fareast-font-family: Symbol; mso-bidi-font-family: Symbol"&gt;&lt;SPAN style="mso-list: Ignore"&gt;·&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Input and output DMA share the same interrupt. &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;By making these assumptions, the MDD/PDD model greatly simplifies the PDD layer, and the MDD/PDD driver is relatively easy to port if you have fairly generic audio hardware and you have fairly generic needs. However, if your hardware is nonstandard, or if you need to implement some special handling, you may find yourself itching to modify the MDD source code. At that point you may be fighting against the MDD/PDD interface design and creating more complexity than needed.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;Wavedev2&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;At the start of the Smartphone project in 2000 we had a number of audio requirements which we found the MDD/PDD model could not meet without major changes to the MDD/PDD interface. In addition, at that point in time (WinCE 3.0) there was no waveapi “software mixer” to allow us to play multiple sounds concurrently, so we knew we would have to take care of that in the driver. The solution was to start over and implement a new design which became informally known as wavedev2 (the original wave driver was under platform\hornet\drivers\wavedev, so when it came time to start on the new design it got put in the wavedev2 subdirectory).&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;Wavedev2 is a monolithic design in which all the source files are located in a single directory. To port a wavedev2 driver you just copy all the files from an existing sample and start modifying. This actually isn’t as bad as it sounds because in most cases the only files you need to modify are hwctxt.h and hwctxt.cpp. In retrospect it would have been better to put the files in different directories to make this a little more clear, reduce the tendency of OEMs to make random changes in the other files, and simplify the task of fixing bugs in the other files. That's probably something we'll be looking at cleaning up in the future.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;The most recent wavedev2 sample was shipped as part of WinCE 6 under public\common\oak\drivers\wavedev\wavedev2\ensoniq. &lt;/FONT&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;This latest wavedev2 driver includes the following features which are not found on the other driver implementations:&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpFirst style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: normal; mso-list: l0 level1 lfo2; mso-add-space: auto; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;-&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;“MIDI” synthesizer. I put MIDI in quotes because, frankly, it’s a pretty minimal implementation which only supports sine wave output (this will probably be another blog topic). However, it works great for the types of things a phone needs to do: play DTMF and call progress tones and simple melodies. (See &lt;A class="" id=bp___v___r___postlist___EntryItems_ctl05_PostTitle href="http://blogs.msdn.com/medmedia/archive/2007/01/03/the-wavedev2-midi-implementation.aspx" mce_href="http://blogs.msdn.com/medmedia/archive/2007/01/03/the-wavedev2-midi-implementation.aspx"&gt;The Wavedev2 MIDI Implementation&lt;/A&gt;&amp;nbsp;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: normal; mso-list: l0 level1 lfo2; mso-add-space: auto; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;-&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Sample-rate-conversion and mixing on both input and output streams. The driver can mix multiple output streams at different sample rates into a single output stream (something that can now be done with the MDD/PDD driver using the software mixer). It can also split the single input stream and source it to multiple applications at different sample rates (something no other driver design can currently do).&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: normal; mso-list: l0 level1 lfo2; mso-add-space: auto; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;-&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;A “gain class” interface. Each output stream is associated with a specific class. Whenever an app creates a new stream it is associated with class 0, although the app can move its stream to a different class via a waveOutMessage call to the driver. The system can use a separate waveOutMessage call to the driver to control the volume level on a per-class basis. This interface is used by the shell to do things like mute audio playback when a phone call is in progress. This is probably another blog topic for later. (See &lt;A id=ctl00___ctl00___ctl01___Results___postlist___EntryItems_ctl04_PostTitle href="http://blogs.msdn.com/medmedia/archive/2007/01/04/the-wavedev2-gainclass-implementation.aspx"&gt;&lt;FONT color=#0000cc&gt;The Wavedev2 Gainclass Implementation&lt;/FONT&gt;&lt;/A&gt; )&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpMiddle style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: normal; mso-list: l0 level1 lfo2; mso-add-space: auto; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;-&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;A “forcespeaker” interface which is used by the shell to “hint” to the driver that a specific sound should be played out the speaker even if a headset is plugged in. This is typically used to allow an OEM to play ringtones out a speaker even if a headset is plugged in. (See &lt;A class="" id=bp___v___r___postlist___EntryItems_ctl00_PostTitle href="http://blogs.msdn.com/medmedia/archive/2007/01/16/the-wavedev2-forcespeaker-api.aspx" mce_href="http://blogs.msdn.com/medmedia/archive/2007/01/16/the-wavedev2-forcespeaker-api.aspx"&gt;&lt;FONT color=#0000cc&gt;The Wavedev2 ForceSpeaker API&lt;/FONT&gt;&lt;/A&gt; )&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoListParagraphCxSpLast style="MARGIN: 0in 0in 10pt 0.5in; TEXT-INDENT: -0.25in; LINE-HEIGHT: normal; mso-list: l0 level1 lfo2; mso-add-space: auto; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;FONT color=#000000&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: Arial"&gt;&lt;SPAN style="mso-list: Ignore"&gt;-&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;Support for an S/PDIF interface and for streaming of WMAPro compressed content across S/PDIF. This is a recent addition, specific to the Ensoniq version, which was used as a proof-of-concept for the Tomatin project. (See &lt;A class="" id=bp___v___r___postlist___EntryItems_ctl01_PostTitle href="http://blogs.msdn.com/medmedia/archive/2007/01/16/multichannel-audio-in-windows-ce.aspx" mce_href="http://blogs.msdn.com/medmedia/archive/2007/01/16/multichannel-audio-in-windows-ce.aspx"&gt;&lt;FONT color=#0000cc&gt;Multichannel Audio in Windows CE&lt;/FONT&gt;&lt;/A&gt; )&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;[Note: a previous version of this blog claimed that&amp;nbsp;a wavedev2 sample&amp;nbsp;shipped with the Tomatin (NMD)&amp;nbsp;feature pack under public\fp_nmd\common\oak\drivers\wavedev\wavedev2\ensoniq. I was wrong; the files&amp;nbsp;did not ship in that release. I apologize to anyone I misled. The sample code in the CE6 release should be backward compatible, although I have no idea of whether there are any licensing issues with using CE6 sample code&amp;nbsp;with a CE5 device]&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;If you’re developing a Windows Mobile Smartphone or PocketPC Phone, you pretty much have to start with the wavedev2 sample: the system depends on a number of the extensions implemented in wavedev2. On the other hand, if you’re developing an embedded Windows CE product you can use whichever design best fits your needs.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;B style="mso-bidi-font-weight: normal"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;UAM&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;During the development of WinCE 4.2 the audio team was working on adding support for DirectSound and needed a sample driver to demonstrate exposing DirectSound support from the device driver. As was discovered during the Smartphone effort, retrofitting the MDD/PDD driver would entail a number of changes. Instead, a new monolithic driver was written using some bits of the wavedev2 design, with added support for the Ensoniq-specific feature of mixing two audio streams in hardware (and falling back to the software mixer for any additional streams). While there are superficial similarities between UAM and Wavedev2, they're still pretty different though.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;However, support for DirectSound was dropped in WinCE 5.0, and it’s very rare to find audio designs that support mixing audio streams in hardware. There’s absolutely nothing wrong with it, and many OEMs still use it as the basis for their audio driver ports; but for new designs it doesn’t add much value to either of the other models.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 10pt; LINE-HEIGHT: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'"&gt;&lt;FONT color=#000000&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&amp;nbsp;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1407109" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/medmedia/archive/tags/WaveAPI/default.aspx">WaveAPI</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Andy+Raffman/default.aspx">Author: Andy Raffman</category></item><item><title>Camera Capture Performance (Part1)</title><link>http://blogs.msdn.com/medmedia/archive/2006/11/13/camera-capture-performance-part1.aspx</link><pubDate>Tue, 14 Nov 2006 00:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1071179</guid><dc:creator>saadpuri</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/medmedia/comments/1071179.aspx</comments><wfw:commentRss>http://blogs.msdn.com/medmedia/commentrss.aspx?PostID=1071179</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;STRONG&gt;&lt;FONT face="Times New Roman" size=3&gt;Still Image Capture&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;FONT face="Times New Roman" size=3&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;SPAN style="FONT-SIZE: 10pt"&gt;&lt;FONT face="Times New Roman"&gt;Windows Mobile 5.0 contains an Image Sink Filter (a DShow filter). This filter encodes the image data and writes the encoded image to a file. For encoding, the Image Sink&amp;nbsp;Filter&amp;nbsp;uses Imaging API to access the installed Imaging&amp;nbsp;encoders. The still image encoders which Microsoft ships with Windows Mobile 5.0 are not optimized and should, in general be replaced by OEMs with optimized encoders for the particular platform. One limitation of Imaging framework is that it only accepts RGB input, i.e., the raw buffer sent to Imaging encoder must be in RGB format. For this very reason, the Image Sink filter does not accept YCbCr. &lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;SPAN style="FONT-SIZE: 10pt"&gt;&lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman"&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;SPAN style="FONT-SIZE: 10pt"&gt;&lt;FONT face="Times New Roman"&gt;Besides accepting RGB data, the Image Sink Filter also accepts pre-encoded JPG data. This is useful when there is an optimized still image&amp;nbsp;encoder&amp;nbsp;available on a given platform,&amp;nbsp;which accepts YCbCr. For this to work the actual encoding is done by the driver and the camera driver exposes a format with SubFormat field of CSDATARANGE equal to&amp;nbsp;MEDIASUBTYPE_IJPG GUID.&amp;nbsp; The encoded buffer will then be passed down to the Image Sink Filter simply for file I/O.&amp;nbsp; This optimized encoding can also be done in a DShow Transform filter with the transform filter exposing MEDIASUBTYPE_IJPG on its output pin.&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;SPAN style="FONT-SIZE: 10pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman"&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;SPAN style="FONT-SIZE: 10pt"&gt;&lt;FONT face="Times New Roman"&gt;The OEMs can still use the encoders that are shipped with Windows Mobile 5.0. These encoders provide a stable, platform independent solution. However, as the resolution of still image increases, the performance of these encoders deteriorates.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;FONT face="Times New Roman"&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;SPAN style="FONT-SIZE: 10pt"&gt;&lt;FONT face="Times New Roman"&gt;Following is how you would change the sample null camera driver to provide JPG data on STILL pin.&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;B&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;Step 1:&amp;nbsp;Define the format&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;B&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;SPAN style="FONT-SIZE: 10pt"&gt;&lt;FONT face="Times New Roman"&gt;In adapterprops.h &lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&lt;/SPAN&gt;define the following&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: blue"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman"&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; TEXT-ALIGN: justify"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue"&gt;#define&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt"&gt; FOURCC_IJPG mmioFOURCC(&lt;SPAN style="COLOR: maroon"&gt;'I'&lt;/SPAN&gt;, &lt;SPAN style="COLOR: maroon"&gt;'J'&lt;/SPAN&gt;, &lt;SPAN style="COLOR: maroon"&gt;'P'&lt;/SPAN&gt;, &lt;SPAN style="COLOR: maroon"&gt;'G'&lt;/SPAN&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue"&gt;#define&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt"&gt; MEDIASUBTYPE_IJPG {0x47504A49, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; mso-no-proof: yes"&gt;#define&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; mso-no-proof: yes"&gt; DX&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;176&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; mso-no-proof: yes"&gt;#define&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; mso-no-proof: yes"&gt; DY&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;144&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; mso-no-proof: yes"&gt;#define&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; mso-no-proof: yes"&gt; DBITCOUNT&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;16&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9"&gt;&lt;FONT face="Times New Roman"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; mso-no-proof: yes"&gt;#define&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; mso-no-proof: yes"&gt; FRAMERATE&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;15&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;CS_DATARANGE_VIDEO DCAM_StreamMode = &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: green; FONT-FAMILY: Arial"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // CSDATARANGE&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: Arial"&gt;sizeof&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt; (CS_DATARANGE_VIDEO), &lt;SPAN style="COLOR: green"&gt;// Flags &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;0,&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;SAMPLESIZE, &lt;SPAN style="COLOR: green"&gt;// Replace with maximum Sample Size that the JPG data would take for the current resolution and image quality&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;&lt;SPAN style="COLOR: green"&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;0, &lt;SPAN style="COLOR: green"&gt;// Reserved&lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;STATIC_CSDATAFORMAT_TYPE_VIDEO, &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;STRONG&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: Arial"&gt;MEDIASUBTYPE_IJPG,&lt;/SPAN&gt;&lt;/STRONG&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;STATIC_CSDATAFORMAT_SPECIFIER_VIDEOINFO&lt;SPAN style="COLOR: blue"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;},&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;TRUE, &lt;SPAN style="COLOR: green"&gt;// BOOL, bFixedSizeSamples (all samples same size?)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;TRUE, &lt;SPAN style="COLOR: green"&gt;// BOOL, bTemporalCompression (all I frames?)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;CS_VIDEOSTREAM_CAPTURE, &lt;SPAN style="COLOR: green"&gt;// StreamDescriptionFlags (CS_VIDEO_DESC_*)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;0, &lt;SPAN style="COLOR: green"&gt;// MemoryAllocationFlags (CS_VIDEO_ALLOC_*)&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: green; FONT-FAMILY: Arial"&gt;// _CS_VIDEO_STREAM_CONFIG_CAPS &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;{&lt;SPAN style="COLOR: green"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: green; FONT-FAMILY: Arial"&gt;//&amp;nbsp;Omitted for this sample. Please refer to adapterprops.h in the sample null camera driver for ways to fill in this structure&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: green; FONT-FAMILY: Arial"&gt;………&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: green; FONT-FAMILY: Arial"&gt;………&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;}, &lt;SPAN style="COLOR: green"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: green; FONT-FAMILY: Arial"&gt;// CS_VIDEOINFOHEADER&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;{&lt;SPAN style="COLOR: green"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;0,0,DX,DY, &lt;SPAN style="COLOR: green"&gt;// RECT rcSource; &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;0,0,DX,DY, &lt;SPAN style="COLOR: green"&gt;// RECT rcTarget; &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;BITRATE, &lt;SPAN style="COLOR: green"&gt;// DWORD dwBitRate;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;0L, &lt;SPAN style="COLOR: green"&gt;// DWORD dwBitErrorRate; &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;REFTIME_15FPS, &lt;SPAN style="COLOR: green"&gt;// REFERENCE_TIME AvgTimePerFrame; &lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: Arial"&gt;sizeof&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt; (CS_BITMAPINFOHEADER), &lt;SPAN style="COLOR: green"&gt;// DWORD biSize;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;DX, &lt;SPAN style="COLOR: green"&gt;// LONG biWidth;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;DY, &lt;SPAN style="COLOR: green"&gt;// LONG biHeight;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;3, &lt;SPAN style="COLOR: green"&gt;// WORD biPlanes;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;DBITCOUNT, &lt;SPAN style="COLOR: green"&gt;// WORD biBitCount;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: blue; FONT-FAMILY: Arial"&gt;FOURCC_IJPG&lt;/SPAN&gt;&lt;/B&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt; | BI_SRCPREROTATE, &lt;SPAN style="COLOR: green"&gt;// DWORD biCompression;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;SAMPLESIZE, &lt;SPAN style="COLOR: green"&gt;// DWORD biSizeImage;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;0, &lt;SPAN style="COLOR: green"&gt;// LONG biXPelsPerMeter;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;0, &lt;SPAN style="COLOR: green"&gt;// LONG biYPelsPerMeter;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;0, &lt;SPAN style="COLOR: green"&gt;// DWORD biClrUsed;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;0, &lt;SPAN style="COLOR: green"&gt;// DWORD biClrImportant;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;0, 0, 0 &lt;SPAN style="COLOR: green"&gt;// DWORD dwBitMasks[3]&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9; TEXT-INDENT: 0.5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;}&lt;SPAN style="COLOR: green"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BACKGROUND: #d9d9d9"&gt;&lt;SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: Arial"&gt;};&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 9pt; FONT-FAMILY: Arial"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;Step 2: Add this format to the list of formats of Still pin&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt"&gt;&lt;FONT face="Times New Roman"&gt;In sample null camera driver, you would modify CCameraDevice::Initialize() in cameradevice.cpp to have &lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;m_PinVideoFormat[STILL].categoryGUID = PINNAME_VIDEO_STILL;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;m_PinVideoFormat[STILL].ulAvailFormats = 1;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;m_PinVideoFormat[STILL].pCsDataRangeVideo[0] = &amp;amp;DCAM_StreamMode;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;Step 3: Modify the BufferFill() function&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;Use biCompression field of the current format to determine whether MEDIASUBTYPE_IJPG format is selected. In BufferFill() you can have following check&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;UINT&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;BufferFill( PUCHAR pImage, PCS_VIDEOINFOHEADER pCsVideoInfoHdr, IMAGECOMMAND Command, &lt;SPAN style="COLOR: blue"&gt;bool&lt;/SPAN&gt; FlipHorizontal, LPVOID lpParam )&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;( NULL == pCsVideoInfoHdr )&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; -1;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;DWORD biCompression = pCsVideoInfoHdr-&amp;gt;bmiHeader.biCompression;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; ( (FOURCC_IJPG == (biCompression &amp;amp; ~BI_SRCPREROTATE)) )&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;// Real drivers would add code here to handle JPEG encoding.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;// The biSizeImage that is returned here should be the actual&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; TEXT-INDENT: 0.5in; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; COLOR: green; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;// size of JPEG data that is written to the buffer.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; biSizeImage;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;……….&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;……….&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="BACKGROUND: #d9d9d9; MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;FONT size=3&gt;&lt;FONT face="Times New Roman"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT size=3&gt;&lt;B&gt;&lt;FONT face="Times New Roman"&gt;Step 4: Handle &lt;/FONT&gt;&lt;/B&gt;&lt;B&gt;&lt;SPAN style="FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;PROPSETID_VIDCAP_VIDEOCOMPRESSION&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;B&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/B&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-no-proof: yes"&gt;The default implementation(AdapterHandleCompressionRequests()) for PROPSETID_VIDCAP_VIDEOCOMPRESSION returns ERROR_INVALID_PARAMETER. Camera application on Windows Mobile 5.0 and later, uses this interface to set encoder quality. You would need to change this to return ERROR_SUCCESS after correctly handling various properties in this property set. Failure to do this would result in camera application raising an exception at initialization.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;o:p&gt;&lt;FONT face="Times New Roman" size=3&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/o:p&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1071179" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/medmedia/attachment/1071179.ashx" length="61595" type="image/jpeg" /><category domain="http://blogs.msdn.com/medmedia/archive/tags/DShow/default.aspx">DShow</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Still+Image/default.aspx">Still Image</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Camera/default.aspx">Camera</category><category domain="http://blogs.msdn.com/medmedia/archive/tags/Author_3A00_+Saad+Puri/default.aspx">Author: Saad Puri</category></item></channel></rss>