title: Playing PCM stream from Web Audio API on Node.js
body: <p>I'm streaming recorded PCM audio from a browser with web audio api.</p>
  
  <p>I'm streaming it with <a href="https://github.com/binaryjs/binaryjs">binaryJS (websocket connection)</a> to a nodejs server and I'm trying to play that stream on the server using the speaker npm module.  </p>
  
  <p>This is my client.  <a href="https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer">The audio buffers are at first non-interleaved IEEE 32-bit linear PCM with a nominal range between -1 and +1</a>.  I take one of the two PCM channels to start off and stream it below.</p>
  
  <pre><code>var client = new BinaryClient('ws://localhost:9000');
  var Stream = client.send();
  
  recorder.onaudioprocess = function(AudioBuffer){
      var leftChannel = AudioBuffer.inputBuffer.getChannelData (0);
      Stream.write(leftChannel);
  }
  </code></pre>
  
  <p>Now I receive the data as a buffer and try writing it to a speaker object from the npm package.</p>
  
  <pre><code>var Speaker = require('speaker');
  
  var speaker = new Speaker({
    channels: 1,          // 1 channel
    bitDepth: 32,         // 32-bit samples
    sampleRate: 48000,     // 48,000 Hz sample rate
    signed:true
  });
  
  server.on('connection', function(client){
      client.on('stream', function(stream, meta){
          stream.on('data', function(data){
              speaker.write(leftchannel);
          });
      });
  });
  </code></pre>
  
  <p>The result is a high pitch screech on my laptop's speakers, which is clearly not what's being recorded. It's not feedback either.  I can confirm that the recording buffers on the client are valid since I tried writing them to a WAV file and it played back fine.  </p>
  
  <p>The <a href="https://github.com/TooTallNate/node-speaker">docs for speaker</a> and the <a href="https://developer.mozilla.org/en-US/docs/Web/API/AudioBuffer">docs for the AudioBuffer</a> in question</p>
  
  <p>I've been stumped on this for days.  Can someone figure out what is wrong or perhaps offer a different approach?</p>
  
  <h1><strong>Update with solution</strong></h1>
  
  <p>First off, I was using the websocket API incorrectly.  I updated above to use it correctly.</p>
  
  <p>I needed to convert the audio buffers to an array buffer of integers.  I choose to use <a href="https://developer.mozilla.org/en-US/docs/Web/API/Int16Array">Int16Array</a>.  Since the given audio buffer has a range in-between 1 and -1, it was as simple as multiplying by the range of the new ArrayBuffer (32767 to -32768).  </p>
  
  <pre><code>recorder.onaudioprocess = function(AudioBuffer){
  
      var left = AudioBuffer.inputBuffer.getChannelData (0);
  
      var l = left.length;
      var buf = new Int16Array(l)
  
      while (l--) {
          buf[l] = left[l]*0xFFFF;    //convert to 16 bit
      }
  
      Stream.write(buf.buffer);
  
  }
  </code></pre>