digital to analog

encode and decode an analog sound from binary data base on frequencies.

by francisfortier

HTML

<audio id="test" controls="controls"></audio>

JavaScript

window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder;
window.URL = window.URL || window.webkitURL;

HEADER = [82, 73, 70, 70, 0, 0, 0, 0, 87, 65, 86, 69, 102, 109, 116, 32, 16, 0, 0, 0, 1, 0, 1, 0, 68, 172, 0, 0, 136, 88, 1, 0, 2, 0, 16, 0, 100, 97, 116, 97, 0, 0, 0, 0];

BITS_PER_SECOND = 40;
SAMPLE_RATE = 44100;
BLOCK_ALIGN = 2
AVG_BYTES_PER_SEC = SAMPLE_RATE * BLOCK_ALIGN;

function digitalToAnalog(bits) {
    var duration = bits.length / BITS_PER_SECOND;
    var headerBuffer = new ArrayBuffer(HEADER.length);
    var headerArray = new Uint8Array(headerBuffer);
    
    for (var i = 0; i < headerArray.length; i++) {
        headerArray[i] = HEADER[i];
    }
    
    var a = new Uint32Array(headerBuffer);
    
    a[1] = AVG_BYTES_PER_SEC * duration + HEADER.length - 8; // RIFF size
    a[10] = AVG_BYTES_PER_SEC * duration; // data size
    
    var dataBuffer = new ArrayBuffer(AVG_BYTES_PER_SEC * duration);
    var sampleArray = new Int16Array(dataBuffer);
    
    var zero = 2 * Math.PI * 500 / SAMPLE_RATE;
    var one = 2 * Math.PI * 1000 / SAMPLE_RATE;
    var k;
    var bitIndex = 0;
    var samplePerBit = Math.floor(sampleArray.length / bits.length);
    
    for (var i = 0; i < sampleArray.length; i++)
    {
        if (i % samplePerBit === 0)
        {
            k = bits[bitIndex++] ? one : zero;
        }
        
        sampleArray[i] = Math.sin(k * i) * 0x7fff;
    }
    
    var builder = new BlobBuilder();
    
    builder.append(headerBuffer);
    builder.append(dataBuffer);
    
    return builder.getBlob("audio/wav");
}

function textToBinary(text) {
    var bits = [];
    
    for (var i = 0; i < text.length; i++)
    {
        var code = text.charCodeAt(i);
        
        if (code === 0)
        {
            for (var j = 0; j < 8; j++) bits.push(0);
        }
        else
        {
            var a = [];
            
            while (code !== 0)
            {
                a.unshift(code & 1);
                
        ...