Sunday, November 29, 2015

LESS is More

When a programer looks at a new language which is slightly different than general programming languages, first question that comes to his mind is if the language is turing complete. Similar thing happened to me when I looked at LESS. LESS is a CSS preprocessor and from a cursory look it looks like a macro sort of language which copy pastes definitions from one place to another. Actually, it is little more than that as it also tries to be a CSS like declarative language. That is, instead of defining variable you define properties and order defining those properties does not matter. Nevertheless, I have still not well understood the model of computation followed by this language, but it seems that even implementing a counter in this language is not very straightforward. I do not have anything to say to creators of LESS as it is not intended to be a general purpose language. Language does allow mathematical expression, variable definition, conditions (guards), methods. With these tools at hand I thought it would be easy to implement loops using recursion and calculate factorial and fibonacci sequence. My first attempt at creating a program that will find the factorial of a given number failed as it seems language does not allow updating a variable in a given scope once it is defined. At this point I knew that probably language does not well support writing such routines. I googled a lot to see if someone else has done something like this, but did not find anything. I was now looking for a language feature which could be exploited to carry out calculations and also preserve state. After trying many things I found that if you keep all the state in the form of parameters of a function (mixin), it is possible to get the effect of modifying a variable (state updation).  Below are some programs I wrote for calculating factorial and fibonacci numbers.
  
.fact_impl(@n,@res) when (@n > 1){
   .fact_impl(@n - 1, @res * (@n - 1));
}

.fact_impl(1,@res){
  @fact_res:@res;
}
.fact(@k){
  .fact_impl(@k,@k);
}

.fib_impl(@n,@first,@second) when (@n > 0){
  .fib_impl(@n - 1,@second,@first+@second);
}
.fib_impl(0,@first,@second){
  @fib_res:@first;
}
.fib(@k){
  .fib_impl(@k,0,1);
}

result{
  .fact(6);
  .fib(8);
  factorial_of_6:@fact_res;
  fibonacci_8:@fib_res;
}

LISP in Javascript

The main concept in LISP is that data is program and program is data. A wonderful way in which authors of SICP present the later is by creating data structure just by using functions. Lists in LISP and methods to operate on them can be created using just functions. We can do the same in Javascript as well, i.e. create List data-structure by just using functions and without objects or arrays. In fact we can create any data structure in this way. But an interesting question is where is data stored? (Its not too difficult to answer this question). Following is the JavaScript code which implements basic cons, car and cdr routines in Javascript.

  
function cons(x,y){
    var p=function(n){
        if(n==0)return x;
        if(n==1)return y;
        throw new Error("Index out of bound"+n);
    }
    p.toString=function(){
        return "("+x+","+y+")";
    }
    return p;
}
function car(z){
    return z(0);
}
function cdr(z){
    return z(1);
}


Now let us create some functions based on this list


  
/**
 * Syntactic sugar for constructing a list
 */
function list(){
   var args = [].slice.call(arguments);
   if(args.length == 0)
       return null;
   var first = args.shift();
   return cons(first,list.apply(this,args));
}
/**
 *  calculates length of the list
 */
function len(l){
    if(!l) return 0;
    return 1 + len(cdr(l))
}
/**
 * Calculate the factorials upto n
 * returns a list of factorials upto n
 */ 
function fact1(n,acc,a){
   if(n>1) return cons(acc,fact(n-1,acc*a,a+1));
   return acc;
}
function fact(n){
  return fact1(n,1,1);
}

These lists are created purely out of functions, we did not use any array or object type. This list can be extended to more complex data structures such as tree or graph.
Now let us create a little more complicated data structure, a binary search tree.
/**
 * Method to create a node in tree
 */
function create_node(val,left,right){
  return cons(val,cons(left,right));
}
/**
 * method to get left subtree
 */
function left(tree){
  return car(cdr(tree));
}
/**
 * method to get right subtree
 */
function right(tree){
  return cdr(cdr(tree));
}
/**
 * method to add a new number in binary search tree
 */
