title: Convert wav streamed over HTTP to mp3, in real-time
body: <p><strong>Background</strong>: I am consuming a service which returns data with a MIME type of <code>audio/wav</code>.  I need to provide a playback mechanism for this audio (currently built as an MVC application).  As an example, my endpoint looks something like <code>https://audio.fooservice.com/GetAudio?audioId=123</code></p>
  
  <p>The audio is 8kHz, 1-channel u-law.</p>
  
  <p>Due to varying format support across browsers when using the HTML5 <code>&lt;audio&gt;</code> tag, I am unable to use the original u-law wav because Internet Explorer will not play it.</p>
  
  <p>My proposed solution is to do a real-time conversion from the source format to mp3.</p>
  
  <p>I've cobbled together a partially working solution from various other questions here and in the <em>NAudio</em> forums, but it throws an exception as noted in the comments below:</p>
  
  <pre><code>private void NAudioTest(string url)
  {
      Stream outStream = new MemoryStream();
      var format = WaveFormat.CreateMuLawFormat(8000, 1);
  
      using (Stream ms = new MemoryStream())
      {
          var request = (HttpWebRequest)WebRequest.Create(url);
          request.KeepAlive = false;
          request.ProtocolVersion = HttpVersion.Version10;
  
          using (Stream stream = request.GetResponse().GetResponseStream())
          {
              using (var reader = new RawSourceWaveStream(stream, format))
              {
                  // reader is not seekable; we need to convert to a byte array to seek
                  var bytes = reader.ToByteArray();
  
                  // create a new stream from the byte aray
                  var seekableStream = new MemoryStream(bytes);
  
                  // instantiating a WaveFileReader as follows will throw an exception:
                  // "System.FormatException: Not a WAVE file - no RIFF header"
                  using (var waveReader = new WaveFileReader(seekableStream))
                  {
                      using (var pcmStream = WaveFormatConversionStream.CreatePcmStream(waveReader))
                      {
                          var pcmBytes = pcmStream.ToByteArray();
                          var mp3 = pcmBytes.ToMp3();
                      }
                  }
              }
          }
      }
  }
  
  public static class StreamExtensions
  {
      public static byte[] ToByteArray(this Stream stream)
      {
          var ms = new MemoryStream();
          var buffer = new byte[1024];
          int bytes = 0;
  
          while ((bytes = stream.Read(buffer, 0, buffer.Length)) &gt; 0)
              ms.Write(buffer, 0, bytes);
  
          return ms.ToArray();
      }
  }
  
  public static class ByteExtensions
  {
      public static byte[] ToMp3(this byte[] bytes)
      {
          using (var outStream = new MemoryStream())
          {
              using (var ms = new MemoryStream(bytes))
              {
                  using (var reader = new WaveFileReader(ms))
                  {
                      using (var writer = new LameMP3FileWriter(outStream, reader.WaveFormat, 64))
                      {
                          reader.CopyTo(writer);
                          return outStream.ToArray();
                      }
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>I've been poking around at this for most of the day and I feel like I'm introducing unnecessary complexity into something that <strong>seems</strong> like it should be fairly straightforward.</p>
  
  <p>Any help would be much appreciated.</p>
  
  <p><strong>Note</strong>: I cannot change the source format and supporting IE is a requirement.</p>
  
  <p><strong>EDIT</strong>: I resolved the RIFF exception and am able to produce a stream of the MP3, but it's nothing but white noise.  Hopefully I can resolve that as well.  My new code is as follows:</p>
  
  <pre><code>[HttpGet]
  public ActionResult GetMp3(string url)
  {
      if (String.IsNullOrWhiteSpace(url))
          return null;
  
      var muLawFormat = WaveFormat.CreateMuLawFormat(8000, 1);
      var compressedStream = new MemoryStream();
  
      using (var ms = new MemoryStream())
      {
          var request = (HttpWebRequest)WebRequest.Create(url);
          request.KeepAlive = false;
          request.ProtocolVersion = HttpVersion.Version10;
  
          using (Stream webStream = request.GetResponse().GetResponseStream())
          {
              var buffer = new byte[4096];
              int read;
              while (webStream != null &amp;&amp; (read = webStream.Read(buffer, 0, buffer.Length)) &gt; 0)
                  ms.Write(buffer, 0, read);
          }
  
          ms.Position = 0;
  
          using (WaveStream wav = WaveFormatConversionStream.CreatePcmStream(new RawSourceWaveStream(ms, muLawFormat)))
          using (var mp3 = new LameMP3FileWriter(compressedStream, new WaveFormat(), LAMEPreset.MEDIUM_FAST))
              wav.CopyTo(mp3);
      }
  
      compressedStream.Seek(0, 0);
      return new FileStreamResult(compressedStream, "audio/mpeg");
  }
  </code></pre>