/* audio.c Martin Round November '89 This code is taken straight from Steven A. Bennett's 'scales.c' Thanks Steven! I've mostly left the code in it's original state, only putting in a few function prototypes and 'voids' to stop my compiler issuing me with warnings. I've also stripped comments and altered bracket indenting into my own weird style - sorry Steven! Actually it's not my own style, I'm driven to use it by a stupid Lint-like program I use called 'ccheck'. */ #define PRIORITY 10L #define NBR_IOA_STRUCTS 10L #define PV_IOA_STRUCT 0L #define FIN_IOA_STRUCT 9L #define BIG_WAVE 256L #define NBR_WAVES 7L #define WAVES_TOTAL 1024L #define YES 1L #define NO 0L extern struct MsgPort *CreatePort(); extern void *AllocMem(); void clear_audio (int); UBYTE aMap[] = { 0x0f }; long voiceMap[] = { 1, 2, 4, 8 }; struct IOAudio *ioa, *finishioa, *ioapv; struct IOAudio *ioainuse[4]; struct IOAudio *freeioa[4]; long unitno = 1; int error; int waiting[4] = { NO, NO, NO, NO }; int woffsets[] = { 0, 256, 384, 448, 480, 496, 504, 508, 510 }; int wlen[] = { 256, 128, 64, 32, 16, 8, 4, 2, 1 }; int perval[] = { 428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226, 214 }; BYTE *wptr; BYTE *owptr[4] = { NULL, NULL, NULL, NULL }; char *portstring[] = { "Audio one", "Audio two", "Audio three", "Audio four", "Audio five", "Audio six", "Audio seven", "Audio eight" }; int get_audio() { int i; ioa = (struct IOAudio *) AllocMem((NBR_IOA_STRUCTS * (long)sizeof(*ioa)),MEMF_PUBLIC | MEMF_CLEAR); if (ioa == NULL) { clear_audio(1); return(0); } for (i = 0; i < 4; ++i) { ioainuse[i] = &ioa[i + 1]; freeioa[i] = &ioa[i + 5]; } ioapv = &ioa[PV_IOA_STRUCT]; finishioa = &ioa[FIN_IOA_STRUCT]; ioa->ioa_Request.io_Message.mn_Node.ln_Pri = PRIORITY; ioa->ioa_Request.io_Message.mn_ReplyPort = CreatePort("Audio zero", 0L); if (ioa->ioa_Request.io_Message.mn_ReplyPort == NULL) { clear_audio(2); return(0); } ioa->ioa_Data = aMap; ioa->ioa_Length = (long)sizeof(aMap); error = OpenDevice(AUDIONAME, 0L, (struct ioRequest *) ioa, 0L); if (error) { clear_audio(3); return(0); } *finishioa = *ioa; finishioa->ioa_Request.io_Flags = IOF_QUICK; ioapv->ioa_Request.io_Flags = IOF_QUICK; finishioa->ioa_Request.io_Command = ADCMD_FINISH; ioapv->ioa_Request.io_Command = ADCMD_PERVOL; for (i = 0; i < 4; ++i) { *freeioa[i] = *ioa; *ioainuse[i] = *ioa; freeioa[i]->ioa_Request.io_Message.mn_ReplyPort = CreatePort(portstring[i], 0L); ioainuse[i]->ioa_Request.io_Message.mn_ReplyPort = CreatePort(portstring[i + 4], 0L); } for (i = 0; i < 4; ++i) if ( freeioa[i]->ioa_Request.io_Message.mn_ReplyPort == NULL || ioainuse[i]->ioa_Request.io_Message.mn_ReplyPort == NULL ) { clear_audio(4); return (0); } return (makewaves()); } void clear_audio(finishcode) int finishcode; { int i; switch(finishcode) { case 0: FreeMem(wptr, WAVES_TOTAL); case 4: case 5: for (i = 0; i < 4; ++i) { if (freeioa[i]->ioa_Request.io_Message.mn_ReplyPort) DeletePort(freeioa[i]->ioa_Request.io_Message.mn_ReplyPort); if (ioainuse[i]->ioa_Request.io_Message.mn_ReplyPort) DeletePort(ioainuse[i]->ioa_Request.io_Message.mn_ReplyPort); } CloseDevice((struct ioRequest *) ioa); case 3: DeletePort(ioa->ioa_Request.io_Message.mn_ReplyPort); case 2: FreeMem(ioa, (NBR_IOA_STRUCTS * (long)sizeof(*ioa))); } } void setwpv(wf, len, per, vol, voice) char *wf; int len, per, vol, voice; { struct IOAudio *tmpioa; freeioa[voice]->ioa_Request.io_Command = CMD_WRITE; freeioa[voice]->ioa_Request.io_Flags = ADIOF_PERVOL | IOF_QUICK; freeioa[voice]->ioa_Cycles = 0; freeioa[voice]->ioa_Request.io_Unit = (struct Unit *)unitno; finishioa->ioa_Request.io_Unit = (struct Unit *)unitno; freeioa[voice]->ioa_Data = (UBYTE *)wf; freeioa[voice]->ioa_Length = len; freeioa[voice]->ioa_Period = per; freeioa[voice]->ioa_Volume = vol; if (waiting[voice]) { BeginIO((struct ioRequest *) finishioa); WaitIO((struct ioRequest *) ioainuse[voice]); waiting[voice] = NO; } BeginIO((struct ioRequest *) freeioa[voice]); error = CheckIO((struct ioRequest *) freeioa[voice]); if (error) WaitIO((struct ioRequest *) freeioa[voice]); waiting[voice] = YES; tmpioa = ioainuse[voice]; ioainuse[voice] = freeioa[voice]; freeioa[voice] = tmpioa; } void setpv(per, vol) int per, vol; { ioapv->ioa_Period = per; ioapv->ioa_Volume = vol; ioapv->ioa_Request.io_Unit = (struct Unit *)unitno; BeginIO((struct ioRequest *) ioapv); } void StopVoices() { int voice; for (voice = 0; voice < 4; ++voice) { if (waiting[voice]) { unitno = voiceMap[voice]; setpv(128, 0); finishioa->ioa_Request.io_Unit = (struct Unit *)unitno; BeginIO((struct ioRequest *) finishioa); WaitIO((struct ioRequest *) ioainuse[voice]); waiting[voice] = NO; } } } void setwave(wfp) UBYTE *wfp; { int i; for (i = 0; i < BIG_WAVE; ++i) wfp[i] = i; } void xpandwave(wfp) BYTE *wfp; { int i, j, rate; BYTE *tptr; rate = 1; tptr = wfp + BIG_WAVE; for (i = 0; i < NBR_WAVES - 1; ++i) { rate *= 2; for (j = 0; j < BIG_WAVE; j += rate) *tptr++ = wfp[j]; } } int makewaves() { wptr = (BYTE *)AllocMem(WAVES_TOTAL, MEMF_CHIP); if (wptr == NULL) { clear_audio(5); return (0); } setwave(wptr); xpandwave(wptr); return (1); } void play_note(note, voice) int note, voice; { int per, oct; BYTE *wfp; unitno = voiceMap[voice]; if (note >= 100) { if (waiting[voice]) setpv(200, 0); return; } oct = note / 12; per = perval[note % 12]; wfp = wptr + woffsets[oct]; if (wfp == owptr[voice]) setpv(per, 32); else { setwpv(wfp, wlen[oct], per, 32, voice); owptr[voice] = wfp; } }