function add(num,tree){
    if(!tree){
      return create_node(num,null,null);
    }
    var val=car(tree);
    var l = left(tree);
    var r = right(tree);
    if(num > val) return create_node(val,l,add(num,r));
    if(num < val) return create_node(val,add(num,l),r);
    return tree;
}
/*
 * method to check if a number 
 * exists in the tree
 */
function num_exists(num,tree){
  if(tree){
     var l = left(tree);
     var r = right(tree);
     var val = car(tree);
     if(num == val){
       return true;
     }
     return num_exists(num,l) || num_exists(num,r);
  }
  return false;
}

/**
 * method to do in order traversal of tree
 * and output list of sorted nodes
 * @param tree current node to traverse in the tree
 * @parent list of root val and in order traversed 
 * list of right sibling subtree
 */
function traverse(tree,parent){
  if(!parent){
    parent = null;
  }
  if(tree){
     var l = left(tree);
     var r = right(tree);
     var val = car(tree);
     var traversedRight = traverse(r,parent);
     var trr = cons(val,traversedRight);
     return traverse(l,trr);
  }
  return parent;
}

/* sample run */
var tree = add(3);
tree=add(4,tree);
tree=add(9,tree);
tree=add(5,tree);
tree=add(1,tree);
tree=add(2,tree);
console.log(num_exists(5,tree)); // outputs: true
console.log(""+traverse(tree)); // outputs: (1,(2,(4,(5,(9,null)))))



As we can how complex data structures can be created without using any object or array

Friday, May 30, 2014

Quality

Recently I finished reading Zen and Art of Motorcycle Maintenance by Robert M. Pirsig. In this book Pirsig introduces a concept of Quality which is so weird that it cannot be defined. I found concept of Quality so intriguing that I went ahead and read his another book "Lila" in which he explains Quality in more detail and introduces some new concepts.

He describes Quality as something that cannot be defined because whenever you try to define it, it loses its essence and what we end up defining is something inferior to the Quality itself. He argues that we all know what Quality is but we cannot define it. For example we often talk about things having high quality and things having low Quality but when asked why, the answer usually varies from person to person and also from time to time.

My original intention here was to put down the concept of Quality in as much detail as I understand and in as simple terms as possible. But while writing this I quickly realized that it's very difficult if not impossible to nail down the concept of Quality. Trying to talk about Quality in its full genrality is like shaking a bee hive. Therefore, I will not attempt this. Instead, I will first present a simplified model of our universe and define what quality is in that universe.

This Model Universe ( or 'MUniverse' for short) consists of an arbitrary number of entities. These entities represent anything and everything of our real universe. An entity could represents something as small as a grain of salt or an atom, or something as big as mountain. It could represent something as simple as an atom or something as complex as a human being. In MUniverse these entities constantly interact with each other by exchanging messages.

