One-line algorithmic music

Here is my code (with serial, not a keyboard as in the video):

// Parser for algorithmic music (serial version)
// This version:
// * no limit on number of digits for constants
// * No error checking
// * No precedence (of operators) checking
// * Each individual operation MUST BE between parentheses
// * Algos must end with the character 'E'

// by 23N! 2012.09.15

const byte MAX_CHAR=50; // max number of characters in formula
char pile[MAX_CHAR],sortie[MAX_CHAR]; // stacks for conversion to RPN (shunting-yard algorithm)
unsigned long pileRPN[MAX_CHAR],t; // stack for RPN computation / time variable
byte p,s; // counters for pile and sortie
boolean firstChar,multipleDigit; // for reinitialization when new algo is received / multiple digit detection

void setup() {  
  // This works on an arduino MEGA.
  // Just modify the registers and pins for other boards.
  // A prescaler of 8 with a 8 or 9 bits fast PWM might me more appropriate but lower sampling rate.
  // In the current situation, long algos might cause problems/crashes.
  // If sound seems too slow, just increase the increment of t.
  // PWM out pin
  DDRB = (1 << PB5); // Pin 11 on MEGA
  // fast-PWM 10-bit / compare match on OCR1A / output on OC1A=PB5 / prescaler=1
  TCCR1A = (1 << COM1A1)|(1<<WGM10)|(1<<WGM11);
  TCCR1B = (1 << CS10)|(1<<WGM12);
  // Initial values
  t=0;
  p=0;
  s=0;
  firstChar=true;
  multipleDigit=false;
  // Serial  
  Serial.begin(57600);
  Serial.println("Ready!");
} 

ISR(TIMER1_OVF_vect) // Interrupt Service Routine (sampling rate of sound)
{
  // computation of the algo based on its RPN representation
  p=0;
  for (byte i=0;i<s;i++) { // Loop on the RPN algo as an array of char (=sortie)
    switch(sortie[i]) { 
    case 't': // variable=> just add to pile
      pileRPN[p++]=t;
      multipleDigit=false; // not a digit
      break; 
    case '+': // perform ADDITION, de-pile
      p--; //de-pile
      pileRPN[p-1]+=pileRPN[p]; // perform operation
      multipleDigit=false; // not a digit
      break;
    case '|':  // perform OR, de-pile
      p--;
      pileRPN[p-1]|=pileRPN[p];
      multipleDigit=false;
      break;
    case '&': // perform AND, de-pile
      p--;
      pileRPN[p-1]&=pileRPN[p];
      multipleDigit=false;
      break;
    case '^':  // perform XOR, de-pile
      p--;
      pileRPN[p-1]^=pileRPN[p];
      multipleDigit=false;
      break;
    case '-':  // perform SUBSTRACTION, de-pile
      p--;
      pileRPN[p-1]-=pileRPN[p];
      multipleDigit=false;
      break;
    case '*':  // perform MULTIPLICATION, de-pile
      p--;
      pileRPN[p-1]*=pileRPN[p];
      multipleDigit=false;
      break;
    case '/':  // perform DIVISION, de-pile
      p--;
      pileRPN[p-1]/=pileRPN[p];
      multipleDigit=false;
      break;
    case '>':  // perform BIT SHIFT RIGHT, de-pile
      p--;
      pileRPN[p-1]=pileRPN[p-1]>>pileRPN[p];
      multipleDigit=false;
      break;
    case '<':  // perform BIT SHIFT LEFT, de-pile
      p--;
      pileRPN[p-1]=pileRPN[p-1]<<pileRPN[p];
      multipleDigit=false;
      break;
    case '%':  // perform MODULO, de-pile
      p--;
      pileRPN[p-1]=pileRPN[p-1]%pileRPN[p];
      multipleDigit=false;
      break;
    default: // digit, add to pile except if multiple digits (in this case process the digits)
      if (multipleDigit) {
        pileRPN[p-1]*=10;
        pileRPN[p-1]+=sortie[i]-48;
      } 
      else {
        pileRPN[p++]=sortie[i]-48;
        multipleDigit=true;
      }
      break;
    }
  }
  OCR1A=pileRPN[0]; // PWM output (the final result is the first element of the stack)
  t++; // variable inc.
}

void loop() {
  // read the serial input and parse it (don't forget to type "E" at the end of the algo)
  // example (copy-paste in serial monitor): ((t>5)*t)E (">" is actually ">>" not "greater than")
  // each individual operation MUST BE between parentheses.
  while (Serial.available() > 0) {
    if(firstChar) { // Disable interrupt and initialize variables
      TIMSK1 = (0 << TOIE1); 
      firstChar=false;
      p=0;
      s=0;
    }
    char inChar = Serial.read(); // current char
    char symbol=inChar; // meta-char
    if ((inChar>=48)&(inChar<58)) symbol='D'; // Digit
    if ((inChar!='(')&(inChar!=')')&(inChar!='t')&(inChar!='E')&(symbol!='D'))  symbol='O'; // Operator
    // Shunting-yard algorithm
    switch(symbol) { 
    case 't':
    case 'D':
      sortie[s++]=inChar; // if variable or digit, add to sortie
      break; 
    case 'O':
    case '(':
      pile[p++]=inChar; // if operator or left parenthesis, add to pile
      break;
    case ')':
      sortie[s++]=pile[p-1]; // if right parenthesis, transfer from pile to sortie, remove left parenthesis
      // In our case there is always a single operation between parentheses. No need to check if there is
      // a left parenthesis in the pile, we can just move the index p back and overwrite the left parenthesis.
      p-=2;
      break;
    case 'E': // End char => send the new algo to the interrupt for sound generation.
      // Not necessary to have an end char, end can be detected by matching parentheses.
      // But an End char makes things clearer and easier.
      Serial.println("Uploaded!");
      firstChar=true;
      t=0;
      p=0;
      TIMSK1 = (1 << TOIE1); // enable interrupt
      break;
    }
  }
}

If the algorithm is entered in RPN then it's even easier as there is almost nothing in the loop.
In the case of a keyboard and an LCD screen, then it's getting difficult to type anything if the algo is a bit long (the program rarely enters the loop and then misread the keyboard most of the time). What I do in this case is using an arduino for the interface/parsing (just a loop, no interrupt) and an attiny for sound (computation of the algo). Those two are connected through serial.