//  Wave - a sound waveform generator 
//  reduced for muLinux by M. Andreoli
//  added support for console beep (-c switch)
//
//  argv[1]=freq, argv[2]=duration (1/10s)
//  based on Wave: 
	// Copyright (C) 1996 Jeff Tranter (jeff_tranter@pobox.com)

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
/*#include <math.h> */
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/soundcard.h>
#include <sys/kd.h>
#include "math.h"

/* global variables */
int rate          = 8000;	// sampling rate in samples/second
int frequency;
double duration   = 0;		// playing duration in seconds, 0=infinite
int channels      = 1;		// 1 = mono 2 = stereo
int bits          = 8;		// sample size in bits
char *device      = "/dev/audio"; // output device or file
int fd;				// file descriptor for device
unsigned char *buffer = 0;	// buffer for one cycle of sound data

int use_console=0;	// if=1 use /dev/console beeper

// generate and play 
static void Play()
{
  int numPoints = rate/frequency;
  int numCycles = int(frequency*duration)/10;
  int  i,j;
  buffer = new unsigned char[numPoints*channels*(bits/8)];

 /* generate one cycle */

      for (i = 0 ; i < numPoints ; i++) {
        j = int(128 *sin(2.0*PI*i/numPoints) + 128);
        if(j<0) j=0; if(j>255) j=255;
        buffer[i] = j;
      }


/* write data */
  for (i = 0 ; (i < numCycles) || duration == 0 ; i++)
    write(fd, buffer, numPoints);

}


// main program
int main(int argc, char *argv[])
{
  int arg,status;
  char *opt=argv[1];
  int i=1;
  int tone;

/* parse args */

if ( 
( 
(argc<2)
|| ( opt[0]=='-' ) && (opt[1]=='h' ))
)
{
	fprintf(stderr,"Usage: wave [-h] [-c] frequency duration (1/10s)\n");
	fprintf(stderr,"\t [-c] use console beeper\n");
	exit(0);
}

if ( ( opt[0]=='-' ) && (opt[1]=='c' ))
{
	use_console=1;
	i++;
}

  frequency=atol(argv[i]);
  duration=atof(argv[++i]);

fprintf(stderr,"f=%d, d=%f\n",frequency,duration);

/* open device */

if (use_console)
{
	 fd = open("/dev/console", O_WRONLY);
	 if (fd < 0) fd = 1; /* stdout */

	if (frequency!=0.0) tone=1190000/frequency;
  		else tone=0;
  ioctl(fd,KIOCSOUND,tone);
  usleep((long)duration*100000);   // duration is in 1/10s=100ms=100.000micro
  ioctl(fd,KIOCSOUND,0);

}
else
{

  fd = open(device, O_WRONLY|O_CREAT|O_TRUNC, 0777);

  if (fd == -1)
     fprintf(stderr, "%s:unable to open\n", device);
/* init device */
  status = ioctl(fd, SOUND_PCM_WRITE_BITS, &bits);
  if (status == -1)
        fprintf(stderr,"SOUND_PCM_WRITE_BITS ioctl failed\n");
  ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &channels);
  ioctl(fd, SOUND_PCM_WRITE_RATE, &rate);
  arg = AFMT_U8;
  ioctl(fd, SOUND_PCM_SETFMT, &arg);

/* generate and play */
  Play();
}


/* close device */
 if(fd>2) close(fd);
  return 0;
}
