/* Aix/audio.c 
	vi:ts=3 sw=3:
 */
/* Ported from Linux/audio.c by Sam Hartman <hartmans@mit.edu>*/
/* minor mods for pl14 by Mike Battersby */
/* Modified from soundblaster_audio.c by Hannu Savolainen */
/* hsavolai@cs.helsinki.fi */

#include "defs.h"
#include <unistd.h>
#include <fcntl.h>
#include "extern.h"

#undef SIGNED /*redefined in system include file*/
#include <sys/audio.h>
#include <sys/acpa.h>


ID("$Id: audio.c,v 1.2 1995/02/01 16:43:47 espie Exp $")

LOCAL unsigned char *buffer;	/* buffer for ready-to-play samples */
LOCAL unsigned short *buffer16;			/* Sure this isn't unsigned short ? */
LOCAL int buf_index;   			/* index conflicts with index(3) */
LOCAL int buf_max;
LOCAL int audio;           	/* /dev/acpa0/1 */

LOCAL int stereo;					/* are we playing stereo or not ? */
/* 256th of primary/secondary source for that side. */
LOCAL int primary=512, secondary=0;
LOCAL int dsp_samplesize = 16; /* must be 8 or 16 */

void set_mix(percent)
int percent;
    {
    percent *= 256;
    percent /= 100;
    primary = percent;
    secondary = 512 - percent;
    }

int open_audio(f, s)
int f;
int s;
  	{
  	audio_init init;
	audio_control control;
	audio_change change;
	audio = open("/dev/acpa0/1", O_WRONLY, 0);
   if (audio == -1)
		end_all("Error opening audio device");

	if (f==0) f = 44100;

   init.srate = f;
   init.bits_per_sample = 16;
   init.mode = PCM;
	init.channels = s?2:1;
   init.flags = BIG_ENDIAN;
	init.operation = PLAY;
   if (ioctl(audio, AUDIO_INIT, &init)!= 0)
		end_all("Error initializing ACPA");

	stereo = (init.channels == 2)?1:0;
	buf_max = init.bsize*20;	/* This is set by the ioctl. */

   buffer = malloc(buf_max);
   buffer16 = (short *)buffer;
   buf_index = 0;

   control.ioctl_request = AUDIO_CHANGE;
	control.request_info = &change;
	control.position = 0;

	change.dev_info = 0;
	change.input = AUDIO_IGNORE;
	change.output = OUTPUT_1;
	change.monitor = AUDIO_IGNORE;
	change.volume = 0x7fff0000;
	change.volume_delay = 0;
	change.balance = 0x3fff0000;
	change.balance_delay = 0;
	change.treble = AUDIO_IGNORE;
	change.bass = AUDIO_IGNORE;
	change.pitch = AUDIO_IGNORE;
	
	if (ioctl(audio, AUDIO_CONTROL, &control) != 0)
		end_all( "Error changing ACPA parameters");

	control.ioctl_request = AUDIO_START;

  	if (ioctl(audio, AUDIO_CONTROL, &control) != 0)
		end_all("Error starting ACPA");

  	return init.srate;

   }

LOCAL void actually_flush_buffer()
   {
   int l,i;

   l = sizeof(*buffer) * buf_index;
   if (dsp_samplesize !=8) l *= 2;
   write(audio, buffer, l);

   buf_index = 0;
   }

void output_samples(left, right)
unsigned int left, right;
   {
   if (dsp_samplesize != 8)	/* Cool! 16 bits/sample */
		{
	   if (stereo)
	   	{
	      if (buf_index * 2 >= buf_max - 1) 
	      	actually_flush_buffer();

	      buffer16[buf_index++] = 
				32768+((left*primary + right*secondary) / 65536);
	      buffer16[buf_index++] = 
				32768+((right*primary + left*secondary) / 65536);
		  	}
	 	else
	   	{
	      if (buf_index * 2 >= buf_max) 
	      	actually_flush_buffer();
		  	buffer16[buf_index++] = 32768+(left + right)/256;
	      }
		}
	else
   	{
	   if (stereo)
	   	{
	      if (buf_index >= buf_max - 1) 
				actually_flush_buffer();
	      buffer[buf_index++] = ((left*primary + right*secondary) >> 24)
	      	+ 128;
	      buffer[buf_index++] = ((right*primary + left*secondary) >> 24)
	         + 128;
	      }
	   else
	   	{
	      if (buf_index >= buf_max) 
				actually_flush_buffer();
	      buffer[buf_index++] = ((left + right) >> 16) + 128;
	      }
	   }
	}

void flush_buffer()
   {	/* Dummy version */
   }

/* We must wait for all samples to be played before closing.*/
void close_audio()
   {
   audio_control control;
   if (buf_index != 0)
		actually_flush_buffer();
   ioctl(audio, AUDIO_WAIT, 0);
   control.position = 0;
	control.ioctl_request = AUDIO_STOP;
	control.request_info = 0;
	ioctl(audio, AUDIO_CONTROL, &control);

   close(audio);
   free(buffer);
   }

/* dummy system calls, to patch ? */
void set_synchro(s)
	{
	}

int update_frequency()
	{
	return 0;
	}

void discard_buffer()
	{
   audio_control control;
   control.ioctl_request = AUDIO_STOP;
	control.request_info = 0;
	control.position = 0;
	ioctl(audio, AUDIO_CONTROL, &control);
   usleep(150000);
   control.ioctl_request = AUDIO_START;
   if (ioctl(audio, AUDIO_CONTROL, &control) == -1)
		end_all ("Unable to restart AACPA");
	buf_index = 0;
	}


