/*
 * If the audio library or audio include files are missing, you need
 * to get /usr/demo/SOUND off the Sun OS tapes or CD.
 *
 * This routine will turn your audio device up to full volume, but
 * will not attempt to reset the current speaker / jack choice.
 */

/* beepSun.c -- seligman 6/92 */

/*
-- Implementation of beep.h for Sun.
-- Rick to Joe to Scott to Joe.
*/

/* Date: Fri, 2 Aug 91 08:26:08 PDT */
/* From: rick@st.unocal.com (Richard Ottolini) */

#include "beep.h"
#include <sun/audioio.h>
#include </usr/demo/SOUND/multimedia/libaudio.h>
#include </usr/demo/SOUND/multimedia/ulaw2linear.h>
#include <stropts.h>
#include <math.h>
#include <fcntl.h>


#define RATE	8000

static int      audio;
static audio_info_t audio_stat;

int
BeepInit ()
{
    audio = open ("/dev/audio", O_WRONLY);

    if (audio < 0)
	/* Uh oh! */
	return 1;
    else
    {
	/*
	 * Turn the speaker (or headphone, whichever the user has it set to)
	 * up to full volume.
	 */
	ioctl (audio, AUDIO_GETINFO, &audio_stat);
	audio_stat.play.gain = AUDIO_MAX_GAIN;
	ioctl (audio, AUDIO_SETINFO, &audio_stat);
	return 0;
    }
}


/*
 * This routine is very, very lazy. It just calculates everything from
 * scratch every time it is called, even when the volume is zero.
 * But it seems to be plenty fast enough, even on an IPC, and I've
 * got work to do! If anyone out there feels sorry for the SPARC CPU
 * and wants to make it more efficient, be my guest. -- Joe
 */
int
Beep (time, volume, pitch)
    int             time, volume, pitch;
{
unsigned char   buf[RATE];
int             i, n, cycle;
double          dt;

    n = (time / 1000.) * RATE;
    n = n < RATE ? n : RATE;	/* clip to buffer size */
    pitch = pitch < RATE / 2 ? pitch : RATE / 2;	/* clip to Nyquist */
    cycle = (RATE / pitch) / 2;	/* samples per half cycle */
    n = (n / cycle) * cycle;	/* round length to integral half cycle */
    dt = pitch * 2 * M_PI / RATE;	/* sine scale factor */
    for (i = 0; i < n; i++)
	buf[i] = audio_l2u (audio_d2l (volume * sin (i * dt) / 100.));
    write (audio, buf, n);
    return 0;
}


int
BeepWait ()
{
    ioctl (audio, AUDIO_DRAIN);
    return 0;
}


int
BeepCleanup ()
{
    return 0;
}


int
BeepResume ()
{
    return 0;
}
