/*
  Aaron Linville
  aaron@linville.org

  Should compile cleanly on Solaris 2.7 and 2.8 with:
  gcc sun_audio_tester.c -lm -o sun_audio_tester
*/

#include <fcntl.h>
#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/audioio.h>

void sigproc(void);

int audioDevice;
int audioCtlDevice;

int main(int, char*[]) {
  float pi, freq, sampFreq;
  float j;
  int i, bits, amplitude;
  short temp[2000]; /* Short is 16 bits */
  
  audio_info_t info;
  audio_info_t info2;
  
  /* Install signal handler */
  
  signal(SIGINT, (void *) sigproc);
  
  /* /dev/audioctl stuff */
  
  if((audioCtlDevice = open("/dev/audioctl", O_RDWR)) < 0) {
    printf("Failed to open device /dev/audioctl.\n");
    return 0;
  }
  
  if(ioctl(audioCtlDevice, AUDIO_GETINFO, &info) < 0) {
    printf("Can't get info on device /dev/audioctl.\n");
    close(audioCtlDevice);
    return 0;
  }
  
  info.play.port = AUDIO_SPEAKER + AUDIO_HEADPHONE + AUDIO_LINE_OUT;
  
  if(ioctl(audioCtlDevice, AUDIO_SETINFO, &info) < 0) {
    printf("Can't set info on device /dev/audioctl.\n");
    close(audioCtlDevice);
    return 0;
  }
  
  close(audioCtlDevice);
  
  /* /dev/audio stuff */

  if((audioDevice = open("/dev/audio", O_RDWR)) < 0) {
    printf("Failed to open device /dev/audio.\n");
    return 0; 
  }

  if(ioctl(audioDevice, AUDIO_GETINFO, &info2) < 0) {
    printf("Can't get info on device /dev/audio.\n");
    close(audioDevice);
    return 0;
  }

  AUDIO_INITINFO(&info2);
  
  info2.play.sample_rate = 11050; /* In Hz */
  info2.play.channels = 2;
  info2.play.precision = 16; /* Bits per sample */
  info2.play.encoding = AUDIO_ENCODING_LINEAR;
  info2.play.gain = 100;
  
  if(ioctl(audioDevice, AUDIO_SETINFO, &info2) < 0) {
    printf("Can't set info on device /dev/audio.\n");
    close(audioDevice);
    return 0;
  }
  
  amplitude = 16000; /* Loudness */
  pi = 3.1415926454;
  sampFreq = 11050; /* In Hz */

  freq = 1500; /* In Hz */
  
  j = 1;
  
  while(1) {
    if(freq > 2700)
      j = -1;
    else if(freq < 1500)
      j = 1;
      
    freq += 50 * j;
    
    for(i = 0; i < 2000; i+=2) {
      /*
        Stereo samples are interleaved.
        Even samples - Left Channel (0, 2, 4...)
        Odd samples - Right Channel (1, 3, 5...)
      */
    
      temp[i] = amplitude * sin(2 * pi * freq * i / sampFreq);
      temp[i + 1] = amplitude * sin(2 * pi * freq * i / sampFreq);
    }
    
    bits = write(audioDevice, temp, 2000);
    /* printf("Bits written %i.\n", bits); */
  } 

  return 0;
}

void sigproc(void) {
  printf("Caught SIGINT! Exiting.\n");

  close(audioDevice);

  exit(0);
}
