title: Save audio stream float frames as WAV with C#
body: <p>I am testing an application in C# that receives a live audio stream and then saves it to a WAV file. The audio stream has these characteristics: frequency or sampling rate: 16000, channels: 1, frame Samples Per Channel: 320, play Delay in Ms: 200. The audio frames come as floats, and I am collecting the float frames and storing them into a Memorystream with Binarywriter. After that, I convert the content of the Memorystream into an array, and that array then is converted to a Float array again. With the float array, I start the process to assemble the WAV file.</p>
  
  <p>I have compared the float frames values received with the ones inside the float array that I am using to build the WAV file and are the same. I am having trouble processing the float array to assemble the WAV file. I am not sure if I am doing the data conversion wrong with the <code>ConvertAndWrite()</code> method, or if the WAV header is not well formatted according to the characteristics of the audio stream. </p>
  
  <p>I can see the WAV file being created, but there is no content inside apart from the header I think. Any guidance will be much appreciated. I put together this sample code for you to test what I am doing:</p>
  
  <pre><code>using System;
  using System.IO;
  using System.Text;
  
  class SaveAudioStreamToWav
  {
  
      //Sample as received from stream. Here as a double to avoid altering the sample adding F to each value.
      public double[] receivedStreamSample = { 0, -0.003509521, -0.003356934, 0.0002746582, -0.004516602, -0.0027771, -0.0003967285, -0.001739502, 0.004150391, 0.0008544922, 0.002593994, 0.00970459, 0.003631592, 0.001800537, 0.004760742, 0.004272461, -0.002655029, -0.001495361, -0.006835938, -0.004211426, -0.0008239746, 0.001525879, 0.006347656, 0.002532959, -0.002471924, -0.001342773, 0.001159668, 0.0006713867, -0.000793457, 0.001403809, -0.0006713867, -0.0006713867, -0.0007629395, 0.0009460449, -0.003662109, 0.00390625, -0.001312256, -0.001678467, 0.002288818, -0.001831055, -0.00579834, 0.001220703, -0.005096436, -0.003631592, -0.007019043, -0.0001220703, -0.0008850098, -0.0001220703, -0.005371094, 0.004608154, 0.004425049, 0.0027771, 0.005279541, 0.0001525879, 0.0009765625, 0.004150391, -0.002807617, 0.001678467, -0.004577637, -0.002685547, -0.004364014, -0.0008544922, 0.001281738, -0.0009155273, -0.008148193, -0.001983643, 9.155273E-05, 0.0008239746, 0.0004272461, 0.002807617, -0.00289917, 0.002075195, 0.008392334, 0.003479004, 0.005615234, 0.0009460449, 0.002471924, 0.0004272461, -0.006164551, 0.0003967285, -0.0007629395, -0.007476807, -0.002532959, 0.01495361, 0.01382446, 0.002288818, -0.009063721, -0.1129761, -0.05401611, 0.03497314, -0.03027344, 0.08999634, 0.01831055, 0.01037598, 0.03302002, 0.02667236, 0.04309082, -0.01806641, -0.0440979, 0.07125854, 0.00680542, -0.01242065, 0.001983643, -0.03710938, 0.009552002, 0.01013184, 0.002258301, 0.007446289, 0.004486084, -0.009063721, -0.007293701, 0.008239746, -0.0003967285, 0.001556396, 0.001586914, 0.002258301, 0.001281738, 0.001617432, -0.001831055, 0.001556396, -0.001525879, -0.002410889, 0.004516602, 0.000793457, -0.001403809, -0.004882813, -0.0005187988, -0.003540039, -0.004302979, 0.0004272461, 0.004974365, -0.002868652, -0.003875732, -0.0001220703, 0.001617432, 0.002258301, -0.005889893, -0.001068115, 0.003295898, 0.002410889, -0.00201416, 0.001068115, 0.003143311, -0.001464844, 0.000579834, 0.005310059, 0.001434326, 0.001403809, 0.001312256, -0.001617432, 0.0009460449, -0.0009765625, -0.0007324219, -0.001617432, -0.004730225, 0.001373291, -0.001586914, 0.0005187988, 0.001556396, -0.001647949, 0.0008544922, 0.001739502, 0.0027771, 0.001831055, 3.051758E-05, -0.04672241, 0.02276611, 0.02529907, -0.005249023, -0.02285767, -0.0378418, -0.1454468, 0.04385376, -0.04058838, -0.005249023, -3.051758E-05, -0.02166748, -0.006378174, -0.002380371, -0.0368042, 0.04330444, -0.008453369, 0.0300293, -0.01651001, -0.005554199, -0.01828003, 0.008972168, -0.01571655, -0.01202393, 0.01141357, -0.003997803, 0.004119873, -0.002532959, 0.004333496, -0.001495361, -0.001281738, -0.003692627, -0.001647949, -0.001861572, 0.000793457, -0.0003662109, -0.002532959, -0.001342773, 0.0003051758, 0.002075195, 0.002349854, 0.001464844, 0.001678467, -0.0008850098, -0.0001525879, 0.003723145, -0.0009155273, 0.002807617, -0.005157471, -0.001617432, 0.002471924, 0.002166748, -0.0003356934, 0.000213623, -0.000793457, -0.0008544922, -0.00100708, 0.000213623, 0.001037598, -0.003448486, 0.0009460449, -0.0006103516, -0.002655029, -0.009735107, -0.01101685, 0.01937866, 0.00994873, -0.02600098, 0.04592896, 0.1063843, 0.002441406, -0.0100708, 0.002990723, -0.01235962, -0.003448486, 0.01089478, -0.01480103, -0.02902222, 0.02990723, -0.01376343, 0.01275635, -0.008666992, 0.006469727, -0.009857178, 0.002655029, -0.0004882813, 0.003814697, 0.004943848, -0.002990723, -0.0003051758, -0.001678467, 0.003265381, 0.0009460449, -9.155273E-05, -0.001403809, 0.001739502, -0.002685547, -0.0009460449, -0.001281738, 0.0009765625, 0.001312256, 0.002288818, -0.0002746582, -0.001098633, -0.002319336, -0.000793457, 0.001464844, 0.001281738, -0.002319336, 6.103516E-05, 0.0003967285, -0.002532959, 0.0002441406, 0.001861572, 0.0009765625 };
      public float[] floatsArray;
      public FileStream fileStream;
  
  
      static void Main(string[] args)
      {
          var saveAudioStreamToWav = new SaveAudioStreamToWav();
  
          saveAudioStreamToWav.ConvertDoubleToFloat();
          saveAudioStreamToWav.CreateEmpty(saveAudioStreamToWav.SetNameAndPath());
          saveAudioStreamToWav.ConvertAndWrite();
          saveAudioStreamToWav.WriteHeader();
      }
  
      public void ConvertDoubleToFloat()
      {
          floatsArray = new float[receivedStreamSample.Length];
          floatsArray = Array.ConvertAll(receivedStreamSample, x =&gt; (float)x);
      }
  
      public string SetNameAndPath()
      {
  
          //Setting the name of the file
          string timeStamp = DateTime.Now.ToString("yyyyMMddHHmmssfff");
          string filename = "/TestSavingStreamToWav_" + timeStamp + ".wav";
          string path = Directory.GetCurrentDirectory();
          string filepath = path + filename;
          Console.WriteLine(filepath);
          return filepath;
      }
  
      public void CreateEmpty(string filepath)
      {
          const int HEADER_SIZE = 44;
          fileStream = new FileStream(filepath, FileMode.CreateNew, FileAccess.ReadWrite);
          byte emptyByte = new byte();
  
          for (int i = 0; i &lt; HEADER_SIZE; i++) //preparing an empty space for the header
          {
              fileStream.WriteByte(emptyByte);
          }
  
      }
  
      public void ConvertAndWrite()
      {
  
          Int16[] intData = new Int16[floatsArray.Length];
  
          Byte[] bytesData = new Byte[floatsArray.Length * 2]; // bytesData array is twice the size of floatsArray array because a float converted in Int16 is 2 bytes.
  
          const float rescaleFactor = 32767; //to convert float to Int16
  
          for (var i = 0; i &lt; floatsArray.Length; i++)
          {
              intData[i] = (short)(floatsArray[i] * rescaleFactor);
              var byteArr = new Byte[2];
              byteArr = BitConverter.GetBytes(intData[i]);
              byteArr.CopyTo(bytesData, i * 2);
          }
          fileStream.Write(bytesData, 0, bytesData.Length);
  
  
      }
  
      public void WriteHeader()
      {
  
          int hz = 16000; //frequency or sampling rate
          int headerSize = 44; //default for uncompressed wav
  
          fileStream.Seek(0, SeekOrigin.Begin);
  
          Byte[] riff = System.Text.Encoding.UTF8.GetBytes("RIFF"); //RIFF marker. Marks the file as a riff file. Characters are each 1 byte long. 
          fileStream.Write(riff, 0, 4);
  
          Byte[] chunkSize = BitConverter.GetBytes(fileStream.Length - 8); //file-size (equals file-size - 8). Size of the overall file - 8 bytes, in bytes (32-bit integer). Typically, you'd fill this in after creation.
          fileStream.Write(chunkSize, 0, 4);
  
          Byte[] wave = System.Text.Encoding.UTF8.GetBytes("WAVE"); //File Type Header. For our purposes, it always equals "WAVE".
          fileStream.Write(wave, 0, 4);
  
          Byte[] fmt = System.Text.Encoding.UTF8.GetBytes("fmt "); //Mark the format section. Format chunk marker. Includes trailing null. 
          fileStream.Write(fmt, 0, 4);
  
          Byte[] subChunk1 = BitConverter.GetBytes(16); //Length of format data.  Always 16. 
          fileStream.Write(subChunk1, 0, 4);
  
          UInt16 two = 2;
          UInt16 one = 1;
  
          Byte[] audioFormat = BitConverter.GetBytes(one); //Type of format (1 is PCM, other number means compression) . 2 byte integer. Wave type PCM
          fileStream.Write(audioFormat, 0, 2);
  
          Byte[] numChannels = BitConverter.GetBytes(one); //Number of Channels - 2 byte integer
          fileStream.Write(numChannels, 0, 2);
  
          Byte[] sampleRate = BitConverter.GetBytes(hz); //Sample Rate - 32 byte integer. Sample Rate = Number of Samples per second, or Hertz.
          fileStream.Write(sampleRate, 0, 4);
  
          Byte[] byteRate = BitConverter.GetBytes(hz * 2 * 1);// sampleRate * bytesPerSample * number of channels, here 16000*2*1.
          fileStream.Write(byteRate, 0, 4);
  
          UInt16 blockAlign = (ushort)(1 * 2); //channels * bytesPerSample, here 1 * 2  // Bytes Per Sample: 1=8 bit Mono,  2 = 8 bit Stereo or 16 bit Mono, 4 = 16 bit Stereo
          fileStream.Write(BitConverter.GetBytes(blockAlign), 0, 2);
  
          UInt16 sixteen = 16;
          Byte[] bitsPerSample = BitConverter.GetBytes(sixteen); //Bits per sample (BitsPerSample * Channels) ?? should be 8???
          fileStream.Write(bitsPerSample, 0, 2);
  
          Byte[] dataString = System.Text.Encoding.UTF8.GetBytes("data"); //"data" chunk header. Marks the beginning of the data section.
          fileStream.Write(dataString, 0, 4);
  
          Byte[] subChunk2 = BitConverter.GetBytes(fileStream.Length - headerSize); //Size of the data section. data-size (equals file-size - 44). or NumSamples * NumChannels * bytesPerSample ??
          fileStream.Write(subChunk2, 0, 4);
  
          fileStream.Close();
      }
  
  }//end of class
  </code></pre>