/* $Revision Header * Header built automatically - do not edit! *************
 *
 *	(C) Copyright 1991 by Olaf 'Olsen' Barthel & MXM
 *
 *	Name .....: Beep.c
 *	Created ..: Monday 21-Jan-91 20:12
 *	Revision .: 0
 *
 *	Date            Author          Comment
 *	=========       ========        ====================
 *	21-Jan-91       Olsen           Created this file!
 *
 * $Revision Header ********************************************************/

#include "TermGlobal.h"

	/* IFF Sound `8SVX' voice header. */

struct Voice8Header
{
	ULONG	oneShotHiSamples,	/* # samples in the high octave 1-shot part */
		repeatHiSamples,	/* # samples in the high octave repeat part */
		samplesPerHiCycle;	/* # samples/cycle in high octave, else 0 */
	UWORD	samplesPerSec;		/* data sampling rate */
	UBYTE	ctOctave,		/* # of octaves of waveforms */
		sCompression;		/* data compression technique used */
	LONG	volume;			/* playback nominal volume from 0 to Unity
					 * (full volume). Map this value into
					 * the output hardware's dynamic range.
					 */
};

	/* Small sound information. */

struct SoundInfo
{
	APTR	Data;		/* Data pointer. */

	LONG	Length;		/* Real length. */
	ULONG	Rate;		/* Recording rate. */
	WORD	Volume;		/* Sound volume. */
};

	/* Local sound info. */

STATIC struct SoundInfo	SoundInfo;
STATIC BYTE		HasSound = FALSE,SoundPlayed = FALSE;

	/* CreateBeep():
	 *
	 *	Set up the audio.device for a decent beep sound.
	 */

BYTE
CreateBeep()
{
	if(!AudioBlock)
	{
		struct MsgPort *AudioPort;

		SoundPlayed = FALSE;

		if(AudioPort = (struct MsgPort *)CreateMsgPort())
		{
			if(AudioBlock = (struct IOAudio *)CreateIORequest(AudioPort,sizeof(struct IOAudio)))
			{
				if(!OpenDevice(AUDIONAME,0,AudioBlock,0))
				{
					AudioBlock -> ioa_Request . io_Command				= ADCMD_ALLOCATE;
					AudioBlock -> ioa_Request . io_Message . mn_Node . ln_Pri	= 10;
					AudioBlock -> ioa_Data						= &AnyChannel[0];
					AudioBlock -> ioa_Length					= 4;

					if(!DoIO(AudioBlock))
					{
						if(HasSound)
						{
							AudioBlock -> ioa_Request . io_Command	= CMD_WRITE;
							AudioBlock -> ioa_Request . io_Flags	= ADIOF_PERVOL;
							AudioBlock -> ioa_Period		= SoundInfo . Rate;
							AudioBlock -> ioa_Volume		= SoundInfo . Volume;
							AudioBlock -> ioa_Cycles		= 1;
							AudioBlock -> ioa_Data			= SoundInfo . Data;
							AudioBlock -> ioa_Length		= SoundInfo . Length;
						}
						else
						{
							AudioBlock -> ioa_Request . io_Command	= CMD_WRITE;
							AudioBlock -> ioa_Request . io_Flags	= ADIOF_PERVOL;
							AudioBlock -> ioa_Period		= 223;
							AudioBlock -> ioa_Volume		= 64 / 2;
							AudioBlock -> ioa_Cycles		= 150;
							AudioBlock -> ioa_Data			= &SineWave[0];
							AudioBlock -> ioa_Length		= 8;
						}

						return(TRUE);
					}

					CloseDevice(AudioBlock);
				}

				DeleteIORequest(AudioBlock);
			}

			DeleteMsgPort(AudioPort);
		}

		AudioBlock = NULL;

		return(FALSE);
	}
	else
		return(TRUE);
}

	/* DeleteBeep():
	 *
	 *	Remove the data allocated for the beep sound.
	 */

