home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
001-099
/
ff014.lzh
/
beep
/
beep.c
next >
Wrap
C/C++ Source or Header
|
1986-03-02
|
6KB
|
245 lines
/*****************************************************************************
*
* VT100-like Beep Sound Example 22 February 1986
*
* Copyright (c) 1986 Sam Dicker, Commodore/Amiga Inc.
* This is public domain software. Permission is granted to copy and use
* this software as long as this notice is included.
*
* This module makes a beep sound like the CTRL-G on a VT100 terminal.
*
* Calling VTBeep() starts the sound which stops when it times out.
* Calling it again, while it is playing, only restarts the timer.
* Call KillVTBeep() to kill any beeps in progress before exiting your
* main program.
*
* VTBeep() and KillVTBeep() are re-entrant but cannot be used in interrupt
* code.
*
* The audio in this example is very crude. It is more of an example of
* using the timer device and multi-tasking. I sincerely hope, if it appears
* in any products, that it is only used as an authentic 'cheap terminal'
* sound. A little more code can produce much better (less obnoxious) sound.
*
* VT100 is a trademark of Digital Equipment Corporation.
*
*****************************************************************************/
#include "exec/types.h"
#include "exec/errors.h"
#include "exec/memory.h"
#include "devices/timer.h"
#include "devices/audio.h"
#include "libraries/dos.h"
#define BEEPNAME "VTBeep"
#define BEEPSIZE 10
#define BEEPFREQ 1000
#define COLORCLOCK 3579545
#define SIGB_BEEP 31
#define SIGF_BEEP (1 << 31)
#define SIGF_PORT (1 << replyPort->mp_SigBit)
/* channel allocation map (try left channel; if unavailable try right) */
UBYTE allocationMap[] = { 1, 8, 2, 4 };
/* make beep sound */
VTBeep()
{
struct Task *beepTCB;
VOID beepTask();
/* prevent beep child task, if it already exists, from going away before
* it is signaled */
Forbid();
/* find the task by name */
beepTCB = (struct Task *)FindTask(BEEPNAME);
/* check if the task exists */
if (beepTCB == NULL)
/* it doesn't exist, so create it */
beepTCB = (struct Task *)CreateTask(BEEPNAME, 25, beepTask, 500);
else
/* it already exist so signal it so restart it's timer */
Signal(beepTCB, SIGF_BEEP);
Permit();
/* return success */
return(beepTCB != NULL);
}
/* kill any beep sounds in progress. This is necessary before exiting the
* main program; otherwise, if a beep is playing, when the beep times out
* and the child task wakes up its code segment may be gone */
KillVTBeep()
{
struct Task *beepTCB;
do {
/* prevent beep child task, if it already exists, from going away
* before it is signaled */
Forbid();
/* find the task by name */
beepTCB = (struct Task *)FindTask(BEEPNAME);
/* check if the task exists */
if (beepTCB != NULL) {
/* it already exist so signal it so go away */
Signal(beepTCB, SIGBREAKF_CTRL_C);
/* give it a chance to wake up, if it is lower priority */
Delay(10);
}
Permit();
/* if it existed, kill it again */
} while (beepTCB != NULL);
}
/* beep sound child task */
VOID beepTask()
{
struct MsgPort *replyPort;
struct timerequest *timerIOB;
struct IOAudio *audioIOB;
UBYTE *beepWave;
ULONG signals;
/* allocate signal used to re-start beep */
if (AllocSignal(SIGB_BEEP) == SIGB_BEEP) {
/* create reply port for timer and sound I/O block */
replyPort = (struct MsgPort *)CreatePort(NULL);
if (replyPort != NULL) {
/* create timer I/O block */
timerIOB = (struct timerequest *)
CreateExtIO(replyPort, sizeof(struct timerequest));
if (timerIOB != NULL) {
/* open timer device */
if (OpenDevice(TIMERNAME, UNIT_VBLANK, timerIOB, 0) == 0) {
timerIOB->tr_node.io_Command = TR_ADDREQUEST;
/* create beep waveform */
beepWave = (UBYTE *)AllocMem(BEEPSIZE,
MEMF_CHIP | MEMF_CLEAR);
if (beepWave != 0) {
beepWave[0] = 100;
/* create audio I/O block */
audioIOB = (struct IOAudio *)
CreateExtIO(replyPort, sizeof(struct IOAudio));
if (audioIOB != NULL) {
/* setup audio I/O block to allocate a channel
* when the audio device is opened (see Volume 1 of
* the Amiga ROM Kernel Manual - Audio Device
* chapter and Volume 2 of the Amiga ROM Kernel
* Manual - Device Summaries appendix for details)
*/
audioIOB->ioa_Request.io_Message.mn_Node.ln_Pri =
85;
audioIOB->ioa_Data = allocationMap;
audioIOB->ioa_Length = sizeof(allocationMap);
/* open the audio device */
if (OpenDevice(AUDIONAME, 0, audioIOB, 0) == 0) {
/* setup the audio I/O block to play sound */
audioIOB->ioa_Request.io_Command = CMD_WRITE;
audioIOB->ioa_Request.io_Flags = ADIOF_PERVOL;
audioIOB->ioa_Data = beepWave;
audioIOB->ioa_Length = BEEPSIZE;
audioIOB->ioa_Period =
COLORCLOCK / (BEEPSIZE * BEEPFREQ);
audioIOB->ioa_Volume = 64;
/* start the sound */
BeginIO(audioIOB);
/* from this point on the task in cannot
be pre-empted. This prevents the
parent task from signaling it to
restart the timer while it is cleaning
up */
Forbid();
do {
/* start the timer */
timerIOB->tr_time.tv_secs = 0;
timerIOB->tr_time.tv_micro = 250000;
SendIO(timerIOB);
/* wait for:
. the timer to time out,
. the audio I/O block to return
(indicating an error had occurred),
. a signal to restart to timer, or
. a signal to quit */
do
signals = Wait(SIGBREAKF_CTRL_C |
SIGF_BEEP | SIGF_PORT);
while ((signals & SIGF_PORT) != 0 &&
CheckIO(timerIOB) == 0 &&
CheckIO(audioIOB) == 0);
/* if the timer is still going, kill it */
if (CheckIO(timerIOB) == 0) {
AbortIO(timerIOB);
WaitIO(timerIOB);
}
/* restart the timer if signaled */
} while ((signals & SIGF_BEEP) != 0);
/* clean up */
/* closing the audio device kills the sound
* and frees the channels */
CloseDevice(audioIOB);
}
DeleteExtIO(audioIOB);
}
FreeMem(beepWave, BEEPSIZE);
}
CloseDevice(timerIOB);
}
DeleteExtIO(timerIOB);
}
DeletePort(replyPort);
}
}
}