The Swift series
Basics
- Hello Swift/Playgrounds
- Types conversion, subclassing, casting and drawing
- Swift/SpriteKit: Bouncing balls with built-in physics engine
- Swift/SpriteKit: Touch event and physics field
- Swift: ARC vs Flash GC
- Overflowing
- Bitmap Data and filters
- Drawing text on bitmap
- Preloading an image and displaying it
- Loading and parsing a remote JSON file
From microphone to .WAV to server with: getUserMedia and Web Audio
I blogged recently about capturing the audio from the Microphone with Web Audio and saving it as a .wav file. Some people asked me about saving the file on the server, I have to admit I did not have the time to look into this at that time, but it turns out, I had to write a little app this morning that does just that.
So I reused the code from the Web Audio article and just added the 2 additional pieces I needed.
- The XHR code for the upload
- 3 lines of PHP needed on the server.
So here we go. In the encoder, I had the following code to package our WAV file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
// we flat the left and right channels down var leftBuffer = mergeBuffers ( leftchannel, recordingLength ); var rightBuffer = mergeBuffers ( rightchannel, recordingLength ); // we interleave both channels together var interleaved = interleave ( leftBuffer, rightBuffer ); // we create our wav file var buffer = new ArrayBuffer(44 + interleaved.length * 2); var view = new DataView(buffer); // RIFF chunk descriptor writeUTFBytes(view, 0, 'RIFF'); view.setUint32(4, 44 + interleaved.length * 2, true); writeUTFBytes(view, 8, 'WAVE'); // FMT sub-chunk writeUTFBytes(view, 12, 'fmt '); view.setUint32(16, 16, true); view.setUint16(20, 1, true); // stereo (2 channels) view.setUint16(22, 2, true); view.setUint32(24, sampleRate, true); view.setUint32(28, sampleRate * 4, true); view.setUint16(32, 4, true); view.setUint16(34, 16, true); // data sub-chunk writeUTFBytes(view, 36, 'data'); view.setUint32(40, interleaved.length * 2, true); // write the PCM samples var lng = interleaved.length; var index = 44; var volume = 1; for (var i = 0; i < lng; i++){ view.setInt16(index, interleaved[i] * (0x7FFF * volume), true); index += 2; } // our final binary blob var blob = new Blob ( [ view ], { type : 'audio/wav' } ); |
The key piece is the last line. This is our blob that we will send to the server. To do this, we use our good friend XHR:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
function upload(blobOrFile) { var xhr = new XMLHttpRequest(); xhr.open('POST', './upload.php', true); xhr.onload = function(e) {}; // Listen to the upload progress. // assuming you have a progress element on your dom var progressBar = document.querySelector('progress'); xhr.upload.onprogress = function(e) { if (e.lengthComputable) { progressBar.value = (e.loaded / e.total) * 100; progressBar.textContent = progressBar.value; // Fallback for unsupported browsers. } }; xhr.send(blobOrFile); } |
It takes our blob as a parameter and sends it to our php file. Thank you Eric Bidelman for the great article about tricks with XHR on HTML5Rocks.com, the function is literally a copy/paste from there.
And then all you need are these 3 key lines of PHP code. Funny, these lines come from a Flash project where I needed to send raw binary data (ByteArray) through POST. Code recycling, simple, easy.
1 2 3 |
$fp = fopen( 'savedfile.wav', 'wb' ); fwrite( $fp, $GLOBALS[ 'HTTP_RAW_POST_DATA' ] ); fclose( $fp ); |
And that’s it. VoilĂ !
Posted on March 8, 2015 by Thibault Imbert · 10 comments Read More