title: Multiply audio signals for robot voice C#
body: <p>I'm trying to get the wave output of .NET SpeechSynthesizer to make the voice sound like robot-ish. </p>
  
  <p>After some research, I have found that ring modulation might be a good option to obtain the effect I want. I have seen that the formula is basically <code>Result(t) = Voice(t) * SineWave(t)</code>. </p>
  
  <p>Although, I have no idea of how I could apply this effect from a Wave Stream, is there any library out there to :</p>
  
  <ul>
  <li>Generate a sine wave and process it into a Wave Stream</li>
  <li>Multiply both Streams in order to get the result</li>
  </ul>
  
  <p>If not, do you know any other option ? Maybe I could multiply each sample in the Voice Wave Stream by each sample in the sine wave ?</p>
  
  <p>I'm using C# /.net framework.</p>
  
  <p>Thank you !</p>
  
  <p><strong>Edit :</strong> Okay, so after a few hours of failed attempts, I've finally came up with what seems to be the good result. The only problem is that there's a lot of crackling on the output, and the only fix I've found is to apply a low pass filter.</p>
  
  <p>Here's what I've got so far (quick, dirty and uncommented code, but should be self explanatory):</p>
  
  <pre><code>class Mixer
  {
      public static Stream RingModulation(Stream voiceStream, TimeSpan duration, SpeechAudioFormatInfo format)
      {
          var sineWave = SineOscillator.GenerateWave(duration, 80, 1, format);
          var numSamples = Convert.ToInt32(duration.TotalSeconds * format.SamplesPerSecond);
          var dataStream = new MemoryStream();
  
          sineWave.Position = 0;
          voiceStream.Position = 0;
  
          var buf1 = new byte[2];
          var buf2 = new byte[2];
          for (var i = 0; i &lt; numSamples; i++)
          {
              voiceStream.Read(buf1, 0, 2);
              sineWave.Read(buf2, 0, 2);
  
              var data = BitConverter.GetBytes(Convert.ToInt16(BitConverter.ToInt16(buf1, 0) * BitConverter.ToInt16(buf2, 0)));
              dataStream.Write(data, 0, data.Length);
          }
  
          return dataStream;
      }
  }
  
  class SineOscillator
  {
      public static Stream GenerateWave(TimeSpan duration, double frequency, int amplitude, SpeechAudioFormatInfo format)
      {
          var numSamples = Convert.ToInt32(duration.TotalSeconds * format.SamplesPerSecond);
          var dataStream = new MemoryStream();
          var angle = (Math.PI * 2 * frequency) / (format.SamplesPerSecond * format.ChannelCount);
  
          for (var i = 0; i &lt; numSamples; i++)
          {
              var data = BitConverter.GetBytes(Convert.ToInt16(amplitude * Math.Sin(angle*i)));
              // Generate a sine wave in both channels.
              dataStream.Write(data, 0, data.Length);
          }
  
          return dataStream;
      }
  } 
  </code></pre>
  
  <p>The low pass filter isn't applied yet, although, questions are still open in case someone has a good answer to provide and/or a better way to do it :)</p>