Now these entities have an internal state which gets modified as they send and receive messages. Change in state of these entities can be small or large or there maybe no change at all. One other property of these entities is that usually these entities would not like their state to be changed, and when a message arrives they may either ignore the message completely or modify it so that change in their state is very small. So there is some discrepancy in the message that arrived and the message which actually took effect.

   Analogy to our real universe
   -------------------+----------------------------------------
       MUniverse      |      Real Universe
   -------------------+----------------------------------------------------
       Entities       |     everything from atom(or subatomic particles 
                      |     to human beings, thus group of entites is also 
                      |     entity
       Interactions   |     events, anything from motion, collision
                      |     or even thought.
   ------------------------------------------------------------------------
In this model of universe "Quality" is the message that originally arrived. And since it is we humans who have created the concepts of subject and objects, this distinction between subject and object arises only after message has been perceived either after modification or without any modification.

Prisig in his book further clarifies it by introducing two new concepts that of Static Quality and Dynamic Quality. Dynamic Quality is what we have been referring to as "Quality" so far. Static quality is the state in which entities have become stuck and are resisting any further change.

Now as in the Model I made it clear that a group entities can also form another entity which can have its own state and a state where this group as whole is stuck. This gives rise to a hierarchy of Static Qualities. Pirsig Identifies four levels of Static Qualities. Intellectual Quality, Social Quality, Biological Quality, Inorganic Quality.

Now according to Pirsig we normally perceive only Static Quality or in other words we are trying to ignore the original message (Dynamic Quality). This works well for some time as long as the descrepancy between Dynamic and Static Quality is not too much. When the difference between Dynamic Quality and Static Quality of entity is too great a change occurs which create a new Static Quality. This manifests itself as revolution in society when current Static Quality of society is replaced by new Dynamic Quality that someone or some group of people perceived which forms yet another Static Quality ( or state) which would last as long as it can model Dynamic Quality or the actual messages being sent quite well.

Pirsig also explains that when we solve a problem, one first tries everything one knows to find the solution. At some point it may also seem impossible to solve problem and we find ourselves stuck. It happens because we always were try not to percieve original message and are stuck within our state (Static Quality). After trying everything we know, we reach a state of mind where we have no idea good or bad in our mind. This is the state according to Pirsig that zen budhists try to achieve through meditation. In this state mind becomes empty and ready to accept original messages which are required to solve the problem at hand. In this state the problem and the solver become one. That is, there is no distinction between them just as there is no distinction between the entities of the Model universe they are just exchanging messages to each other. Ability to come into this state of oneness is what distinguishes as expert problem solver from a novice.

With this I hope I have been able to record the concept of quality that Pirsig wanted to communicate.

Stargazing

It all started when I suddenly became curious about Sunrise and Sunset times, probably because my watch can tell it too. Being able to predict Sunrise/Sunset time using model of Solar System is an indirect evidence that the model is correct and probably true also and we are really on a rotating ball which is revolving around Sun at an incredible speed. I was also interested in this because the calculation would have been a good computer programming assignment. This curiosity led me to understanding of solar system and sky beyond of what I ever had and much more than what we had studied. By the time I learnt rising and setting times of Sun, finding these for other stars and planets was also within my reach. First time in my life I was able to point at Venus, Jupiter and Mars. All this was very fascinating.

After researching a lot about telescopes and binoculars I chose to get binoculars because they are cheaper and their wide field of view is perfect when you are new to the sky and learning your way around it. So today I got my 15x70 binoculars. After getting them i was so excited and wanted to see stars through them. I left early from work to have a glance but when i reached i found that there was complete cloud cover. It was very disappointing. I went to the terrace looked through the binoculars, it was an impressive view . I could easily read number plate of a car parked two streets across.  I came down the stairs to my room and had dinner. Afterwards,  I went to balcony to see but there was still cloud cover. I saw that there were some patches of no cloud cover through which i could see clear sky and found one star was shinning through that hole between the clouds. Quickly  I ran to my room to pick pair of binocular. To my amazement I could see at least 10 stars through that hole where there was hardly one visible without them. I had never imagined that this could happen. Then, I went to terrace and targeted binocs at Jupiter. It was looking like a disk, then I tried to steady binocs to see if I could get a view of the moons of Jupiter and yes I could even see the moons. Then I checked the star map and it was showing that moon has not set yet but it is close to horizon. I decided to go to the higher terrace to get a look of the moon. Through binoculars, moon's craters were visible along the edge of crescent. Since power of binocs is not much moon is not visible close enough. However, because of quality You can see the definition of craters.

After that I spent some time looking at a star which I suppose was sirius. However I could not confirm whether it was sirius as I could not identify the canis major constellation. Then I started looking for pleadies in taurus constellation . I again checked my star map application and tried to star hope from jupiter which was in jemini to pla edies. But it was very difficult and only after many trials suddenly it came to my sight. Its was a beautiful view, indeed. The plaedies start have a kind of effect which make them look like a bunch of flash lights in the sky. At this point, I was quite tired and my neck started hurting due to looking up for so long that too with such a heavy binocs. I checked time it was around 11 PM. I thought I should sleep then  but I wanted to take another look at jupiter and its moons. By this time jupiter had shifted towards west from zenith position. This indicated me to look for mars position in the star map as mars might have risen from east now. I checked and affirmed that mars was quite visible above horizon and looking towards east I could see  a star close to the position shown in star map but I could not see another star spica near it as it was in virgo constellation. When i looked at it through binocular it appeared like a red dot which kind of confirmed to me that it was mars. All in all its was a wonderful time with my new binocs.

Tuesday, December 31, 2013

MD5 Revisited

Years ago I implemented MD5 in  C language as a college assignment. It was fun to implement something complex yet very straight forward. You just go over the RFC and  implement each step accurately. Only difficult part was debugging because even if you make a small mistake any where in the code the result is completely different and does not give any clue as to where the error is.

Years later I gave another look at the algorithm to get better understanding of the it. MD5 hash algorithm has three basic construction blocks.

1. Encryption Function: Converts a fixed sized input to fixed sized output such that output is a random permutation of the input. Encryption function also takes a key which can alter the permutations generated by the function. Encryption function by definition is reversible i.e. there exists a Decryption function such that given the output in can produce original input. In case of MD5, the encryption function takes a 32bit key and 128 bit input and 128 bit output. MD5 uses following encyptions function

def encrypt(f:(List[Int])=>Int,T:Int,S:Int)(data:List[Int],key:Int) =  
      data(3) :: 
      data(1) + rotateLeft((data(0)+f(data)+key+T),S) :: 
      data(1) :: 
      data(2) :: Nil
as you can see encryption function is parameterized by f,T and S. MD5 uses 64 different variations of encrypt function.

2. Compression Function: Compression Function takes a fixed sized input and converts it to a smaller fixed sized output. This function is one way i.e. there exists no function which can generate the input for a given output.Compression Functions are created using Encryption Function by applying it to a larger block again and again.

  In case of MD5 the compression function takes 512 bits as input and generates 128 bits of output.

 The 512 bit input is divided into 16 32 bit words. Each of these 32 bit words is used as key to the encryption function. This is repeated four times in four phases. In each phase a different permutation of 32 bit words is used. Thus, phases differ in two ways, first, the permutation of input and second, the encryption function used. Following function creates a four permutations, one for each phases and concatenates them. This results in 64 32 bit words.

  def permute(f:(Int)=>Int)(data:List[Int]):List[Int]={
      List.range(0,data.length).map((i)=>data(f(i)%data.length))
  }

  def permutations(chunk:List[Int]):List[Int]={
      permute((x:Int)=>x)(chunk):::
      permute((x:Int)=>(5*x+1))(chunk):::
      permute((x:Int)=>(3*x+5))(chunk):::
      permute((x:Int)=>(7*x))(chunk)
  }

The permute function takes a function and generates a permutation of data List according to it. permutations function returns four permutations one for each phase of compression function.

Once we have input data ready, we need to generate 64 different encryption functions, 16 for each phase. For this we need values for f,T and S. MD5 Compression function uses four different values of f, one for each phase.

  
  def F(x:Int,y:Int,z:Int) = x&y | ~(x)&z
  def G(x:Int,y:Int,z:Int) = x&z | y&(~z )
  def H(x:Int,y:Int,z:Int) = x ^ y ^ z
  def I(x:Int,y:Int,z:Int) = y ^ ( x | ~z )
  val fList = List(F _,G _,H _,I _).map(listyFy(_) _)

  def listyFy(f:(Int,Int,Int)=>Int)(d:List[Int]) = f(d(1),d(2),d(3))


  Above defines four different values of f. We also create a list these functions. listyFy function converts a function which takes three ints to a function which takes a list ints.

Following a list of functions which generate values for S for each phase.

val shiftfn=List( 
    (i:Int)=>5*i + 7,  (i:Int)=>(i*i + 7*i +10)/2,
    (i:Int)=>4 + 7*((i+1)/2) + 5*(i/2),  (i:Int)=>(i*i + 7*i +10)/2 + 1
  ).map((f)=>(x:Int)=>f(x%4));


Now below is the code which generates 64 encryption functions, which are used in each step of compression function .

def Ts(i:Int)=
      (math.floor(math.abs(math.sin(i+1))*(1L<<32)).toLong).toInt
val EList = 
      List.range(0,64).map((i:Int)=>encrypt(fList(i/16),
                                            Ts(i),
                       shiftfn(i/16)(i)) _)

Here we create EList, a list of 64 encryption function, by passing appropriate value of f,T and S to the encrypt function, which returns an encryption function corresponding to these values.
Now we can use this list of encryption function and permutation to define our compression Function.
  def compressMD5(state:List[Int],chunk:List[Byte]) = {
      val newstate =   permutations(asWords(chunk)).zip(EList).foldLeft(state)((x,y)=>y._2(x,y._1))
      newstate.zip(state).map({ case (a,b)=>(a+b)})
  }

compressMD5 takes a state, a list of four 32 bit words, and chunk, a list of 64 bytes. It converts 64 bytes in chunk to an array of 16, 32 bit words, using asWorkds utility function. It then creates permutations which results in 64 32 bit words, four permutation of 16 32 bit words. Then each of these words is applied as key to the corresponding encryption function in EList. The state variable is uses as initialization vector for this step which encrypted and then fed as data in to next encryption function. Finally, IV and resulting state and added word by word.


3. Hash Function: This is the final function which given input of any arbitrary length generates an output of fixed length. It usually uses merkel-damgard construction to apply a compression function to arbitrary large data.
   val initialState = List(0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476)
   def merkelDamgard(bytes:List[Byte]) = 
    (initialState /: packAs(64)( bytes++padding(bytes.length) ))(compressMD5)
This is the most straight forward step. It appends padding as required by merkelDamgard construction and divides resulting bytes in to chunks of 64 bytes which is equal to size of input of our compression function.

Sunday, November 17, 2013

Karplus–Strong string synthesis in JavaScript


Recently I came across this awesome algorithm which can generate sound of a plucked string, kind of like when picking guitar strings. Idea of generating sound of a guitar string fascinated me and I wanted to understand and finally implement the algorithm to see it working.

Before I go ahead and start explaining, you can try it out by click the button below.

Frequency: Hz.

There are plenty of places on the web that give details of  Karplus-Strong string synthesis algorithm. Basically, there are three main components that are required for this algorithm.
    1. Noise burst:  A source of white noise for a brief time. It is used to inject energy into the string, which happens when you pluck the string.
    2. Delay Line: A delay line which would re-inject the noise again into the circuit after certain time delay. The length of the time after which it should re-inject noise depends on the fundamental frequency of the string we want to simulate.
    3. Filter: A low pass filter to dampen out energy out of the string.

The algorithm by itself generates a stream of audio samples. These audio samples must be converted into an audio signal which will be sent to the speakers to produce sound. This can be done using Web Audio API which provides interfaces that take audio samples and send them to computer's hardware which can play them though the speakers. So, let us first get the setup ready which can send audio samples to the speaker.

The Setup

  if(window.webkitAudioContext){
       // Google Chrome
      var audioContext = new window.webkitAudioContext();
  } else {
       // Firefox
      var audioContext = new window.AudioContext();
  }

Here we create a global instance of AudioContext. It provides all the APIs require to interact with hardware.  There must be only one instance of AudioContext, which is why I have a created a global object for it.

if(audioContext.createJavaScriptNode){
         // Older API, Chrome
       var jsNode = audioContext.createJavaScriptNode(4096,1,1);
  } else {
        // Newer API, Firefox 
      var jsNode = audioContext.createScriptProcessor(4096,1,1);
  }


This creates a JavaScriptNode. JavaScriptNode can be used for sending an endless stream of audio samples to the hardware. AudioContext's createJavaScriptNode takes three parameters. First parameter is the size of the buffer which will be used to send data to the hardware. Think of it like the buffer you would normally use for reading files from file system. Value of this should be a power of two like 256, 512, 1024, 2048, 4096 etc. Second and third parameters are the number of input and output channels respectively. One thing to note here is that jsNode variable must also be global otherwise chrome's garbage collector will clean it up and jsNode will stop working once it is out of scope. This is probably a bug in chrome.


 
 jsNode.onaudioprocess = function(evt){
    var buffer = evt.outputBuffer.getChannelData(0);
    var n = buffer.length;
    for(var i = 0;i<n;i++){
         // write next sample to output
        buffer[i]=getNextSample();
    }
}



Next we define the callback that jsNode will call when it needs next buffersize number of samples. In this callback we iterate over the buffer array and fill it with new samples. The getNextSample() always returns the next sample in the sequence of samples that we want to send. All the magic now happens inside getNextSample() and we do not need to worry about buffersize, all that is taken care by this callback.

jsNode.connect(audioContext.destination);

And finally we connect our JavaScript node to the hardware. With this we are done with code that can send arbitrary audio samples to the hardware.

1. Noise Burst

// version 1.0
function getNextSample(){
      // return a random number between -1 and 1
    return 2*Math.random()-1;
} 


Noise source is nothing but a stream of samples with random values. Math.random() returns random number between 0 and 1. The above function returns a random number between -1 and 1. Now if you copy paste all of the above code in script tag of an html and load the page, you should hear some noise. In order to stop that noise you would have to close the tab since we are sending endless number of samples. For noise burst we should be able to send a fixed number of noise samples. Following version of getNextSample() does exactly that.


var noise_samples=0;
//version 2.0
function getNextSample(){
    var nextSample;
    if(noise_samples>0){
        nextSample= 2*Math.random() - 1;
        noise_samples--;
    } else {
        nextSample = 0;
    }
    return nextSample;
}

Now in some other function which can be called on click of a button we will set noise_samples to a finite value, so that after sometime it stops sending noise to audio device.


//version 1.0
function activate(){
   noise_samples = 10000;
}

With this we have implemented first component, a noise burst, of karplus strong algorithm. It can inject a finite number of samples of white noise. Try this in your browser to see if it works.

2. Delay Line

 Next we need to create a delay line. A delay line is used to re-introduce the samples back after a delay of time T. We can implement a delay line by storing the samples in an array. But how do we calculate number of samples the array should contain? In order to calculate number of samples we need to know the sampling rate of the audio card. Audio card plays a certain number of samples every second, called the Sample Rate. So to create a delay of time T we need T times he Sampling Rate of the Audio Card. sampleRate property in AudioContext tells us precisely that.

But wait, what is time T? The length of the delay line depends on the fundamental frequency of the string we are simulating, it is actually the length of the one complete cycle or time period of the wave with frequency same as the fundamental frequency. We know that time period of any wave is inverse of its frequency. So, let freq be the fundamental frequency of the wave so
      T = 1/freq
      Number of samples in delay line = T x SamplingRate
which means
       Number of samples in delay line = SamplingRate / freq
based on above equations we define following variables



var freq = 440; // 440Hz
var delayLineLen = Math.round(audioContext.sampleRate/freq); // number of sample has to be an integer, round out
var delayLine=[]; // array used creating delay line
var delayLinePos = 0; // marks the position at which the sample will be stored in delay line.


Now let us plug this delay line into our getNextSample() function.
var noise_samples=0;
//version 3.0
function getNextSample(){
    var nextSample;
    if(noise_samples>0){
        nextSample = 2*Math.random() - 1;
        noise_samples --;
    } else {
        nextSample = delayLine[delayLinePos];
    }
    delayLine[delayLinePos]=nextSample;
    delayLinePos = (delayLinePos + 1)%delayLineLen;
    return nextSample;
}

That's it. We have created a delay line and plugged that into out sample generator. Currently, delay line does nothing but stores the samples when noise samples are being sent and then plays them later when there are no noise samples. Since there is no damping or losses this creates an endless stream of same noise samples repeating at a time interval of 1/freq. You can try this out, you should  hear a clean note around 440Hz, and you may have to close the tab to shut it down.

3. Filter

 Now lets add our third component which is a filter or to be accurate, a low pass filter. A discrete low pass filter can be implemented using the formula. y[i] = y[i-1] + alpha*(x[i] - y[i-1]) where, alpha is the gain factor, usually ranges between 0 to 1,   y[i] is the output sample to be calculated y[i-1] is last calculated value x[i] is the current input value. Let us add this to our sample generator (getNextSample)

var noise_samples=0;
var alpha = 0.5;// you can try different values of alpha
//version 4.0
function getNextSample(){
    var nextSample;
    if(noise_samples>0){
        nextSample = 2*Math.random() - 1;
        noise_samples --;
    } else {
        var x_i = delayLine[delayLinePos];
        var y_i_1 = delayLine[(delayLinePos-1+delayLineLen)%delayLineLen]; // last sample in delayLine is yi minus 1 because it was created in last time.
        nextSample = y_i_1 + alpha*(x_i - y_i_1); // here nextSample is the y[i]
    }
    delayLine[delayLinePos]=nextSample; 
    delayLinePos = (delayLinePos + 1)%delayLineLen;
    return nextSample;
}

With this our implementation of Karplus-Strong algorithm is almost complete, there is one simple change we need to make to activate method.

// version 2.0
function activate(){
   noise_samples = delayLineLen; // fill entire delayLine and the stop.
}

If you now call activate method should hear the sound of a plucked string. You can play around with different frequencies and alpha values. Closer the alpha value to 1 longer the string would vibrate. Below is the complete source code listing.

/* *********************************************
 * 
 * Source Code Listing
 * Karplus-Strong String Synthesis
 * =============================================
 */
 // Global Variables
 var audioContext,
     jsNode,
     freq=440, // 440Hz
     delayLine=[], // array used creating delay line
     delayLineLen,
     noise_samples=0, // number of noise sample to play
     alpha = 0.5,
     delayLinePos = 0; // marks the position at which the sample will be stored in delay line.

 if(window.webkitAudioContext){
       // Google Chrome
     audioContext = new window.webkitAudioContext();
 } else {
       // Firefox
     audioContext = new window.AudioContext();
 }


 if(audioContext.createJavaScriptNode){
         // Older API, Chrome
     jsNode = audioContext.createJavaScriptNode(4096,1,1);
 } else {
        // Newer API, Firefox 
     jsNode = audioContext.createScriptProcessor(4096,1,1);
 }
 jsNode.onaudioprocess = function(evt){
     var buffer = evt.outputBuffer.getChannelData(0);
     var n = buffer.length;
     for(var i = 0;i<n;i++){
        // write next sample to output
         buffer[i]=getNextSample();
     }
 }

 jsNode.connect(audioContext.destination);

 delayLineLen = Math.round(audioContext.sampleRate/freq); // number of sample has to be an integer, round out

 function getNextSample(){
     var nextSample;
     if(noise_samples>0){
         nextSample = 2*Math.random() - 1;
         noise_samples--;
     } else {
         var x_i = delayLine[delayLinePos];
         
         // last sample in delayLine is yi minus 1 
         // because it was created in previous call to this function
         var y_i_1 = delayLine[(delayLinePos -1 + delayLineLen) % delayLineLen]; 
         nextSample = y_i_1 + alpha * (x_i - y_i_1); // here nextSample is the y[i]
     }
     delayLine[delayLinePos] = nextSample; 
     delayLinePos = (delayLinePos + 1) % delayLineLen;
     return nextSample;
 }
 // this function should be called on some
 // event, like onclick of a button
 function activate(){
     noise_samples = delayLineLen; // fill entire delayLine and the stop.
 }

/*************************************************************/