home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
comm
/
term23_2.lha
/
Source_Code
/
termSource
/
termBeep.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-18
|
8KB
|
370 lines
/*
** $Id: termBeep.c,v 1.3 92/08/15 20:13:35 olsen Sta Locker: olsen $
** $Revision: 1.3 $
** $Date: 92/08/15 20:13:35 $
**
** Sound support routines
**
** Copyright © 1990-1992 by Olaf `Olsen' Barthel & MXM
** All Rights Reserved
*/
#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()
{
/* Do we already have the resources we need? */
if(!AudioBlock)
{
struct MsgPort *AudioPort;
/* No sound so far. */
SoundPlayed = FALSE;
/* Create the IO reply port. */
if(AudioPort = (struct MsgPort *)CreateMsgPort())
{
/* Create the audio IO info. */
if(AudioBlock = (struct IOAudio *)CreateIORequest(AudioPort,sizeof(struct IOAudio)))
{
/* Open audio.device */
if(!OpenDevice(AUDIONAME,0,AudioBlock,0))
return(TRUE);
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)
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;
}
}
/* ClearAudio():
*
* Clear the audio control block for reuse.
*/
VOID
ClearAudio()
{
/* Remove the request. */
WaitIO(AudioBlock);
/* Clear the signal bit. */
SetSignal(0,SIG_AUDIO);
/* Free the channels we had allocated. */
AudioBlock -> ioa_Request . io_Command = ADCMD_FREE;
DoIO(AudioBlock);
/* No sound running. */
SoundPlayed = FALSE;
}
/* Beep():
*
* Produce a decent beep sound.
*/
VOID
Beep()
{
if(AudioBlock)
{
BYTE PlayItAgainSam; /* Note: `Sam' is Sam Dicker, the author of
* the original audio.device implementation.
*/
/* AudioRequest has returned. */
if(CheckSignal(SIG_AUDIO))
ClearAudio();
/* Check whether we are to play the sound or not. */
if(!SoundPlayed)
PlayItAgainSam = TRUE;
else
{
if(CheckIO(AudioBlock))
PlayItAgainSam = TRUE;
else
PlayItAgainSam = FALSE;
}
/* May we play the sound? */
if(PlayItAgainSam)
{
/* Allocate a sound channel, we don't want to
* wait for it, the `beep' sound is to played
* right now.
*/
AudioBlock -> ioa_Request . io_Command = ADCMD_ALLOCATE;
AudioBlock -> ioa_Request . io_Flags = ADIOF_NOWAIT | IOF_QUICK;
AudioBlock -> ioa_Request . io_Message . mn_Node . ln_Pri = 80;
AudioBlock -> ioa_Data = AnyChannel;
AudioBlock -> ioa_Length = 4;
/* Try the allocation. */
BeginIO(AudioBlock);
/* If still in progress, no channel is available yet. */
if(!CheckIO(AudioBlock))
{
/* Abort the allocation. */
AbortIO(AudioBlock);
/* Wait for request to be returned. */
WaitIO(AudioBlock);
}
else
{
/* Wait for request to be returned. */
if(!WaitIO(AudioBlock))
{
/* Set up the sound IO data. */
if(HasSound)
{
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_Period = 223;
AudioBlock -> ioa_Volume = 64 / 2;
AudioBlock -> ioa_Cycles = 150;
AudioBlock -> ioa_Data = &SineWave[0];
AudioBlock -> ioa_Length = 8;
}
AudioBlock -> ioa_Request . io_Command = CMD_WRITE;
AudioBlock -> ioa_Request . io_Flags = ADIOF_PERVOL;
/* Start the sound. */
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|MEMF_CLEAR))
{
/* 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);
}