<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" media="screen" href="/styles/xslt/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:c9="http://channel9.msdn.com">
<channel>
	<title>Channel 9</title>
    <atom:link rel="self" type="application/rss+xml" href="http://channel9.msdn.com/Niners/c4f.Randall-Maas/Posts/RSS"></atom:link>
    <itunes:summary></itunes:summary>
    <itunes:author>Microsoft</itunes:author>
    <itunes:subtitle></itunes:subtitle>
    <image>
      <url>http://mschnlnine.vo.llnwd.net/d1/Dev/App_Themes/C9/images/feedimage.png</url>
      <title>Channel 9</title>
      <link>http://channel9.msdn.com/Niners/c4f.Randall-Maas/Posts</link>
    </image>
    <itunes:image href=""></itunes:image>
    <itunes:category text="Technology"></itunes:category>
    <description>Channel 9 keeps you up to date with the latest news and behind the scenes info from Microsoft that developers love to keep up with. From LINQ to SilverLight – Watch videos and hear about all the cool technologies coming and the people behind them.</description>
    <link>http://channel9.msdn.com/Niners/c4f.Randall-Maas/Posts</link>
    <language>en</language>
    <pubDate>Sun, 19 May 2013 14:46:20 GMT</pubDate>
    <lastBuildDate>Sun, 19 May 2013 14:46:20 GMT</lastBuildDate>
    <generator>Rev9</generator>
    <c9:totalResults>3</c9:totalResults>
    <c9:pageCount>1</c9:pageCount>
    <c9:pageSize>25</c9:pageSize>
  <item>
      <title>Paint With Light</title>
      <description><![CDATA[
<p>This article is about a winter project I did to learn about video processing and the DirectShow framework. I decided to try making some painting-with-light movies, like those you often see in commercials. When we started, I could not find an existing project—so
 I bought a couple of webcams and wrote one.</p>
<p>You can see a quick demonstration of the program in action in the following video:</p>
<div id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:a93c12a4-b536-4834-a4c1-ab06388930da" class="wlWriterEditableSmartContent">
<div id="1491c0fa-5be7-4640-ba31-616dc686a62c">
<div><a href="http://www.youtube.com/watch?v=uQRetgJbs8M&amp;hl=en_US&amp;fs=1&amp;" target="_new"><img src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9990783/video3e9a4058acdd.jpg" alt=""></a></div>
</div>
</div>
<p>In the next section, we'll learn how to use the program to create a movie. Then we'll look at how the program works and dive into the software's implementation.</p>
<h3>How to Use the Program</h3>
<p>This section will give an overview of how to use the program to make a video. You will need three basic pieces:</p>
<ul>
<li>A pen light or laser pointer to draw sketches with. You can buy cheap laser pointers and LED penlights at almost any convenience or office supply store.
</li><li>A web camera to capture the light pen. </li><li>Software to get the video from the web camera and encode the video file. We'll discuss this program below.
</li></ul>
<p>You can create the program in simple six steps:</p>
<ol>
<li>Select a video camera to use (plug one in, if necessary) </li><li>Configure the camera </li><li>Set the threshold for the pen </li><li>Select the background image or video, if you'll be using one </li><li>Start recording </li><li>Draw! </li></ol>
<p>Let's look at the application's controls:</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9990783/image_4.png"><img title="image" border="0" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9990783/image_thumb_1.png" width="500" height="390"></a>&nbsp;<strong>Figure
 1: A screenshot of the application</strong></p>
<p>There are nine controls for the video camera, audio input and recording:</p>
<ul>
<li>A combo box for selecting the camera </li><li>An option to flip the camera's video </li><li>An option to tweak the camera's video control settings </li><li>A slider to control the discrimination between the pen light and normal scene
</li><li>A combo box for selecting the microphone to use when recording </li><li>An option to choose the background </li><li>An option to choose the desired size of the output video </li><li>Buttons to start, stop or pause recording </li><li>A button to clear the current drawing </li></ul>
<h3>
<p align="center"><strong></strong></p>
Some recommended settings for the camera:</h3>
<ul>
<li>Reduce exposure setting until there is no glare </li><li>Lower the brightness until there is no glare </li><li>Disable the white balance “auto” setting and <i><u>manually</u></i> adjust it
</li><li>Disable the auto-exposure setting (if applicable) </li></ul>
<p>Adjust these while watching the video preview area.</p>
<h3>The Pen Threshold Slider</h3>
<p>The next step is to move the pen light and adjust the threshold until the response to the light feels right. Anything brighter than the threshold will be considered a pen; everything else is just regular pixels. If the setting is too low, everything in the
 video will appear to be a pen; too high and it won't pick up on the pen. You may wish to go back and adjust the camera's parameters (see the previous section).</p>
<ul>
<li>If you are using a laser pointer, I recommend putting Scotch tape over the pointer. This will diffuse the light and keep it from overwhelming the CCD in the webcam and ruining the image.
</li></ul>
<p>The clear button erases the current pen drawing. You can use this periodically as you adjust the settings.</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9990783/image_14.png"><strong><img title="image" border="0" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9990783/image_thumb_6.png" width="342" height="243"></strong></a><strong>
<br>
Figure 2: The pen light detector threshold</strong></p>
<h4>Other Tips for Making a Video</h4>
<p>Making a movie takes some getting used to. Here are a few other tips I learned:</p>
<ul>
<li>Try to use a dark background behind you. </li><li>Use a light low, and pointed toward the front of your face. This will make you look better and ensure the light isn't too bright on your skin.
</li><li>Try not to wear anything shiny, such as shirts or buttons. Depending on your lighting, the shiny part can look like a pen.
</li><li>Don't have any glass or other items behind you. Light might reflect off glass or a forehead, and look like a pen.
</li></ul>
<ul>
<li>Don't vary the lighting. Some webcams change their parameters automatically based on light level; others change their frame rate when it's darker (to allow longer exposure).
</li></ul>
<h3>DirectShow</h3>
<p>To understand how the software is implemented, we first need a quick overview of DirectShow. Software built using DirectShow employs component (object) graphs to do its work and create overall behavior. Some components—such as video camera or video encoder—are
 necessary. Some add features, and a few are needed to connect it all. When the graph is built and run, DirectShow makes sure each node agrees on the exact media formats that will be provided. I enjoy object graphs as a design structuring technique, but I found
 DirectShow a challenge to master.</p>
<p>In a sense, you lay out the basic schematic of the system—or at least the DirectShow portion—and then create code to complete the fine details and add functionality. You can prototype a graph (schematic) with GraphEdit or Monograph EditStudio. These tools
 have a large catalog of pieces, making it easy to try out different ideas. Then you can lay out the pieces to see if they go together (some pieces just don't) and test it.</p>
<p>This project uses three different graphs:</p>
<ol>
<li>A graph to show the camera preview, which is used when not recording or when sketching on a movie
</li><li>A graph to record from web camera, with or without a still image in the background
</li><li>A graph to paint on a video from a file </li></ol>
<h4>The Preview Graph</h4>
<p>Let's start with the simple camera preview:</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9990783/image_16.png"><strong><img title="image" border="0" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9990783/image_thumb_7.png" width="480" height="66"></strong></a>
<br>
<strong>Figure 3: Second DirectShow graph to get the pen</strong></p>
<p>Here are the components and what they do:</p>
<ul>
<li>The <i>Camera</i>: your webcam (or other video input device) </li><li>A <i>Sample Grabber</i> to get an image frame and pass it to a delegate. This graph uses two: The first,
<i>Flip Video</i>, flips the video to make the preview more like a mirror. The second,
<i>Light Paint</i>, scans for pen light and adds points in for the previous pen. I'll go into a bit more detail below.
</li><li>The <i>Video Renderer </i>is a helper object that displays the camera image on the window. It requires a window region to display on.</li></ul>
<h4>Finding the Camera</h4>
<p>Let's look at how the program code does this. The following enumeration is used by the display pull down to list all the video sources:</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">static</span> <span class="kwrd">public</span> IEnumerable&lt;VideoSource&gt; VideoDevices()
{
  IEnumMoniker em = DeviceEnum(<span class="kwrd">ref</span> DirectShowNode.CLSID_VideoInputDeviceCategory);
  <span class="kwrd">if</span> (<span class="kwrd">null</span> == em)
    <span class="kwrd">yield</span> <span class="kwrd">break</span>;

  <span class="kwrd">foreach</span> (IMoniker Moniker <span class="kwrd">in</span> COM.Enumerator(em))
  {
     VideoSource S = <span class="kwrd">new</span> VideoSource(Moniker), T;
     <span class="kwrd">string</span> Key = S.DevicePath;
     <span class="kwrd">if</span> (<span class="kwrd">null</span> == Key)
       Key = S.DisplayName;
     <span class="kwrd">if</span> (DevicePath2Source.TryGetValue(Key, <span class="kwrd">out</span> T))
       {
          S.Dispose();
          S = T;
       }
      <span class="kwrd">else</span>
       DevicePath2Source[Key] = S;

     <span class="kwrd">yield</span> <span class="kwrd">return</span> S;
  }

  Marshal.ReleaseComObject(em);
}</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>Whenever the video source selection changes, the <i>_VideoSource</i> instance variable is updated accordingly.</p>
<h4>Creating the Preview Graph</h4>
<p>The following code builds the video graph (see Figure 3):</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode">DirectShowGraph CamVideo=<span class="kwrd">null</span>;
<span class="kwrd">public</span> <span class="kwrd">void</span> BuildPreviewGraph(Control CamPreview)
{
  <span class="rem">// Disable any face tracking</span>
  _VideoSource.FaceTracking  = PluralMode.None;

  <span class="rem">// Add the camera source</span>
  CamVideo = <span class="kwrd">new</span> DirectShowGraph();
  CamVideo.Add(_VideoSource, <span class="str">&quot;source&quot;</span>, <span class="kwrd">null</span>);

  <span class="rem">// Add the flip video item, as a delegate of a sample grabber</span>
  SampleGrabber CamFrameGrabber1 = <span class="kwrd">new</span> SampleGrabber();
  Flip = <span class="kwrd">new</span> FlipVideo();
  CamFrameGrabber1.Callback(Flip);
  Flip.FlipHorizontal = FlipHorizontal;
  AMMediaType  Media = CamVideo.BestMediaType(RankMediaType);
  CamVideo.Add(CamFrameGrabber1, <span class="str">&quot;flipgrabber&quot;</span>,  Media);
  CamFrameGrabber1.MediaType = Media;

  <span class="rem">// Add the paint-with light item, as a delegate of a sample grabber</span>
  SampleGrabber CamFrameGrabber = <span class="kwrd">new</span> SampleGrabber();
  PaintedArea = <span class="kwrd">new</span> LightPaint();
  CamFrameGrabber.Callback(PaintedArea);
  Media = CamVideo.BestMediaType(RankMediaType);
  CamVideo.Add(CamFrameGrabber, <span class="str">&quot;grabber&quot;</span>,  Media);
  CamFrameGrabber.MediaType = Media;

  DirectShowNode Preview = <span class="kwrd">new</span> DirectShowNode(DirectShowNode.CLSID_VideoRenderer);
  CamVideo.Add(Preview, <span class="str">&quot;render1&quot;</span>, <span class="kwrd">null</span>);

  Preview.RenderOnto(CamPreview);

  <span class="rem">// Add a null renderer to consume any extra pins from the camera source</span>
  DirectShowNode N = <span class="kwrd">new</span> DirectShowNode(DirectShowNode.CLSID_NULLRenderer);
  CamVideo.Add(N, <span class="str">&quot;null&quot;</span>,<span class="kwrd">null</span>);

  <span class="rem">// The size isn't known until we've built a sample grabber graph</span>
  CamFrameGrabber1.UpdateFrameSize();
  Flip.Size = CamFrameGrabber1.FrameSize;
  CamFrameGrabber.UpdateFrameSize();
  PaintedArea.Size = CamFrameGrabber.FrameSize;

  <span class="rem">// Start the camera graph</span>
  CamVideo.Start();
}</pre>
<p>If it has the option, the first thing it does is tell the camera to disable face tracking. Otherwise, the camera might move its view on us, causing all sorts of confusion.
</p>
<p>Then it builds the graph using a helper class called DirectShowGraph to add each of the nodes. The helper automatically connects the pins between the passed node and the most recent node with available output pins.</p>
<p>Next, the frame sizes are updated and the graph is executed. DirectShow takes over, moving video from the camera through the graph and onto the display.</p>
<h4>The FlipVideo Sample Grabber Delegate</h4>
<p>The SampleGrabber class is a proxy to the DirectShow COM ISampleGrabber objects. It has a procedure called
<i>Callback()</i> that registers a callback to a delegate implementing the ISampleGrabberCB interface.</p>
<p>This project includes a class called FlipVideo whose instances are used here. If enabled, each instance is responsible for flipping the video. Some cameras don't have a built-in setting to do this, so we provide a way to do it in code.</p>
<p>Here is a portion of the code that does this. Because it is byte manipulation, it looks a like C:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">int</span> BufferCB(<span class="kwrd">double</span> SampleTime, IntPtr Buffer, <span class="kwrd">int</span> BufferLen)
{
    <span class="kwrd">unsafe</span>
    {
        <span class="kwrd">byte</span>* Buf = (<span class="kwrd">byte</span>*) Buffer;
        <span class="kwrd">byte</span>* End = Buf &#43; BufferLen-(BufferLen%3);

        <span class="rem">// The width of our buffer</span>
        <span class="kwrd">int</span> Width  = Size . Width;

        <span class="kwrd">if</span> (!FlipHorizontal)
        <span class="kwrd">return</span> 0;
        <span class="rem">// This takes about 8 ms (640x480)</span>
        <span class="kwrd">int</span> Width3 = Width*3;
        <span class="kwrd">byte</span>* BufEnd = Buf &#43; Width3 * Size.Height;
        <span class="kwrd">for</span> (<span class="kwrd">byte</span>* BPtr= Buf; BPtr != BufEnd; BPtr&#43;= Width3)
            <span class="kwrd">for</span> (<span class="kwrd">byte</span>* B = BPtr, BEnd = B&#43;Width3-3; B &lt; BEnd;)
            {
                <span class="kwrd">byte</span> Tmp =*BEnd;
                *BEnd&#43;&#43; = *B;
                *B&#43;&#43;    = Tmp;
                Tmp =*BEnd;
                *BEnd&#43;&#43; = *B;
                *B&#43;&#43;    = Tmp;
                Tmp     = *BEnd;
                *BEnd   = *B;
                *B&#43;&#43;    = Tmp;
                BEnd -= 5;
            }
    }
    <span class="kwrd">return</span> 0;
}<b><br></pre>
</b>
<h3>The LightPaint Sample Grabber Delegate</h3>
<p>This project includes a class called LightPaint, whose instances are used as here. Each LightPaint instance is responsible for three things:</p>
<ol>
<li>Finding the pen points </li><li>Replacing the video with the background image (optional). Although this isn't necessary for the simple preview case, it is necessary in the more complex configurations. We'll look at those later.
</li><li>Painting all the pen strokes</li></ol>
<p>Below is a portion of the code that does this. I've excluded a nearly identical chunk of code that removes the step where the background image pixels are copied in. (We allow this duplication for performance reasons—checking whether to include a background
 image with every pixel gets expensive!)</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">int</span> BufferCB(<span class="kwrd">double</span> SampleTime, IntPtr Buffer, <span class="kwrd">int</span> BufferLen)
{
    <span class="kwrd">unsafe</span>
    {
        <span class="rem">// This scary construct speeds up the processing of the buffer a lot</span>
        <span class="rem">// by 10ms or more.  This is critical in speeding up acsess</span>
        <span class="kwrd">fixed</span> (<span class="kwrd">byte</span>* _CurrentPoints = CurrentPoints)
        <span class="kwrd">fixed</span> (<span class="kwrd">byte</span>* _IsPenPoint   = IsPoint)
        <span class="kwrd">fixed</span> (<span class="kwrd">byte</span>* Bknd         = Bkgnd)
        {
            <span class="kwrd">byte</span>* Buf = (<span class="kwrd">byte</span>*) Buffer;
            <span class="kwrd">int</span> Width3 = _Size.Width*3, Width=_Size.Width;

            BufferLen -= BufferLen % 3;
            <span class="kwrd">byte</span>* End = Buf &#43; BufferLen;
            <span class="kwrd">byte</span>* CurrentPoint = _CurrentPoints;
            <span class="kwrd">byte</span>* IsPenPoint = _IsPenPoint;

            <span class="rem">// Scan the image for the points brighter than threshold</span>
            <span class="kwrd">for</span> (<span class="kwrd">int</span> PI=0,I=0; Buf != End;  PI&#43;&#43;, I &#43;= 3)
            {
                <span class="kwrd">byte</span> B1= Buf[0];
                <span class="kwrd">byte</span> G1= Buf[1];
                <span class="kwrd">byte</span> R1= Buf[2];
                <span class="kwrd">byte</span> B2 = _CurrentPoints[I&#43;0];
                <span class="kwrd">byte</span> G2 = _CurrentPoints[I&#43;1];
                <span class="kwrd">byte</span> R2 = _CurrentPoints[I&#43;2];

                <span class="rem">// This is the key spot that detects the pen light.  </span>
                <span class="rem">// This must be very fast</span>
                <span class="rem">// Tweak this in different ways to see what works</span>
                <span class="kwrd">if</span> (R1 * RedScale &#43; G1 * GreenScale &#43; 
                    B1*BlueScale &gt;= Threshold)
                {
                    <span class="kwrd">if</span> (B1&gt;B2 || G1&gt;G2 || R1&gt;R2)
                    {
                        _IsPenPoint[PI] = 1;
                        _CurrentPoints[I&#43;0] = B1;
                        _CurrentPoints[I&#43;1] = G1;
                        _CurrentPoints[I&#43;2] = R1;
                    }
                    Buf&#43;=3;
                    <span class="kwrd">continue</span>;
                }

                <span class="kwrd">if</span> (0 == _IsPenPoint[PI])
                {
                    <span class="rem">// Add the current points</span>
                    B2 = Bknd[I&#43;0];
                    G2 = Bknd[I&#43;1];
                    R2 = Bknd[I&#43;2];
                }

                *Buf&#43;&#43; = B2;
                *Buf&#43;&#43; = G2;
                *Buf&#43;&#43; = R2;
            }
        }
    }

    <span class="kwrd">return</span> 0;
}</pre>
<h4>The Scariest Keyword in .NET…</h4>
<p>… is the “fixed” keyword. It turns an array into a pointer and keeps the garbage collector from touching the array while you use it. In short, “fixed” is everything your mother warned you about in C. But it gives a big performance improvement.</p>
<p>A frame needs to complete processing, compression and be written to the file in less than 30ms. (Usually it must do so in a lot less time, to provide adequate safety margin.) If not, the processing buffers will fill, the video quality could deteriorate,
 and the video preview will lag so much it will make the program unusable.</p>
<p>I found that “fixed” saves 10ms (about 30%) of the processing time spent in the Sample Grabber delegates. That's big.</p>
<h3>The Graph to Painting on the Video Stream or Still Image</h3>
<p>Now that we've learned how the pieces go together for painting on a preview, let's look at how we can record the stream.</p>
<p>You can use the next graph to record yourself painting on a still image or the video stream. It's a lot more complicated than the previous one:
</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9990783/image_18.png"><strong><img title="image" border="0" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9990783/image_thumb_8.png" width="447" height="148"></strong></a><strong>
<br>
Figure 4: DirectShow when painting on the Webcam video or a still picture</strong></p>
<p>This adds a lot more components. Here are the components and what they do:</p>
<ul>
<li>A <i>WM Asf Writer</i> that encodes the movie and writes it to a file. It needs both an audio and a video input, as well as a special profile to support encoding at different sizes.
</li><li>Three Sample Grabbers. The first two delegates are the FlipVideo and LightPaint objects discussed earlier. The third has an
<i>Overlay</i> delegate that puts the pen stroke onto the video preview so you can see where your hand and pen are while you paint.
</li><li>A <i>Smart Tee</i> splits an image stream into two copies. There are two tees used. The first splits the camera video into streams with and without the still background image. The second splits the video into two screens: one that is recorded, and another
 that is seen on the preview. As a bonus, the Smart Tee gives priority to the movie encoder and can drop frames to the preview.
</li><li><i>Microphone</i>. The WM Asf Writer requires an audio source. The microphone gives you a chance to narrate something fun onto the movie.
</li><li>Two <i>Video Renderers. </i>One provides previews of the pen over a still background image; the other goes over the webcam video to show the user is painting. I found that I needed to see where the pen is in the camera's view, and where it is on the resulting
 movie, in order to paint effectively.</li></ul>
<h4>The Overlay Delegate</h4>
<p>The overlay delegate is a much simpler version of the LightPaint class. Like the LightPaint class, it flips the video (if appropriate) and puts the pen stroke onto the video preview so you can see where your hand and pen are while painting. It's synchronized
 with the LightPaint object in order to grab the pen strokes from it.</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">int</span> BufferCB(<span class="kwrd">double</span> SampleTime, 
        IntPtr Buffer, <span class="kwrd">int</span> BufferLen)
{
    <span class="kwrd">unsafe</span>
    {
        <span class="rem">// This scary construct speeds up the </span>
        <span class="rem">// processing of the buffer a lot by 10ms or more.  </span>
        <span class="rem">// This is critical in speeding up access: each frame</span>
        <span class="rem">// has to make it thru the whole DS graph </span>
        <span class="rem">// in far less than 30ms.</span>
        <span class="kwrd">fixed</span> (<span class="kwrd">byte</span>* CurrentPoint = SrcPoints.CurrentPoints)
        <span class="kwrd">fixed</span> (<span class="kwrd">byte</span>* IsPenPoint   = SrcPoints.IsPoint)
        {
            <span class="kwrd">byte</span>* Buf = (<span class="kwrd">byte</span>*) Buffer;
            <span class="kwrd">byte</span>* End = Buf &#43; BufferLen-(BufferLen%3);

            <span class="rem">// The width of the LightPaint delegate and it's size</span>
            <span class="kwrd">int</span> Width2 = SrcPoints.Size.Width;

            <span class="rem">// The width of our buffer</span>
            <span class="kwrd">int</span> Width  = Size.Width;

            <span class="kwrd">if</span> (Size == SrcPoints.Size)
            {
                <span class="rem">// This is for the common, but special, </span>
                <span class="rem">// case where the LightPaint</span>
                <span class="rem">// delegate and use have the size and </span>
                <span class="rem">// we don't need to resize</span>
                <span class="kwrd">for</span> (<span class="kwrd">int</span> I=0; Buf != End; Buf&#43;=3, I&#43;&#43;)
                    <span class="kwrd">if</span> (0 != IsPenPoint[I])
                    {
                       <span class="kwrd">int</span> J = I*3;
                       Buf[0] = CurrentPoint[J&#43;&#43;];
                       Buf[1] = CurrentPoint[J&#43;&#43;];
                       Buf[2] = CurrentPoint[J&#43;&#43;];
                    }
            }
            <span class="kwrd">else</span>
            {
                <span class="rem">// The loop used to scan over the points</span>
                <span class="rem">// Note: This is designed to allow different </span>
                <span class="rem">// sizes for the LightPaint delegate and </span>
                <span class="rem">// the buffer we are painting on</span>
                <span class="kwrd">for</span> (<span class="kwrd">int</span> Y = 0, Y2=0; Buf != End; Y2&#43;= dY2, Y=(Y2&gt;&gt;10))
                    <span class="kwrd">for</span> (<span class="kwrd">int</span> X=0,J=Y*Width2,I=J*3,I2=Y*Width2*1024;
                        Buf != End &amp;&amp; X &lt; Width;
                        X&#43;&#43;, Buf&#43;=3, I2&#43;= dX2, J=(I2&gt;&gt;10),I=3*J)
                    {
                        <span class="kwrd">if</span> (0 != IsPenPoint[J])
                        {
                            Buf[0] = CurrentPoint[I];
                            Buf[1] = CurrentPoint[I&#43;1];
                            Buf[2] = CurrentPoint[I&#43;2];
                        }
                    }
            }
        }
    }
    <span class="kwrd">return</span> 0;
}</pre>
<h3>The Graph to Paint on a Movie</h3>
<p>We can take this a step further by painting onto a movie. This means we need two video sources: one for the camera (which can see the pen light), and one for the movie.</p>
<p align="center"><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9990783/image_20.png"><strong></a><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9990783/image_20.png"><img title="image" border="0" alt="image" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9990783/image_thumb_9.png" width="432" height="152"></a></strong><strong>
<br>
Figure 5: DirectShow when painting on a movie, using your own microphone or the movie's audio</strong></p>
<p>There are <i>two</i> separate filter graphs here. The top graph captures the pen strokes from the camera. The lower graph captures video from a video file, overlays the pen strokes, and previews and encodes the video. The code selects one of the dashed lines
 at run-time. If the user chooses to use the movie's original audio track, the WM Asf Writer's audio input is connected to the movie's output. Otherwise, the input is connected to the microphone.</p>
<p>We've also introduce two more components:</p>
<ul>
<li>The <i>WM Asf Reader, </i>which reads from a video file </li><li>The <i>Color Convert,</i> which converts the video to RGB format. The video cameras allow a variety of output formats, and the delegate selects the RGB format. However, movie files tend to have only one output encoding, and it's seldom RGB.</li></ul>
<h3>Conclusion</h3>
<p>In this article, I described how to create a paint-with-light effect on pictures, movies, etc. using a webcam. I reviewed the key concepts of DirectShow and how they can be used to create the video. Watching a movie of a sketch being drawn is what makes
 this different from a simple doodle on a picture.</p>
<p>If you want to try this out, check the download link for the source code at the top of the article!</p>
<h3>About The Author</h3>
<p>Randall Maas writes firmware for medical devices, and consults in embedded firmware. Before that, he did a lot of other things… like everyone else in the software industry. You can contact him at randym@acm.org.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Randall-Maas/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:9fce7b2c48684c589adc9e7600c9a5ae">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Paint-With-Light</comments>
      <itunes:summary>
This article is about a winter project I did to learn about video processing and the DirectShow framework. I decided to try making some painting-with-light movies, like those you often see in commercials. When we started, I could not find an existing project—so
 I bought a couple of webcams and wrote one. 
You can see a quick demonstration of the program in action in the following video: 





In the next section, we&#39;ll learn how to use the program to create a movie. Then we&#39;ll look at how the program works and dive into the software&#39;s implementation. 
How to Use the Program
This section will give an overview of how to use the program to make a video. You will need three basic pieces: 

A pen light or laser pointer to draw sketches with. You can buy cheap laser pointers and LED penlights at almost any convenience or office supply store.
A web camera to capture the light pen. Software to get the video from the web camera and encode the video file. We&#39;ll discuss this program below.

You can create the program in simple six steps: 

Select a video camera to use (plug one in, if necessary) Configure the camera Set the threshold for the pen Select the background image or video, if you&#39;ll be using one Start recording Draw! 
Let&#39;s look at the application&#39;s controls: 
&amp;nbsp;Figure
 1: A screenshot of the application 
There are nine controls for the video camera, audio input and recording: 

A combo box for selecting the camera An option to flip the camera&#39;s video An option to tweak the camera&#39;s video control settings A slider to control the discrimination between the pen light and normal scene
A combo box for selecting the microphone to use when recording An option to choose the background An option to choose the desired size of the output video Buttons to start, stop or pause recording A button to clear the current drawing 

 
Some recommended settings for the camera:

Reduce exposure setting until there is no glare Lower the brightness until there is no glare Disable the</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Paint-With-Light</link>
      <pubDate>Mon, 05 Apr 2010 18:42:50 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Paint-With-Light</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9990783_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9990783_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Randall Maas</dc:creator>
      <itunes:author>Randall Maas</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Paint-With-Light/RSS</wfw:commentRss>
    </item>
  <item>
      <title>Halloween Gremlins</title>
      <description><![CDATA[
<p>This article describes a quick and easy application to play Halloween tricks on the PC.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9915768/clip_image001_2.jpg"><img title="clip_image001" border="0" alt="clip_image001" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9915768/clip_image001_thumb.jpg" width="282" height="135"></a></p>
<h3>Introduction</h3>
<p>This article describes “Gremlin”, a quick and easy application that lets you play Halloween tricks. When your victim's computer is idle, Gremlin moves windows around on the screen, changes the focus window, moves your mouse, scrolls windows, and types nonsensical
 stuff. When there is background noise – like someone talking – it will shake the screen, even as your victim is typing away.</p>
<h3>Deployment</h3>
<p><b>Run it right away</b>. You can download, copy theGremlin.exe executable and NAudio.dll to the victim's computer (say in c:\ directory), and then double click on the executable to run it.</p>
<p><b>Run it later.</b> The other option is to copy the executable and dll files (or a shortcut to it) to the Startup folder on the victim's machine and watch the fun begin when they start up their machine in the morning!</p>
<p>If the computer you're using runs on Windows XP the path is: </p>
<blockquote>
<p>C:\Documents and Settings\All Users\Start Menu\Programs\Startup</p>
</blockquote>
<p>With Vista and Windows 7 the path looks like: </p>
<blockquote>
<p>C:\Users\<i>USERNAME</i>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup</p>
</blockquote>
<p>Just remember to change <i>USERNAME</i> to the name of the user on your machine.</p>
<p></p>
<h4>Commandline</h4>
<p>Gremlin is compiled as a windows application, so it won't popup a terminal window if you double click on it, etc. But you can run it from the command line with flags:</p>
<blockquote>
<p><b>-aggressive</b> will make the gremlin's actions more obvious</p>
<p><b>-help</b> will display the command line options</p>
<p><b>-name</b> <i>NAME</i> is useful for testing. Gremlin will only use windows with this specific title or from this specific application. (Remember to drop the &quot;.exe&quot; from the application filename)</p>
</blockquote>
<p>To stop the program, press CTRL&#43;F2.</p>
<h3>And now … the dodgy bits</h3>
<p>The overall structure of the program is broken down into three kinds of functionality – actions, triggers and some interstitial glue:</p>
<p>Actions</p>
<ul>
<li>The screen-shaker is a window that makes the monitor look like it is shaking. Sort of like a loose cable on the back of the monitor.
</li><li>A random event might kick the windows around—either friction will slow them down, or...
</li><li>Gremlin will type nonsensical messages from the keyboard. These messages are then sent from a virtual keyboard, or they:
</li><li>Move the mouse around, or </li><li>Press the mouse buttons, or </li><li>Randomly switch the focus to another window </li></ul>
<p>Triggers</p>
<ul>
<li>An audio module listens for sounds that trigger the module that shakes your screen.
</li><li>Otherwise, the software uses a p/invoke to <strong>GetLastInputInfo()</strong> and waits for the user to be idle for a minute or two. When it detects that the user is inactive, it randomly selects and carries out actions.
</li></ul>
<p>Other</p>
<ul>
<li>A hidden window receives key press events. I tend to reuse this module a lot, as a way to
<i>stop</i> experimental programs that may have made my machine unusable. </li></ul>
<p>For fun, I'll describe a couple of these modules below.</p>
<p></p>
<h4>Screen shaker</h4>
<p>My favorite bit is the screen shaker. It grabs a picture of the screens, creates a window that spreads across them, and then moves that image back and forth a few pixels every 30ms or so, with a little bit of random rotation. (Faster computers, of course,
 get a better effect).</p>
<p>The screen shaker is special in four ways:</p>
<ul>
<li>It is a top-level window – no other windows are allowed to go over it. </li><li>This top-level window never becomes the focus window (the window that gets the keyboard events).
</li><li>Mouse button events (e.g. clicks and double-clicks) are passed through to the windows and desktop underneath. This gives the illusion that this is the &quot;real&quot; desktop shaking, by allowing a person to click on a button or text that passes the click thru to
 the <i>real</i> button or text. </li><li>It shakes each of the monitor's screens independently </li></ul>
<p>Some background: to create a window that looks like the shaking screen, I used two classes. The first is ScrShake (in ScreenShake.cs), which derives from the second class UnfocusableForm.&nbsp; I'll describe ScrShake first.</p>
<p>The screen shaking process requires five instance variables:</p>
<ul>
<li><i>animTimer</i> is a System.Windows.Forms.Timer used to force painting of a new frame on the screen.
</li><li><i>bx</i>, and <i>by </i>are how far the screen has shaken up or down, left or right.
</li><li><i>angle </i>is how much the screen has twisted during shaking. </li><li><i>screenBitmap</i> is an array of bitmaps, one for each of the monitors. </li></ul>
<p>This creates a window without a border or other trappings, then makes it the topmost window and sets a flag in the method variable ExStyle to ignore mouse clicks. More on this flag in a little while.</p>
<p></p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> ScrShake : UnfocusableForm
{
   <span class="kwrd">public</span> ScrShake(<span class="kwrd">double</span> ShakeCoef, <span class="kwrd">double</span> AngleCoef) : <span class="kwrd">base</span>(<span class="kwrd">true</span>)
   {
      <span class="kwrd">this</span>.SuspendLayout();
      … other setup code …
      <span class="rem">// This is needed since we're over the whole display, and we don't</span>
      <span class="rem">// want the other areas to be blurry</span>
      TransparencyKey =  BackColor = ForeColor = System.Drawing.Color.Fuchsia;
      DoubleBuffered = <span class="kwrd">true</span>;
      TopMost = <span class="kwrd">true</span>;
      FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

      ClientSize = <span class="kwrd">new</span> System.Drawing.Size(300, 300);
      Name = <span class="str">&quot;topimage&quot;</span>;
      ResumeLayout(<span class="kwrd">false</span>);

      <span class="rem">// This is need to pass mouse clicks thru to lower layers</span>
      ExStyle |= (<span class="kwrd">int</span>) WS . EX_TRANSPARENT;

      … More code that will be described later…
   }
}</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p><b><br>
</b></p>
<p>When the timer has done a given number of animations, it will call the Stop() method. This will stop the animation, clean it up, and hide the window:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">void</span> Stop()
{
   animTimer . Stop();
   Hide();
   screenBitmap = <span class="kwrd">null</span>;
}</pre>
<p>When the main loops that start the animated screen shaking process, it calls the Screens() method. This grabs an image of the screens, determines the shape of each monitor, and starts the animation for 10 frames.</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">internal</span> <span class="kwrd">void</span> Screens()
{
   <span class="kwrd">if</span> (Visible)
   {
      Stop();
      <span class="kwrd">return</span> ;
   }
   <span class="rem">// Grab the screens</span>
   screenBitmap = Program.GrabScreens();
   CountDown = 10;

   animTimer.Start();
   angle = 0.0f;
   … code to display the window and get shape of monitors (see below)…
}</pre>
<p><b><br>
</b></p>
<p>The screen capture portion is in ScreenCapture.cs. The method GrabScreens() creates an individual bitmap for each monitor and returns them as an array.</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">internal</span> <span class="kwrd">void</span> Screens()
{
   <span class="kwrd">if</span> (Visible)
   {
      Stop();
      <span class="kwrd">return</span> ;
   }
   <span class="rem">// Grab the screens</span>
   screenBitmap = Program.GrabScreens();
   CountDown = 10;

   animTimer.Start();
   angle = 0.0f;
   … code to display the window and get shape of monitors (see below)…
}</pre>
<p><b><br>
</b></p>
<p>The code below determines the bounds of each screen and builds up a size of all of the screens put together. The window will be set to be this size.
</p>
<p><b>C# </b></p>
<pre class="csharpcode">Screen[] AllScreens = Screen.AllScreens;

<span class="rem">// full width/height of all monitors combined</span>
Rectangle fullSize = AllScreens[0].Bounds;

<span class="rem">// find a rectangle that will encompass all monitors on the system</span>
<span class="rem">// (assuming the primary monitor is on the left/top!)</span>
<span class="kwrd">for</span> (<span class="kwrd">int</span> i = 1; i &lt; AllScreens.Length &amp;&amp; i &lt; screenBitmap.Length; i&#43;&#43;)
{
    Rectangle Bounds = AllScreens[i].Bounds;

    <span class="kwrd">if</span> (Bounds.Left &lt; fullSize.Left)
        fullSize.X = Bounds.X;

    <span class="kwrd">if</span> (Bounds.Right &gt; fullSize.Right)
        fullSize.Width = Bounds.Right - fullSize.X;

    <span class="kwrd">if</span> (Bounds.Top &lt; fullSize.Top)
        fullSize.Y = Bounds.Y;

    <span class="kwrd">if</span> (Bounds.Bottom &gt; fullSize.Bottom)
        fullSize.Height = Bounds.Bottom - fullSize.Y;
}</pre>
<p>The code to show the window, fill the whole screen, and move it to the top looks like:</p>
<p><b>C# </b></p>
<pre class="csharpcode">Show();
WindowState = FormWindowState.Normal;
<span class="rem">// cover all monitors with one gigantic window</span>
Location = <span class="kwrd">new</span> Point(fullSize.Left, fullSize.Top);
Size = <span class="kwrd">new</span> Size(fullSize.Width, fullSize.Height);

<span class="rem">// bring it to the top</span>
BringToFront();</pre>
<p>The constructor also created a timer that drives the screen shaking effect. The timer has a delegate that randomly selects the angle of rotation and the offset of the image, and triggers a repaint of the window. (The amount of shaking is controlled by two
 external variables called <i>AngleCoef</i> and <i>ShakeCoef</i>).</p>
<p><b>C# </b></p>
<pre class="csharpcode">animTimer = <span class="kwrd">new</span> System.Windows.Forms.Timer();
animTimer.Tick &#43;= <span class="kwrd">delegate</span>(<span class="kwrd">object</span> A, EventArgs E)
{
    <span class="kwrd">if</span> (--CountDown &lt; 1)
        Stop();

    angle &#43;= (<span class="kwrd">float</span>)((Program.Rnd.NextDouble() - 0.5) * AngleCoef);
    bx = (<span class="kwrd">float</span>)((Program.Rnd.NextDouble() - 0.5) * ShakeCoef);
    by = (<span class="kwrd">float</span>)((Program.Rnd.NextDouble() - 0.5) * ShakeCoef);
    Invalidate();
};

<span class="rem">// Sets the timer interval to 30 milliseconds.</span>
animTimer.Interval = 30;</pre>
<p>Although each monitor shifts up &amp; down, left &amp; right by the same amount, and rotates by the same angle, they are painted independently. This gives the illusion that each monitor has a shaky image. Paint the window is using the following code.
</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> OnPaint(PaintEventArgs e)
{
    <span class="kwrd">base</span>.OnPaint(e);
    Graphics g = e.Graphics;
    g.CompositingQuality = CompositingQuality.HighQuality;

    <span class="rem">// for each monitor, draw the effect</span>
    Screen[] AllScreens = Screen.AllScreens;
    <span class="kwrd">for</span>(<span class="kwrd">int</span> i = 0; i &lt; screenBitmap.Length; i&#43;&#43;)
    {
        <span class="kwrd">if</span> (<span class="kwrd">null</span> == screenBitmap[i])&nbsp;&nbsp; <span class="kwrd">continue</span>;
        g.SmoothingMode = SmoothingMode.HighQuality;

        <span class="rem">// grab the size of the current monitor</span>
        Rectangle region = AllScreens[i].Bounds;

        <span class="kwrd">double</span> ImWidth = screenBitmap[i].Width  * <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.Graphics.DpiX / screenBitmap[i].HorizontalResolution;
        <span class="kwrd">double</span> ImHeight= screenBitmap[i].Height * <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.Graphics.DpiY / screenBitmap[i].VerticalResolution;
        Matrix m = <span class="kwrd">new</span> Matrix();
        m.Translate( (<span class="kwrd">float</span>)(- ImWidth  /2), 
                  (<span class="kwrd">float</span>)(- ImHeight /2), MatrixOrder.Append);

        <span class="rem">// rotate the bitmap about the center</span>
        m.RotateAt(angle, <span class="kwrd">new</span> Point(0,0), MatrixOrder.Append);

        <span class="rem">// center the image no matter what its size is</span>
        m.Translate( region.Width /2 - bx, 
                  region.Height/2 - by, MatrixOrder.Append);

        <span class="rem">// assign our transformation matrix</span>
        g.Transform = m;

        <span class="rem">// draw it</span>
        g.DrawImage(screenBitmap[i], region.Left, region.Top);
    }</pre>
<h4>The Form that does nothing!</h4>
<p>The ScrShaker class uses a help class called UnfocusableForm (in UnfocusableForm.cs) to create a window that never becomes the focus window – it never receives key presses, etc.</p>
<p>This window has no trappings – no border, no resize gripper, no icon, no minimize / maximize buttons, no title bar.</p>
<p></p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> UnfocusableForm : Form
{
   <span class="kwrd">public</span> UnfocusableForm(<span class="kwrd">bool</span> X) : <span class="kwrd">base</span>()
   {
      <span class="kwrd">if</span> (X)
        {
           ControlBox = <span class="kwrd">false</span>;
           FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
           ShowInTaskbar = <span class="kwrd">false</span>;
           ShowIcon = <span class="kwrd">false</span>;
           MinimizeBox = <span class="kwrd">false</span>;
           SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
           StartPosition = System.Windows.Forms.FormStartPosition.Manual;
        }
   }</pre>
<p>Then it overrides the ShowWithoutActivation method so that the window will <i>
not</i> become the active when it is shown.</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">bool</span> ShowWithoutActivation
{ get {  <span class="kwrd">return</span> <span class="kwrd">true</span>; } }</pre>
<p>The UnfocusableForm class also overrides the CreateParams() method to set extra styles when creating the window. I haven't found a way to set these styles flexibly. Instead, the UnfocusableForm uses a method variable called ExStyle that allows derived classes
 to specify what flags they desire. In this case, The ScrShake class used the method variable to set a flag that ignore mouse clicks:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">protected</span> <span class="kwrd">override</span> CreateParams CreateParams
{
  get
  {
     CreateParams cp=<span class="kwrd">base</span>.CreateParams;
     cp . ExStyle |= ExStyle;
     <span class="kwrd">return</span> cp;
  }
}</pre>
<p><b><br>
</b>Finally, it captures a couple of events that ask a window if it would like to become the active window. (These usually happen when the user clicks on an inactive window):</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">internal</span> <span class="kwrd">const</span> <span class="kwrd">int</span> MA_NOACTIVATE = 0x0003;
<span class="kwrd">protected</span> <span class="kwrd">override</span> <span class="kwrd">void</span> WndProc(<span class="kwrd">ref</span> Message m)
{
  <span class="kwrd">if</span> (m.Msg == (<span class="kwrd">int</span>) WM.MOUSEACTIVATE)
  {
     m.Result = (IntPtr) MA_NOACTIVATE;
     <span class="kwrd">return</span>;
  }
  <span class="kwrd">if</span> (m.Msg == (<span class="kwrd">int</span>) WM.FOCUS)
  {
     m.Result = (IntPtr)1;
     <span class="kwrd">return</span>;
  }
  <span class="kwrd">base</span>.WndProc(<span class="kwrd">ref</span> m);
}</pre>
<h4>Sending Mouse Events</h4>
<p>Sending Mouse Events is simple, but not trivial. The wiki at Pinvoke.net provides the signature to the procedures and structures we need to pass to it. (Note: these structures are a bit different, based on
<a href="http://blogs.msdn.com/oldnewthing/archive/2009/08/13/9867383.aspx">a blog posting by Raymond Chen</a>)</p>
<p><b>C# </b></p>
<pre class="csharpcode">[DllImport(<span class="str">&quot;user32.dll&quot;</span>, EntryPoint = <span class="str">&quot;SendInput&quot;</span>, SetLastError = <span class="kwrd">true</span>)]
<span class="kwrd">static</span> <span class="kwrd">extern</span> <span class="kwrd">uint</span> SendInput(<span class="kwrd">uint</span> nInputs, INPUT[] Inputs, <span class="kwrd">int</span> cbSize);
[DllImport(<span class="str">&quot;user32.dll&quot;</span>, EntryPoint = <span class="str">&quot;GetMessageExtraInfo&quot;</span>, SetLastError = <span class="kwrd">true</span>)]
<span class="kwrd">static</span> <span class="kwrd">extern</span> IntPtr GetMessageExtraInfo();

[StructLayout(LayoutKind.Sequential)]
<span class="kwrd">struct</span> INPUT
{
   <span class="kwrd">internal</span> INPUTTYPE   type;
   <span class="kwrd">internal</span> INPUT_UNION i;
}

 <span class="rem">// This generates the anonymous union</span>
[StructLayout(LayoutKind.Explicit)]
<span class="kwrd">struct</span> INPUT_UNION
{
   [FieldOffset(0)]
   <span class="kwrd">public</span> MOUSEINPUT mi;
   [FieldOffset(0)]
   <span class="kwrd">public</span> KEYBDINPUT ki;
   [FieldOffset(0)]
   <span class="kwrd">public</span> HARDWAREINPUT hi;
};

[StructLayout(LayoutKind.Sequential)]
<span class="kwrd">struct</span> MOUSEINPUT
{
   <span class="kwrd">public</span> <span class="kwrd">int</span>    dx;
   <span class="kwrd">public</span> <span class="kwrd">int</span>    dy;
   <span class="kwrd">public</span> <span class="kwrd">int</span>    mouseData;
   <span class="kwrd">public</span> MOUSEEVENTF dwFlags;
   <span class="kwrd">public</span> <span class="kwrd">int</span>    time;
   <span class="kwrd">public</span> IntPtr dwExtraInfo;
}

[Flags]
<span class="kwrd">enum</span> MOUSEEVENTF : <span class="kwrd">int</span>
{
   MOVE       = 0x01,
   LEFTDOWN   = 0x02,
   LEFTUP     = 0x04,
   RIGHTDOWN  = 0x08,
   RIGHTUP    = 0x10,
   MIDDLEDOWN = 0x20,
   MIDDLEUP   = 0x40,
   ABSOLUTE   = 0x8000
}</pre>
<p><b><br>
</b></p>
<p>Each of these pieces go together in a specific way. To do a mouse movement, a mouse event structure needs to be created. This involves setting dwFlags to the kind of mouse event (a relative movement in this case), dx and dy to the number of pixels moved.
 It is also important to set dwExtraInfo to whatever GetMessageExtraInfo() is set to.</p>
<p><b>C# </b></p>
<pre class="csharpcode">MOUSEINPUT MEvent = <span class="kwrd">new</span> MOUSEINPUT();
MEvent.dwFlags = MOUSEEVENTF.MOVE;
MEvent.dx = Rnd . Next(-8, 8) ;
MEvent.dy = Rnd . Next(-8, 8);
MEvent.dwExtraInfo = GetMessageExtraInfo();
Send(MEvent);</pre>
<p>Sending the event takes a few more steps that are all wrapped in a helper methdo called Send(). Send these
<i>human interface device</i> events via the SendInput() procedure (earlier). The procedure takes an array of events, for different kinds of devices. We have to create the array, set the event type, copy the event data, and then make the call:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">virtual</span> <span class="kwrd">bool</span> Send(MOUSEINPUT Event)
{
  INPUT[] Events = <span class="kwrd">new</span> INPUT[1];
  Events[0] . type = INPUTTYPE . MOUSE;
  Events[0] . i.mi = MEvent;
  <span class="kwrd">return</span> SendInput((<span class="kwrd">uint</span>)Events.Length, Events, Marshal.SizeOf(Events[0])) &gt; 0; 
}</pre>
<p><b><br>
</b></p>
<p>From here, sending a mouse button click is pretty straight forward. A mouse click is really a mouse button press event, followed by a mouse button release event. To make things interesting the mouse button is choosen at random. The “ugly” part is that each
 of the mouse buttons is assigned a bit, so a binary shift is used to convert a button number to its bit. And the button release is yet another bit, so the second message shifts the flags, to move the bit from the “button pressed” state to the “button released
 state”.</p>
<p><b>C# </b></p>
<pre class="csharpcode">MOUSEINPUT MEvent = <span class="kwrd">new</span> MOUSEINPUT();
MEvent.dwFlags = (MOUSEEVENTF) (1 &lt;&lt; (2*Rnd.Next(0, 3)&#43;1)) ;
MEvent.dwExtraInfo = GetMessageExtraInfo ();
Send(MEvent);

MEvent.dwFlags = (MOUSEEVENTF)((<span class="kwrd">int</span>) MEvent.dwFlags &lt;&lt; 1);
MEvent.dwExtraInfo = GetMessageExtraInfo ();
Send(MEvent);</pre>
<p><b><br>
</b></p>
<h4>Generating deranged text</h4>
<p>The gremlin can also type deranged sentences that will appear in editors, if the user left one open. The SendWait() method in the SendKeys class does the typing itself:</p>
<p><b>C#</b>&nbsp;</p>
<pre class="csharpcode">SendKeys . SendWait(GenerateSentence());
SendKeys . SendWait(<span class="str">&quot;{ENTER}&quot;</span>);</pre>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9915768/clip_image001_5B6_5D.jpg"><img title="clip_image001[6]" border="0" alt="clip_image001[6]" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9915768/clip_image001_5B6_5D_thumb.jpg" width="282" height="135"></a></p>
<p>Generating the sentences is not difficult; I used a simplistic Markov generator. This generator starts by randomly selecting a word that can start a sentence. The
<i>Starts</i> variable is array which holds just these words. Then, in the Transition method, this word is used to find the
<i>next</i> word that can be included in the sentence. It does this by using a dictionary, called
<i>NonStart</i>, which given the word as a key, will return a list of all the words that can come after it. This process then repeats, appending the words onto the end of a string. It stops if it finds a word that can end a sentence.</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">static</span> Dictionary&lt;<span class="kwrd">string</span>,<span class="kwrd">string</span>[]&gt; NonStart ;
<span class="kwrd">static</span> <span class="kwrd">string</span>[] Starts;
<span class="kwrd">static</span> Dictionary&lt;<span class="kwrd">string</span>,<span class="kwrd">string</span>&gt; Terminal ;

<span class="kwrd">static</span> <span class="kwrd">string</span> GenerateSentence()
{
  StringBuilder SB = <span class="kwrd">new</span> StringBuilder();
  <span class="kwrd">string</span> Word = Starts[ Rnd.Next(0, Starts.Length) ];

  Transition(SB, Word);
  <span class="kwrd">return</span> SB.ToString();
}

<span class="kwrd">static</span> <span class="kwrd">void</span> Transition(StringBuilder SB, <span class="kwrd">string</span> Word)
{
  <span class="kwrd">while</span> (<span class="kwrd">true</span>)
  {
     SB.Append(Word);
     SB.Append(<span class="str">' '</span>);

     <span class="rem">// Look up word after this</span>
     <span class="kwrd">string</span>[] Nexts;
     <span class="kwrd">if</span> (!NonStart.TryGetValue(Word, <span class="kwrd">out</span> Nexts))
       <span class="kwrd">break</span>;
     <span class="kwrd">int</span> Idx = Rnd.Next(Terminal . ContainsKey(Word) ? -1 :0, Nexts.Length);
     <span class="kwrd">if</span> (Idx &lt; 0)
       <span class="kwrd">break</span>;
     Word = Nexts[Idx];
  }
}</pre>
<p><b><br>
</b></p>
<p>Building these two dictionaries and array is a pretty simple process. The BuildSuffixTree() method takes a string and splits it up into sentences. Then it splits each sentence into (lower case) words. The first word of the sentence goes onto the end of the
<i>Starts</i> array. Otherwise, the previous word is used to look up a list in a dictionary, and the current word is appended on to the list. This dictionary will become the
<i>NonStarts</i> dictionary. The last word of the sentence is also placed into the
<i>Terminal</i> dictionary, to indicate that this might be the end of a sentence.</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">static</span> <span class="kwrd">void</span> BuildSuffixTree()
{
  <span class="rem">// First, build up a list of words that start sentence, and transitions</span>
  List&lt;<span class="kwrd">string</span>&gt; Starts1 = <span class="kwrd">new</span> List&lt;<span class="kwrd">string</span>&gt;();
  Dictionary&lt;<span class="kwrd">string</span>,List&lt;<span class="kwrd">string</span>&gt;&gt; Trans = <span class="kwrd">new</span> Dictionary&lt;<span class="kwrd">string</span>,List&lt;<span class="kwrd">string</span>&gt;&gt;();
  <span class="kwrd">foreach</span>(<span class="kwrd">string</span> S1 <span class="kwrd">in</span> S.Split(<span class="kwrd">new</span> <span class="kwrd">char</span>[]{<span class="str">'.'</span>,<span class="str">'?'</span>,<span class="str">'!'</span>}))
  {
     <span class="kwrd">string</span> Prev=<span class="kwrd">null</span>;
     <span class="kwrd">foreach</span>(<span class="kwrd">string</span> S2 <span class="kwrd">in</span> S1.Split(<span class="kwrd">new</span> <span class="kwrd">char</span>[]{<span class="str">' '</span>,<span class="str">'\n'</span>,<span class="str">'\r'</span>,<span class="str">'\t'</span>,<span class="str">','</span>,<span class="str">';'</span>}))
     {
        <span class="kwrd">if</span> (S2 . Length &lt; 1)
          <span class="kwrd">continue</span>;
        <span class="kwrd">if</span> (<span class="kwrd">null</span> == Prev)
          {
             Starts1.Add(<span class="kwrd">string</span>.Intern(S2.ToLower()));
             Prev = <span class="kwrd">string</span>.Intern(S2.ToLower());
             <span class="kwrd">continue</span>;
          }
        List&lt;<span class="kwrd">string</span>&gt; Nextsa;
        <span class="kwrd">if</span> (! Trans.TryGetValue(Prev, <span class="kwrd">out</span> Nextsa))
          Trans[Prev] = Nextsa = <span class="kwrd">new</span> List&lt;<span class="kwrd">string</span>&gt;();
        Prev = <span class="kwrd">string</span>.Intern(S2.ToLower());
        Nextsa.Add(Prev);
     }
     <span class="kwrd">if</span> (<span class="kwrd">null</span> != Prev)
       Terminal[Prev] = Prev;
 }

 <span class="rem">// Next, flatten the list of words that start a sentence</span>
 Starts = Starts1.ToArray();

 <span class="rem">// Flatten the transition table</span>
 <span class="kwrd">foreach</span> (<span class="kwrd">string</span> S3 <span class="kwrd">in</span> Trans.Keys)
  NonStart[S3] = Trans [S3].ToArray();
}</pre>
<p><b><br>
</b></p>
<h3>The things that trigger action</h3>
<h4>The audio trigger</h4>
<p>The audio module (in file AudioTrigger.cs) listens in on all of the microphones. It uses NAudio, with a basic setup and delegate structure swiped from Mark Heath's article “.NET Audio Recording”. The first difference is that it registers
<i>all</i> audio input devices:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">static</span> WaveIn[] StartMics()
{
  <span class="kwrd">int</span> NumDevices = WaveIn.DeviceCount;
  WaveIn[] AudIns = <span class="kwrd">new</span> WaveIn[NumDevices];
  <span class="kwrd">for</span> (<span class="kwrd">int</span> waveInDevice = 0; waveInDevice &lt; NumDevices ; waveInDevice&#43;&#43;)
  {
     AudIns[waveInDevice] = <span class="kwrd">new</span> WaveIn();
     AudIns[waveInDevice].DeviceNumber = waveInDevice;
     AudIns[waveInDevice].DataAvailable &#43;= waveIn_DataAvailable;
     AudIns[waveInDevice].WaveFormat = <span class="kwrd">new</span> WaveFormat(8000, 1);
     AudIns[waveInDevice].StartRecording();
  }
  <span class="kwrd">return</span> AudIns;
}</pre>
<p>The real magic in the trigger is a modified version of the waveIn_DataAvailable delegate. Instead of saving the audio, it checks for any sound activity. It starts by checking to see if any of the sound amplitudes are greater than a pre-defined, very high
 threshold. Then the samples are squared and summed up, and the result is compared with a threshold. If it exceeds the threshold, the trigger is set. These two are good at catching the kind of sound made when a person is talking, futzing on the desk, or typing.</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9915768/clip_image002_2.jpg"><img title="clip_image002" border="0" alt="clip_image002" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9915768/clip_image002_thumb.jpg" width="372" height="210"></a></p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">static</span> <span class="kwrd">double</span> AudioThresh  = 0.8;
<span class="kwrd">static</span> <span class="kwrd">double</span> AudioThresh2 = 0.09;

<span class="kwrd">static</span> <span class="kwrd">void</span> waveIn_DataAvailable(<span class="kwrd">object</span> sender, WaveInEventArgs e)
{
  <span class="kwrd">bool</span> Tr = <span class="kwrd">false</span>;
  <span class="kwrd">double</span> Sum2  = 0;
  <span class="kwrd">int</span> Count = e.BytesRecorded / 2;
  <span class="kwrd">for</span> (<span class="kwrd">int</span> index = 0; index &lt; e.BytesRecorded; index &#43;= 2)
  {
     <span class="kwrd">double</span> Tmp = (<span class="kwrd">short</span>)((e.Buffer[index &#43; 1] &lt;&lt; 8) | e.Buffer[index &#43; 0]);
     Tmp /= 32768.0;
     Sum2 &#43;= Tmp*Tmp;
     <span class="kwrd">if</span> (Tmp &gt; AudioThresh)
       Tr = <span class="kwrd">true</span>;
  }
  Sum2 /= Count;

  <span class="rem">// If the Mean-Square is greater than a threshold, set a flag to indicate that noise has happened</span>
  <span class="kwrd">if</span> (Tr || Sum2 &gt; AudioThresh2)
    Interlocked.Exchange(<span class="kwrd">ref</span> AudioTrigger, 1);
}</pre>
<p><b><br>
</b></p>
<p>This sets a flag – AudioTrigger – which will be seen (and reset) in the main loop, with a bit of code that looks like:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">while</span> (0 == Shutdown)
{
    <span class="rem">// Do some lovely events</span>
    Application . DoEvents();
    Thread . Sleep (20);

    <span class="rem">//… do some other stuff ..</span>

    <span class="rem">// Check for a kick from the sound system</span>
    <span class="kwrd">if</span> (0 != AudioTrigger)
    {
        Interlocked . Exchange(<span class="kwrd">ref</span> AudioTrigger, 0);
        …
        ScreenShaker . Screens();
        <span class="kwrd">continue</span>;
    }
    <span class="rem">//… more checks for the user idle trigger…</span>
}<b><br></b></pre>
<h4>Waiting for the user to be idle</h4>
<p>The check to see if the user is not doing anything, the main loop uses a helper method called LastInputTime(), which returns the number of milliseconds the user did any input activity. The loop ensures that the user has been idle for long enough, and then
 calls the method that selects random gremlin actions:</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">uint</span> LastTime = Win32.LastInputTime();
<span class="kwrd">if</span> ((<span class="kwrd">uint</span>) Environment.TickCount &lt; IdleTimeTrigger &#43; LastTime)
    <span class="kwrd">continue</span>;</pre>
<p>The LastInputTime() helper method uses a p/invoke call to the GetLastInputInfo() API call. The wiki at Pinvoke.net provides the signature to the procedure, and a suitable structure that we need to pass to it:</p>
<p><b>C# </b></p>
<pre class="csharpcode">[DllImport(<span class="str">&quot;User32.dll&quot;</span>)]
<span class="kwrd">static</span> <span class="kwrd">extern</span> <span class="kwrd">bool</span> GetLastInputInfo(<span class="kwrd">ref</span> LASTINPUTINFO LastInfo);

[StructLayout(LayoutKind.Sequential)]
<span class="kwrd">struct</span> LASTINPUTINFO
{
  <span class="kwrd">public</span> <span class="kwrd">uint</span> cbSize;

  <span class="rem">/// &lt;summary&gt;</span>
  <span class="rem">/// Number of system tickes</span>
  <span class="rem">/// &lt;/summary&gt;</span>
  <span class="kwrd">public</span> <span class="kwrd">uint</span> dwTime;
}</pre>
<p>Then, these two structures are wrapped up into the LastInputTime() helper procedure, which does the dirty work of allocating and initializing a structure.
</p>
<p><b>C# </b></p>
<pre class="csharpcode"><span class="kwrd">internal</span> <span class="kwrd">static</span> <span class="kwrd">uint</span> LastInputTime()
{
  LASTINPUTINFO lastInput=<span class="kwrd">new</span> LASTINPUTINFO();
  lastInput.cbSize = (<span class="kwrd">uint</span>)Marshal.SizeOf(lastInput);
  GetLastInputInfo(<span class="kwrd">ref</span> lastInput);
  <span class="kwrd">return</span> lastInput . dwTime;
}<b><br></b></pre>
<h3>Conclusion</h3>
<p>The tricks gremlin plays are intended to be somewhat subtle. There is an aggressive option to make it react more, and move windows around more visibly.
</p>
<p>If you want to try this out, the download link for the <a href="http://gremlin.codeplex.com/Release/ProjectReleases.aspx">
executable</a> and <a href="http://gremlin.codeplex.com/SourceControl/ListDownloadableCommits.aspx">
source code</a> are at the top of the article!</p>
<h4>Resources and References</h4>
<p>This article is a blatant grab bag of experimental and reused code from earlier experiments and other demo programs. Below are some of the projects I lifted code examples from:</p>
<ul>
<li><a href="http://pinvoke.net/">Pinvoke.net</a> – a wiki-style site with many useful bits of example code related to calling the Windows API from within .NET.
</li><li><a href="http://blogs.msdn.com/coding4fun/archive/2009/10/08/9905168.aspx">“.NET Audio Recorder”</a> by Mark Heath, from which I stole code to make the audio trigger.
</li><li><a href="http://blogs.msdn.com/coding4fun/archive/2007/10/29/5773776.aspx">“Possessed PC Pranks for Halloween”</a> by Brian Peek, from which I stole the basic code for sending keystrokes.
</li><li><a href="http://blogs.msdn.com/coding4fun/archive/2007/03/29/1991785.aspx">“April Fools' Day Application”</a> by Brian Peek, from which I stole code to grab the screen and rotate it.
</li></ul>
<h3>About The Author</h3>
<p>Randall Maas writes firmware for medical devices, and consults in embedded software. Before that he did a lot of other things… like everyone else in the software industry. You can contact him at
<a href="mailto:randym@acm.org">randym@acm.org</a>.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Randall-Maas/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:144c71c45bb4497091de9e7600caf138">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Halloween-Gremlins</comments>
      <itunes:summary>
This article describes a quick and easy application to play Halloween tricks on the PC. 
 
Introduction
This article describes “Gremlin”, a quick and easy application that lets you play Halloween tricks. When your victim&#39;s computer is idle, Gremlin moves windows around on the screen, changes the focus window, moves your mouse, scrolls windows, and types nonsensical
 stuff. When there is background noise – like someone talking – it will shake the screen, even as your victim is typing away. 
Deployment
Run it right away. You can download, copy theGremlin.exe executable and NAudio.dll to the victim&#39;s computer (say in c:\ directory), and then double click on the executable to run it. 
Run it later. The other option is to copy the executable and dll files (or a shortcut to it) to the Startup folder on the victim&#39;s machine and watch the fun begin when they start up their machine in the morning! 
If the computer you&#39;re using runs on Windows XP the path is:  

C:\Documents and Settings\All Users\Start Menu\Programs\Startup 

With Vista and Windows 7 the path looks like:  

C:\Users\USERNAME\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup 

Just remember to change USERNAME to the name of the user on your machine. 
 
Commandline
Gremlin is compiled as a windows application, so it won&#39;t popup a terminal window if you double click on it, etc. But you can run it from the command line with flags: 

-aggressive will make the gremlin&#39;s actions more obvious 
-help will display the command line options 
-name NAME is useful for testing. Gremlin will only use windows with this specific title or from this specific application. (Remember to drop the &amp;quot;.exe&amp;quot; from the application filename) 

To stop the program, press CTRL&amp;#43;F2. 
And now … the dodgy bits
The overall structure of the program is broken down into three kinds of functionality – actions, triggers and some interstitial glue: 
Actions 

The screen-shaker is a window that makes the monitor look like it i</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Halloween-Gremlins</link>
      <pubDate>Sat, 31 Oct 2009 22:37:42 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Halloween-Gremlins</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9915768_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9915768_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Randall Maas</dc:creator>
      <itunes:author>Randall Maas</itunes:author>
      <slash:comments>0</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Halloween-Gremlins/RSS</wfw:commentRss>
      <category>Audio</category>
      <category>Halloween</category>
      <category>Pranks</category>
      <category>Holiday</category>
    </item>
  <item>
      <title>Adding Sidetone to Skype</title>
      <description><![CDATA[
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9583391/clip_image001_2.jpg"><img title="clip_image001" border="0" alt="clip_image001" align="right" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9583391/clip_image001_thumb.jpg" width="240" height="91"></a>Ever
 use a headset with Skype – and were frustrated that it was <i>too</i> quiet? This article shows how to add the sound of your own voice to the headset and not feel exhausted from shouting to be heard.</p>

<h3>Skype: I find your lack of feedback disturbing.</h3>
<p>This article will discuss how to build a software tool that makes it easier to talk into Skype with a headset.</p>
<p>Recently my family began experimenting with Skype, but we found that talking over Skype can be exhausting with headphones. After doing a little research, I learned that the problem was that we only heard the other party. You'd think that this is a good thing,
 but we have a social brain that works hard to gauge our behavior and adjust.</p>
<p>The answer is to feed a little bit of the microphone back into the earpiece, so that our brain knows how loud we're talking. This is called
<i>side tone</i> in the telecommunication industry. Without it, we talk louder and louder until we're sure that we'll be heard.</p>
<p>I couldn't find a Skype plug-in to do this… but I had just read a <a href="http://blogs.msdn.com/coding4fun/archive/2009/02/02/9391048.aspx">
Coding4Fun article, by Mark Heath, about adding audio effects to Skype</a>. I decided I was going to write a tool to add this feedback.</p>
<h4>How to use the tool</h4>
<p>First, let's take a look at how to use the application. Once it is running, there will be a microphone icon in the lower right hand corner of the screen:</p>
<p>Figure 1: Icon in the system notification tray</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9583391/clip_image004_2.jpg"><img title="clip_image004" border="0" alt="clip_image004" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9583391/clip_image004_thumb.jpg" width="160" height="53"></a></p>
<p>Clicking on it, will get the application control window:</p>
<p>Figure 2: The application's controls</p>
<p><a href="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9583391/clip_image006_2.jpg"><img title="clip_image006" border="0" alt="clip_image006" src="http://ecn.channel9.msdn.com/o9/c4fcontent/migration/9583391/clip_image006_thumb.jpg" width="447" height="333"></a></p>
<p>Let's look at the side tone controls:</p>
<ul>
<li>The “Side Tones” check box enables or disables the side tone. If you have headphones, you'll want this on; if you have loud speakers, you'll want it off.
</li><li>The slider controls the volume of the microphone in the headset. You can change it while talking. The volume will vary with microphone and headset.
</li></ul>
<p>You can do a “sound check” to see if the feedback is working by clicking on the Sound Check button, and adjusting the volume. I found that the volume setting that works best in a conversation is much, much lower than what works in a sound check.</p>
<p>Next, let's look at the AGC (“Automatic Gain Control”) section. When making a call, the software can automatically adjust how loud you sound to the other party:</p>
<ul>
<li>When “Low Pass” is checked, the headphone feedback is at 44100 samples/sec. The microphone sound is filtered to keep only the sounds below 8 Khz, converted to 16000/samples per second and sent to Skype. When it is not checked, headphone feedback is at 16000
 samples/sec, and sent to Skype without the low pass filter. </li><li>When &quot;Skype AutoGain&quot; is checked, it signals to Skype that Skype can use its own algorithm. When clear, Skype is told not to apply any adjustments.
</li><li>When &quot;AutoGain&quot; is checked, the custom Automatic Gain Control algorithm is used.
</li></ul>
<p>The Automatic Gain Control has three sliders:</p>
<ul>
<li>The “Cutoff” slider controls the distinction between background noise and conversation. Sound below this level is cutoff and silence is sent to Skype. This will vary with microphone – more sensitive (expensive) microphones will pick more background noise
 and be better with a higher setting. </li><li>The “Normal” slider controls the volume when you are talking normally. The Gain Control tries to raise the volume to this level.
</li><li>The “Loud” slider controls the volume when you talk exceptionally loud. This rarely happens, but when you
<i>do</i> talk louder than the Normal level, the Gain Control tries to adjust the volume to this level.
</li></ul>
<h3>How the Software Works</h3>
<p>I originally started this project by creating an effect for the <a href="http://blogs.msdn.com/coding4fun/archive/2009/02/02/9391048.aspx">
Skype Voice Changer</a>. My plan was to open a WaveStream, begin playing it on the headphones and copy the microphone stream to it.</p>
<p>I quickly found that this was not the way to add feedback. The underlying “WaveOut” system had a huge latency: Everything I heard in the headphones was at least a second or more behind what I was saying. This made it even harder to talk than before, and
 I had to abandon it.</p>
<p>While researching the problem I found a DirectSound code sample that I could modify into doing what I wanted. (This initial prototype didn't coordinate with Skype – it attached to the microphone and copied the sounds to the output, at a lower volume. But
 it was on <i>always on.</i>) The sound in the headphones is still slightly behind (the microphone) but is barely perceptible, and we'll muffle it a bit more to make it less distinguishable.</p>
<p>From here on I shall describe the major – or technically interesting – components of the program. We'll look at:</p>
<ol>
<li>DirectSound and Circular buffers </li><li>Sample Window and Sizing the buffers </li><li>Using WaitHandle's to Synchronize with DirectSound </li><li>IIR Filters </li><li>Automatic Gain Control </li><li>Estimating loudness </li></ol>
<p>Note: I won't be describing how to connect to Skype. Mark Heath's description is very good.</p>
<h4>DirectSound and Circular Buffers</h4>
<p>The DirectSound code is in AudioLoop.cs. The module sets DirectSound to capture sound from the default recording device at 16bits / sample at either 16000 or 44100 samples per second. The capture and playback buffers are configured in “looping” mode to act
 as circular buffers. The capture buffer eventually overwrites samples, and we'll lose them if we don't act fast enough; if we don't update the playback buffer, it will repeat the same sound over and over.</p>
<p>The <strong>StartMicrophone() </strong>procedure sets up the capture and playback buffers. Then it creates a thread to do the work. The thread is at a high priority so that if the OS has a choice between (say) email or processing sound, it does the sound.</p>
<p>The <strong>StopMicrophone() </strong>procedure stops the worker thread and cleans up the resources.</p>
<p>The software processes a fixed number of samples at a time, called the “sample window.” The buffers are several times the size of sample window, so that the system can keep capturing and playing while the software is processing them. The sound processing
 loop is the heart of the application:</p>
<ol>
<li>Wait for the next sample window to be ready </li><li>Copy the samples from the capture buffer </li><li>Process the samples and send the results to the playback buffer </li><li>Process the samples and sends the results to Skype </li></ol>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">while</span> (Runnable)
{
    <span class="kwrd">for</span> (<span class="kwrd">int</span> I = 0, offset = 0; Runnable &amp;&amp; I &lt; _bufferPositions; I&#43;&#43;, offset &#43;= bufferSize)
    {
        <span class="rem">// Wait for the sample areas to be ready</span>
        notificationEvent[I].WaitOne(Timeout.Infinite, <span class="kwrd">true</span>);

        <span class="rem">// Get the sound samples</span>
        <span class="kwrd">byte</span>[] buffer = (<span class="kwrd">byte</span>[]) captureBuffer.Read(offset, <span class="kwrd">typeof</span> (<span class="kwrd">byte</span>), LockFlag.None, bufferSize);

        <span class="rem">// Convert samples to 16bit PCM </span>
        <span class="kwrd">for</span> (<span class="kwrd">int</span> L = buffer.Length, J = 10, K = 0; K &lt; L; K &#43;= 2)
            PCM16Buffer[J&#43;&#43;] = (Int16) ((UInt16) buffer[K] | (((UInt16) buffer[K &#43; 1]) &lt;&lt; 8));

        <span class="rem">// Play them out to the ear, if applicable</span>
        <span class="kwrd">if</span> (<span class="kwrd">null</span> != playbackBuffer)
        {
            <span class="rem">// Perform a low pass filter to &quot;muffle&quot; the sound</span>
            Butterworth(PCM16Buffer, 10, LPSample, Coefs);

            <span class="rem">// put the muffled sample into the output buffer</span>
            <span class="rem">// -- The lock flag seems to work, but others may work too</span>
            playbackBuffer.Write(Idx, LPSample, LockFlag.None);
            Idx &#43;= buffer.Length;
            <span class="kwrd">if</span> (Idx &gt;= 4*bufferSize)
                Idx -= 4*bufferSize;
            <span class="kwrd">if</span> (!playing)
            {
                playbackBuffer.Volume = _Volume;
                playbackBuffer.Play(0, BufferPlayFlags.Looping);
                playing = <span class="kwrd">true</span>;
            }
        }

        <span class="rem">// Process the sound and deliver it to Skype</span>
        <span class="kwrd">if</span> (<span class="kwrd">null</span> != outStream)
        {
            <span class="kwrd">int</span> L = AGC.Process(PCM16Buffer, 10, buffer);
            <span class="kwrd">if</span> (0 != L)
                outStream.BeginSend(buffer, 0, L, SocketFlags.None, SendCallback, <span class="kwrd">null</span>);
            <span class="rem">// Note: could send out pink noise if L == 0</span>
        }

        <span class="rem">// Move the sliding window of the previous 10 samples into the start</span>
        <span class="rem">// of the PCM16Buffer</span>
        <span class="kwrd">for</span> (<span class="kwrd">int</span> K = 0, J = PCM16Buffer.Length - 10; K &lt; 10; K&#43;&#43;, J&#43;&#43;)
            PCM16Buffer[K] = PCM16Buffer[J];
    }
}</pre>
<style type="text/css">
<!--
.csharpcode, .csharpcode 
	{font-size:small;
	color:black;
	font-family:consolas,"Courier New",courier,monospace;
	background-color:#ffffff}
.csharpcode 
	{margin:0em}
.csharpcode .rem
	{color:#008000}
.csharpcode .kwrd
	{color:#0000ff}
.csharpcode .str
	{color:#006080}
.csharpcode .op
	{color:#0000c0}
.csharpcode .preproc
	{color:#cc6633}
.csharpcode .asp
	{background-color:#ffff00}
.csharpcode .html
	{color:#800000}
.csharpcode .attr
	{color:#ff0000}
.csharpcode .alt
	{background-color:#f4f4f4;
	width:100%;
	margin:0em}
.csharpcode .lnum
	{color:#606060}
-->
</style>
<p>Note the “for” loop at the bottom of the code. This preserves the last 10 incoming samples at the start of the buffer. This is needed to make the sound processing smooth, and will be discussed a bit later.</p>
<h4>Sample Window and Sizing the Buffers</h4>
<p>How big should the sample window be? This is bit of a trade off in responsiveness and design complexity.</p>
<p>I chose a window big enough to hold 10 milliseconds of sound. Since the ear is sensitive sound to delays of even 30 milliseconds, I cut this done so that a delay wouldn't be perceptible. (When I tried a 50 millisecond window, my voice came out the headphone
 sounding like an echo... and I found myself talking slower and slower.) The sample window could be made smaller, but I am sure that there is a point where the OS won't schedule the audio loop to wake-n-run more frequently. And, as the sample window gets smaller,
 the processing may drop in quality, because it doesn't have enough to work with.</p>
<p>The capture buffer is 8 times the size of the sample window. This ratio is arbitrary, but I wanted the buffer to be about an order of magnitude larger. My rationale is that if the processing falls behind, the sound – for the Skype call – won't be dropped.
 I feel that it is more important to preserve sound quality for the other party than to preserve the quality of feedback.</p>
<p>The playback buffer is four times the sample window. I wanted it small, so that if the processing fell behind, the replaying of a sound will seem to be a continuation of a current sound.</p>
<p>When writing the sound to the playback buffer, we have to track where in the buffer to put the samples. I tried to use GetCurrentPosition() to find where to write to next into the playback buffer; this created terrible sound. Instead, the software uses a
 local variable to track where to write next.</p>
<h4>DirectSound and Notifications</h4>
<p>How do we keep in sync with the sound capture – how do we know when a sample buffer is ready?</p>
<p>The application gives a table of buffer indices and WaitHandle's to DirectSound. When the capture buffer's write index reaches one of those indices, it signals the corresponding WaitHandle. The worker thread cycles performs a WaitOne() one each of the WaitHandle's,
 one at a time. As a convenience, we use a specific kind of WaitHandle called AutoResetEvent. This type of WaitHandle sets itself back to a “wait” state once WaitOne() returns.</p>
<p>If the thread has gotten behind, the WaitOne will return immediately, the loop processes the sample, and begins to catch up with the work.</p>
<p>We must use a separate AutoResetEvent for each of the 8 capture windows. The AutoResetEvent doesn't tell us if it was signaled multiple times. If only one AutoResetEvent handle were used, it wouldn't know that two (or more) sample windows were ready. Instead,
 it would process just one, falling further behind, adding latency. This would happen randomly overtime, and be hard to test consistently.</p>
<h4>IIR: Infinite Impulse Response Filters</h4>
<p>This project came together so quickly, so easy – once I found the right approach – that I couldn't resist getting fancy. I added a low-pass filter to muffle the feedback a little. And I added automatic gain control, as an experimental option.</p>
<p>For both of these I used a filtering algorithm called “IIR” (this stands for Infinite Impulse Response – but that term is a confusing mouthful, so let's just call it IIR). IIR is a special purpose virtual machine. Low-pass filters, high-pass filters, combinations
 of those filters, and even equalizers, can be specified, and use very specific techniques (like a compiler) to convert them into an IIR implementation.</p>
<p>(You could, instead, “compile” the filters to be the resistor values to use in a hardware circuit.
<i>That's programming in solder!)</i></p>
<p>The machine code for these IIR virtual machines is just two list of coefficients, called A &amp; B. The software emulator is code that
<i>looks</i> like the following bit of code:</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode">Out[0] = Sample[0];
Out[1] = Sample[1];
<span class="kwrd">for</span> (<span class="kwrd">int</span> Idx = 2; Idx &lt; N; Idx&#43;&#43;)
{
    Out[Idx] =
    B0 * Sample[Idx]
 &#43; B1 * Sample[Idx - 1]
 &#43; B2 * Sample[Idx - 2]
        <span class="rem">// … more like this …</span>
        <span class="rem">// Next, the feed back</span>
 - A1 * Out[Idx - 1]
 - A2 * Out[Idx - 2]
        <span class="rem">// … more like this …</span>
 ;
}</pre>
<p>IIRs are easy to implement - and take less CPU power than other methods. But sometimes they sound poor; if they sound too bad, you'll want to use a different technique. I found that the low-pass filters in this project work will for some microphones, and
 add a slight crackle to others.</p>
<h4>Example Low Pass Filter</h4>
<p>For the low pass filter to create the muffling, I used a Butterworth filter, using the code below. It takes a buffer of signed, 16-bit samples, and then converts the 16-bit values into a byte array suitable for the sound buffer.</p>
<p>The filter code is a bit different than the example code in the previous section. Most of the differences are for speed.</p>
<ul>
<li>This code doesn't use a buffer for the old values, instead uses separate variables for the elements of the buffer.&nbsp; It uses I_0,I_1,I_2 instead of Sample[Idx], Sample[Idx-1], and Sample[Idx-2]. It also uses O_1, and O_2 instead of Out[Idx-1] and Out[Idx-2].
</li><li>The A and B coefficients are put into a single array. It also <i>adds</i> two of the sample input values, and is missing a coefficient; this is because the B0 and B2 coefficients are always the same for this kind of filter.
</li></ul>
<p>There is one difference that is not for speed. These are tricks done to make the filter smooth, and needed because the sample window is so small. They preserve the state of filter. If we didn't preserve them, the filter would be starting and stopping so
 frequently that it would add distracting clicks to the output sound. The filters performance would be weakened, because the sample window isn't big enough to hold sounds lower than (about) 200 Hz. Preserving these values, the filter isn't starting and stopping,
 and doesn't really know about the sample window. All of the IIR filters in this program use similar techniques.</p>
<ul>
<li>O_1, O_2 are explicitly preserved across calls by being stored in class variables
</li><li>I_1 and I_2 are preserved by the audio loop (remember the warning about preserving 10 samples at the bottom of the loop?) The audio loop preserves the last 10 samples at the start of InBuffer. When this procedure is called, it retrieves the last two samples.
</li></ul>
<p><b>C#</b></p>
<pre class="csharpcode"><span class="kwrd">static</span> <span class="kwrd">double</span> O_1 = 0.0, O_2=0.0;

<span class="kwrd">static</span> <span class="kwrd">void</span> Butterworth(Int16[] InBuffer, <span class="kwrd">int</span> Ofs, <span class="kwrd">byte</span>[] OutBuffer, <span class="kwrd">double</span>[] Coefs)
{
  <span class="kwrd">double</span> C0=Coefs[0], C1=Coefs[1], C2 = Coefs[2], C3=Coefs[3];
  <span class="kwrd">double</span> I_1=InBuffer[Ofs-1], I_2= InBuffer[Ofs-2];
  <span class="kwrd">for</span> (<span class="kwrd">int</span> L = InBuffer . Length, J=0, I = Ofs; I &lt; L; I&#43;&#43;)
  {
     <span class="kwrd">double</span> I_0 = InBuffer[I];

     <span class="rem">// Filter the samples</span>
     <span class="kwrd">double</span> A = (I_0 &#43; I_2) * C0 &#43; I_1 * C1;
     I_2 = I_1;
     I_1 = I_0;

     A = A - O_1 * C2 - O_2 * C3;
     O_2 = O_1;
     O_1 = A;

     <span class="rem">// Convert it back to 16 bit</span>
     Int16 S;
     <span class="kwrd">if</span> (A &lt; -32767) S = -32767;
     <span class="kwrd">if</span> (A &gt; 32767)  S = 32767;
     <span class="kwrd">else</span> S = (Int16) A;

     <span class="rem">// Store it</span>
     OutBuffer[J&#43;&#43;] = (<span class="kwrd">byte</span>)(S &amp; 0xFF);
     OutBuffer[J&#43;&#43;] = (<span class="kwrd">byte</span>)(((UInt16)S &gt;&gt; 8) &amp; 0xFF);
  }
}</pre>
<p>Automatic Gain Control</p>
<p>I decided next to tackle a problem where my wife's voice did not carry well on calls. This happens a lot to her with cell phones – and answering machines. I was pretty sure that the problem was poor automatic-gain-control (AGC). The typical amplifier in
 a headset (and in Skype) estimates how loud our voice is, then increases – or decreases – the volume to a reasonable level. It was deciding that my wife's voice was background noise, and cutting her off.</p>
<p>I chose to write an alternate gain control that amplified the sound and passed it to Skype. That way we'd have four to choose from: The one built into the Microphone, the Soundcard's, Mine, and Skype's. (To be fair, these automatic gain controls work well
 in most cases).</p>
<p>The main portion of the gain control is implemented in the file GainControl.cs. The control algorithm is:</p>
<ol>
<li>Calculate (or estimate) how loud we are currently talking (using the Analyze() procedure)
</li><li>If the loudness is very low, no one is talking… so set the output to zero. (Without this step, the volume of noise and hum would be cranked up)
</li><li>Otherwise, compute the guess-gain by dividing how loud the sound of our voice should be by how loud it currently is
</li><li>Compute the gain (called MaxGain) at which the sound will start clipping. If the guess-gain is louder than this, reduce it to MaxGain.
</li><li>The software adjusts the gain for a gentle transition – especially in the case when we go from absolute quiet, to the start of talking. It does this by tracking the gain (called PrevGain) used in previous sample and the current one.
</li><li>Multiple all the samples by this gain value. </li><li>If the sample rate is greater than 16000 samples/sec
<ol>
<li>Do a low pass filter at 8 khz (again in IIR form). This helps prevent artifacts from down sampling
</li><li>Resample the sound to 16000 </li></ol>
</li></ol>
<p>The portion of code that calculates the gain looks like (CutOff_dB, LowGain_dB, and TgtGain_dB are the three slider values):</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">if</span> (!AutoGain)
    Gain = 1.0;
<span class="kwrd">else</span>
{
    <span class="kwrd">double</span> MaxGain;
    <span class="kwrd">double</span> dB = Analyze(InBuffer, Ofs, <span class="kwrd">out</span> MaxGain);

    <span class="kwrd">if</span> (dB &lt; CutOff_dB)
        Gain = 0.0;
    <span class="kwrd">else</span> <span class="kwrd">if</span> (dB &lt; LowGain_dB &#43; 4.0)
    {
        Gain = Math.Exp((LowGain_dB - dB) * db2log);
    }
    <span class="kwrd">else</span>
    {
        Gain = Math.Exp((TgtGain_dB - dB) * db2log);
    }
    Gain = (0.4 * Gain &#43; 0.6 * PrevGain);
    <span class="kwrd">if</span> (Gain &gt; MaxGain)
        Gain = MaxGain;
    PrevGain = Gain;
}

<span class="rem">// Skip further process if there is silence</span>
<span class="kwrd">if</span> (0.0 == Gain)
{
    <span class="kwrd">return</span> 0;
}</pre>
<p>If you look at the code, you'll see that we don't compare directly with LowGain_db; rather we compare the estimate volume with LowGain_db&#43;4. This gives a little “hysteresis” – if we raise our voice momentarily, the software won't suddenly make it the highest
 possible volume. Instead, the software lowers the volume a little bit.</p>
<p>When the software changes the sample rate, it basically needs to know how many input samples to skip. At the start of a call, the software computes this, calling it InInc:</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="rem">// Calculate how we resample to 16Khz</span>
InInc = (<span class="kwrd">int</span>)(1024.0 * SampleRate / 16000.0);</pre>
<p>The process of applying the gain adjustment, performing a low pass filter and re-sampling is below:</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">int</span> NumSamples = InBuffer.Length;
<span class="kwrd">int</span> End = OutBuffer.Length;
<span class="kwrd">int</span> NextIdxForOut = -InInc;
<span class="kwrd">int</span> OutIdx = 0;
<span class="kwrd">for</span> (<span class="kwrd">int</span> I = Ofs; OutIdx &lt; End &amp;&amp; I &lt; NumSamples; I&#43;&#43;)
{
    <span class="rem">// Retrieve the sample</span>
    Int16 S = InBuffer[I];
    <span class="kwrd">double</span> I_0 = S;

    <span class="rem">// Apply Gain</span>
    I_0 *= Gain;

    <span class="rem">// 8khz low pass filter </span>
    <span class="kwrd">if</span> (DoLP)
    {
        <span class="rem">// Simple Butterworth 8KHz low-pass filter</span>
        <span class="kwrd">double</span> A = (I_0 &#43; DS_I_2) * LP[0] &#43; DS_I_1 * LP[1];
        DS_I_2 = DS_I_1;
        DS_I_1 = I_0;
        I_0 = A - DS_O_1 * LP[2] - DS_O_2 * LP[3];
        DS_O_2 = DS_O_1;
        DS_O_1 = I_0;

        <span class="rem">// Change sample rate</span>
        <span class="kwrd">int</span> Tmp = NextIdxForOut / 1024;
        <span class="kwrd">if</span> (I &lt; Tmp)
            <span class="kwrd">continue</span>;
        NextIdxForOut &#43;= InInc;
    }

    <span class="rem">// Convert it back to 16 bit</span>
    S = (Int16)I_0;

    <span class="rem">// Store it</span>
    OutBuffer[OutIdx&#43;&#43;] = (<span class="kwrd">byte</span>)(S &amp; 0xFF);
    OutBuffer[OutIdx&#43;&#43;] = (<span class="kwrd">byte</span>)(((UInt16)S &gt;&gt; 8) &amp; 0xFF);
}</pre>
<p>Estimating Volume</p>
<p>How loud “it should be” is controlled by a slider on the screen. The software estimates how loud the sound is by using
<a href="http://replaygain.hydrogenaudio.org/equal_loudness.html">an algorithm devised by David Robinson</a> that takes into account how it sounds
<i>to a person</i>. This way we can increase the gain on hard to hear sounds, and reduce the gain on sounds that a person is very sensitive to.</p>
<p>The loudness estimator, implemented in the Analysis procedure in GainAnalysis.cs, uses the following algorithm:</p>
<ol>
<li>Uses a combination of two (IIR) filters to make the sound to reflect how our ears hear it.
</li><li>Compute the Mean-Square value of the filtered sound (called MS) </li><li>Track the last 750 ms of these values. </li><li>Make a sorted copy of these. </li><li>Retrieve the first non-zero value at least 95% of the way into the buffer. This is so that we don't take the loudest sample and assume that is how the person is talking.
</li><li>If MS (the value computed in step 2) is much quieter, use that one instead </li><li>Convert this value into dB scale by performing a logarithm on it. </li></ol>
<p>The code to “normalize” the sound into how a person hears it is below. Along the way it computes the square of the samples (used in step 2). Like the earlier IIR filters, these preserves their variables across the calls. The first IIR is a yulewalk filter,
 but it preserves it old intermediary values in an array. Like the trick in AudioLoop, where we copy the last 10 samples into the start of the current buffer, the analysis procedure copies the last 10 immediate values into the start of YuleTmp array.</p>
<p>The output of the yulewalk filter is feed into a 150Hz high pass filter. It is essentially the same as the low-pass filter described earlier.</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">for</span> (<span class="kwrd">int</span> L = Samples.Length, N = Ofs; N &lt; L; N&#43;&#43;)
{
    <span class="kwrd">int</span> _V = Samples[N];
    <span class="kwrd">double</span> V = _V;
    <span class="kwrd">if</span> (_V &gt; MaxSample) MaxSample = _V;
    <span class="kwrd">if</span> (-_V &gt; MaxSample) MaxSample = -_V;

    <span class="rem">// Perform yulewalk filter</span>
    <span class="kwrd">double</span> S = V * YuleCoefs[0];
    <span class="kwrd">for</span> (<span class="kwrd">int</span> J = N - 1, I = 1; I &lt; 11; I&#43;&#43;, J--)
        S &#43;= Samples[J] * YuleCoefs[I];
    <span class="kwrd">for</span> (<span class="kwrd">int</span> J = N - 1, I = 11; I &lt; 21; I&#43;&#43;, J--)
        S -= YuleTmp[J] * YuleCoefs[I];

    <span class="rem">// Store for the feedback into the next stage of the yule walk</span>
    YuleTmp[N] = S;


    <span class="rem">// Perform butterworth high-pass filter stage, using S as an input</span>
    <span class="kwrd">double</span> Accum =
       (S &#43; GA_I_2) * HPCoefs[0]
       &#43; GA_I_1 * HPCoefs[1];
    GA_I_2 = GA_I_1;
    GA_I_1 = S;
    Accum = Accum - GA_O_1 * HPCoefs[2] - GA_O_2 * HPCoefs[3];

    GA_O_2 = GA_O_1;
    GA_O_1 = Accum;

    <span class="rem">// The square of the filtered results</span>
    Sum &#43;= Accum * Accum;
}

<span class="rem">// Copy the intermediate yulewalk state for the next</span>
<span class="rem">// (this is needed since we are looking at a fairly small time window)</span>
<span class="kwrd">for</span> (<span class="kwrd">int</span> I = 0, J = YuleTmp.Length - 10; I &lt; 10; I&#43;&#43;)
    YuleTmp[I] = YuleTmp[J];</pre>
<p>The mean-squared is computed:</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="rem">// The mean square of the filtered results</span>
<span class="kwrd">double</span> MS = Sum / NumSamples;</pre>
<p>Tracking the last 750ms of samples is a simple matter of putting it into a circular queue:</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode">MSQueue[QIdx&#43;&#43;] = MS;
<span class="kwrd">if</span> (QIdx &gt;= MSQueue . Length)
   QIdx = 0;</pre>
<p>Next, is the code to finding the first non-zero value 95% of the way into the buffer. It is a straightforward copy-the-array, sort it, and fetch:</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode">Array.Copy(MSQueue, SortedQ, MSQueue.Length);
Array.Sort(SortedQ);

<span class="rem">// Return the 95% </span>
<span class="kwrd">double</span> X = SortedQ[Q95Idx]; 
<span class="kwrd">for</span> (<span class="kwrd">int</span> I = Q95Idx &#43;1; X &lt; 400.0 &amp;&amp; I &lt; SortedQ . Length; I&#43;&#43;)
      X = SortedQ[I];</pre>
<p>Next, override this value if the current sample window is very, very quiet – that is, the user stopped talking. (If we don't do this, we'll amplify background noise between words)</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">if</span> (MS &lt; X * 0.40 &amp;&amp; MS &lt; 12800.0)
   X = MS;</pre>
<p>Finally, convert the result into decibels (or a reasonable approximation of a decibel)</p>
<p><b>C# <br>
</b></p>
<pre class="csharpcode"><span class="kwrd">return</span> 10.0 * Math . Log10 (X * 0.5 &#43; <span class="kwrd">double</span> . Epsilon);</pre>
<p>Note: The logarithm function takes a positive, non-zero floating point number. However, the value we pass to it can be zero; if we pass a zero, though, the Logarithm function would return a bad value. The simplest thing to do is check to see if the value
 we are passing is “zero” and not call Logarithm. However, I learned a long time ago to just add “epsilon” to the value to whatever we pass. This can really improve performance on number crunching.</p>
<h3>Conclusion</h3>
<p>This concludes how to add a little bit feedback and fancy amplification to you Skype phone calls.</p>
<p>If you want to try this out, the download link for the source code is at the top of the article!</p>
<p>If you'd like to experiment further, here are ideas of what can be done:</p>
<ol>
<li>DirectSound has echo cancellation and noise suppression. These seem desirable, esp. if you wanted to try making your own speakerphone. I was not able to get them to work and I would love to learn how.
</li><li>I'm sure it is possible to trim even more latency off of the side-tone playback, and I would be interested in learning better techniques to do so.
</li><li>Another would be to create the ideal equalizer from Robinson's Equal Loudness model, and use that filter and amplify the sound.
</li><li>It might be useful for the other party to control the settings, so that they decide when your voice has the right volume.
</li></ol>
<h4>Resources and References</h4>
<ul>
<li>David Robinson (while doing his PhD at University of Essex on human hearing).
<a href="http://replaygain.hydrogenaudio.org/equal_loudness.html">His algorithm</a> is intended to find the overall loudness of an album. He includes
<a href="http://replaygain.hydrogenaudio.org/mfiles/equalloudfilt.m">MATLAB scripts to compute coefficients</a> at custom sample rates, as well as some
<a href="http://replaygain.hydrogenaudio.org/equal_loud_coef.txt">pre-computed coefficients</a>.
</li><li>Mark Heath's <a href="http://blogs.msdn.com/coding4fun/archive/2009/02/02/9391048.aspx">
Skype Voice Changer</a> </li><li>Derek Pierson's <a href="http://blogs.msdn.com/coding4fun/archive/2006/11/02/938703.aspx">
DirectX tutorial</a> </li></ul>
<h3>About The Author</h3>
<p>Randall Maas writes firmware for medical devices, and consults in embedded software. Before that he did a lot of other things… like everyone else in the software industry. You can contact him at
<a href="mailto:randym@acm.org">randym@acm.org</a>.</p>
 <img src="http://m.webtrends.com/dcs1wotjh10000w0irc493s0e_6x1g/njs.gif?dcssip=channel9.msdn.com&dcsuri=http://channel9.msdn.com/Niners/c4f.Randall-Maas/Posts/RSS&WT.dl=0&WT.entryid=Entry:RSSView:3f2741667204495887219e7600cc49b6">]]></description>
      <comments>http://channel9.msdn.com/coding4fun/articles/Adding-Sidetone-to-Skype</comments>
      <itunes:summary>
Ever
 use a headset with Skype – and were frustrated that it was too quiet? This article shows how to add the sound of your own voice to the headset and not feel exhausted from shouting to be heard. 

Skype: I find your lack of feedback disturbing.
This article will discuss how to build a software tool that makes it easier to talk into Skype with a headset. 
Recently my family began experimenting with Skype, but we found that talking over Skype can be exhausting with headphones. After doing a little research, I learned that the problem was that we only heard the other party. You&#39;d think that this is a good thing,
 but we have a social brain that works hard to gauge our behavior and adjust. 
The answer is to feed a little bit of the microphone back into the earpiece, so that our brain knows how loud we&#39;re talking. This is called
side tone in the telecommunication industry. Without it, we talk louder and louder until we&#39;re sure that we&#39;ll be heard. 
I couldn&#39;t find a Skype plug-in to do this… but I had just read a 
Coding4Fun article, by Mark Heath, about adding audio effects to Skype. I decided I was going to write a tool to add this feedback. 
How to use the tool
First, let&#39;s take a look at how to use the application. Once it is running, there will be a microphone icon in the lower right hand corner of the screen: 
Figure 1: Icon in the system notification tray 
 
Clicking on it, will get the application control window: 
Figure 2: The application&#39;s controls 
 
Let&#39;s look at the side tone controls: 

The “Side Tones” check box enables or disables the side tone. If you have headphones, you&#39;ll want this on; if you have loud speakers, you&#39;ll want it off.
The slider controls the volume of the microphone in the headset. You can change it while talking. The volume will vary with microphone and headset.

You can do a “sound check” to see if the feedback is working by clicking on the Sound Check button, and adjusting the volume. I found that the volume setting that works be</itunes:summary>
      <link>http://channel9.msdn.com/coding4fun/articles/Adding-Sidetone-to-Skype</link>
      <pubDate>Tue, 09 Jun 2009 18:44:00 GMT</pubDate>
      <guid isPermaLink="false">http://channel9.msdn.com/coding4fun/articles/Adding-Sidetone-to-Skype</guid>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9583391_100.jpg" height="75" width="100"></media:thumbnail>
      <media:thumbnail url="http://ecn.channel9.msdn.com/o9/c4f/images/9583391_220.jpg" height="165" width="220"></media:thumbnail>      
      <dc:creator>Randall Maas</dc:creator>
      <itunes:author>Randall Maas</itunes:author>
      <slash:comments>1</slash:comments>
      <wfw:commentRss>http://channel9.msdn.com/coding4fun/articles/Adding-Sidetone-to-Skype/RSS</wfw:commentRss>
      <category>Audio</category>
      <category>utility</category>
      <category>Windows</category>
      <category>web miscellaneous</category>
    </item>    
</channel>
</rss>