#include<stdio.h>
#include<math.h>
#include<ctype.h>

static int Oct = 4;
static int Len = 4;
static int Vol = 8;
static int Tem = 120;
static int Q   = 6;

static int Note[7] = { 0,2,-9,-7,-5,-4,-2 };

static int BefCol;

extern FILE* Fp;
extern int ErrLin;
extern int ErrCol;

void beep( int pitch, int length, int volume );

static int nextch( void )
{
  int c;

  c = fgetc( Fp );
  if( c == EOF )
    return EOF;

  if( c == '\n' ){
    BefCol = ErrCol;
    ErrCol = 0;
    ErrLin++;
  }else
    ErrCol++;

  return c;
}


void nextline( void )
{
  int c;

  while( ( c = fgetc( Fp ) ) != '\n' )
    if( c == EOF )
      return;

  ErrCol = 0;
  ErrLin++;
}


    
static backch( c )
{
  ungetc( c,Fp );
  if( c == '\n' ){
    ErrCol = BefCol;
    ErrLin --;
  }else
    ErrCol--;
}


static void skipspace( void )
{
  int c;

  while( c = nextch(),isspace(c) )
    ;
  backch( c );
}


static int read_num( void )
{
  int i,c,f;

  i = 0;
  f = -1;

  while( c = nextch(),isdigit(c) ){
    f = 0;
    i = i*10 + c - '0';
  }

  backch( c );

  if ( f ) 
    return -1;
  else
    return i;
}


static int length( void )
{
  int c,l;

  l = read_num();
  if( l == -1 )
    l = Len;
  else if ( l == 0 )
    return -1;

  l = 240000 / l / Tem;

  while( ( c = nextch() ) == '.' )
    l = l * 3 / 2;
  backch( c );

  return l;
    
}

static int note( int key )
{
  int c,l,p;

  key = Note[key];

  c = nextch();
  if( c == '+' )
    key++;
  else if( c == '-' )
    key--;
  else
    backch( c );
 
  l = length();
  if( l == -1 )
    return -1;

  key += ( Oct - 4 ) * 12;
  p = (int)(440.0 * pow( 2,(double)key / 12 ));

  beep( p,l*Q/8,Vol );

  return l;
}


int play( void )
{
  int c;

  while( skipspace(),( c = nextch() ) != EOF ){
    if( 'A' <= c && c <= 'Z' )
      c += 32;
    switch( c ){
    case 'r':
      return length();
      break;

    case '#':
      nextline();
      break;

    case 'v':
      c = read_num();
      if( 0 <= c && c < 16 )
	Vol = c;
      else
	return -1;
      break;

    case 'o':
      c = read_num();
      if( 0 < c )
	Oct = c;
      else
	return -1;
      break;

    case 'l':
      c = read_num();
      if( 0 < c )
	Len = c;
      else
	return -1;
      break;

    case 't':
      c = read_num();
      if( 0 < c )
	Tem = c;
      else
	return -1;
      break;

    case 'q':
      c = read_num();
      if( 0 < c && c <= 8 )
	Q = c;
      else
	return -1;
      break;

    case '>':
      Oct++;
      break;

    case '<':
      if( Oct == 1 )
	return -1;
      else
	Oct--;
      break;

    default:
      if( 'a' <= c && c <= 'g' )
	return note( c - 'a' );
      else
	return -1;
      break;
    }
  }
  return 0;
}