VOID
DeleteBeep()
{
	if(AudioBlock)
	{
		if(AudioBlock -> ioa_Request . io_Device)
		{
/*			if(!CheckIO(AudioBlock))
			{
				AbortIO(AudioBlock);

				WaitIO(AudioBlock);
			}*/

			CloseDevice(AudioBlock);
		}

		if(AudioBlock -> ioa_Request . io_Message . mn_ReplyPort)
			DeleteMsgPort(AudioBlock -> ioa_Request . io_Message . mn_ReplyPort);

		DeleteIORequest(AudioBlock);

		AudioBlock = NULL;
	}

	if(HasSound)
	{
		FreeVec(SoundInfo . Data);

		HasSound = FALSE;
	}
}

	/* Beep():
	 *
	 *	Produce a decent beep sound.
	 */

VOID
Beep()
{
	if(AudioBlock)
	{
			/* AudioRequest has returned. */

		if(SetSignal(0,0) & SIG_AUDIO)
		{
			SetSignal(0,SIG_AUDIO);

			WaitIO(AudioBlock);
		}

		if(CheckIO(AudioBlock) || !SoundPlayed)
		{
			BeginIO(AudioBlock);

			SoundPlayed = TRUE;
		}
	}
}

	/* OpenSound(UBYTE *Name):
	 *
	 *	Load an IFF-8SVX sound file instead of the standard
	 *	beep (yes, this is a zany feature nobody will ever need!).
	 */

BYTE
OpenSound(UBYTE *Name)
{
	STATIC ULONG SoundProps[] = { '8SVX', 'VHDR' };

	struct IFFHandle	*Handle;
	struct StoredProperty	*Prop;
	struct Voice8Header	*VoiceHeader;

	BYTE			 Success = FALSE;

		/* Allocate an IFF handle. */

	if(Handle = AllocIFF())
	{
			/* Open the file. */

		if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
		{
				/* Say it's a DOS file. */

			InitIFFasDOS(Handle);

				/* Open the file for reading. */

			if(!OpenIFF(Handle,IFFF_READ))
			{
					/* Remember VHDR-chunks encountered. */

				if(!PropChunks(Handle,&SoundProps[0],1))
				{
						/* Stop at the body chunk. */

					if(!StopChunk(Handle,'8SVX','BODY'))
					{
							/* Start scanning... */

						if(!ParseIFF(Handle,IFFPARSE_SCAN))
						{
								/* Obtain the stored VHDR-chunk. */

							if(Prop = FindProp(Handle,'8SVX','VHDR'))
							{
								VoiceHeader = (struct Voice8Header *)Prop -> sp_Data;

									/* Compressed data not supported so far. */

								if(!VoiceHeader -> sCompression)
								{
									struct ContextNode *ContextNode;

										/* Inquire current chunk. */

									if(ContextNode = CurrentChunk(Handle))
									{
											/* We don't support double-buffering, this
											 * is only a *simple* example.
											 */

										if(ContextNode -> cn_Size < 102400)
										{
												/* Allocate the data storage. */

											if(SoundInfo . Data = AllocVec(ContextNode -> cn_Size,MEMF_CHIP))
											{
													/* Play either the one-shot or the continuous
													 * part, not both.
													 */

												SoundInfo . Length	= VoiceHeader -> oneShotHiSamples ? VoiceHeader -> oneShotHiSamples : VoiceHeader -> repeatHiSamples;

													/* Calculate recording rate. */

												SoundInfo . Rate	= (GfxBase -> DisplayFlags & PAL ? 3546895 : 3579545) / VoiceHeader -> samplesPerSec;

													/* Calculate volume. */

												SoundInfo . Volume	= (VoiceHeader -> volume * 64) / 0x10000;

													/* Read the data. */

												if(ReadChunkBytes(Handle,SoundInfo . Data,ContextNode -> cn_Size))
													Success = TRUE;
												else
													FreeVec(SoundInfo . Data);
											}
										}
									}
								}
							}
						}
					}
				}

					/* Make iffparse clean up after us. */

				CloseIFF(Handle);
			}

				/* Close the DOS handle. */

			Close(Handle -> iff_Stream);
		}

			/* Free the IFF handle. */

		FreeIFF(Handle);
	}

		/* Remember success/failure. */

	HasSound = Success;

	return(Success);
}
