home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1998 #6
/
amigamamagazinepolishissue1998.iso
/
packery
/
fp_adpcm
/
deliplayers
/
source
/
adpcm-player.c
next >
Wrap
C/C++ Source or Header
|
1977-12-31
|
21KB
|
936 lines
/* DeliTracker-Player for ADPCM audio samples */
/* Written in 1995 by Christian Buchner. This is Public Domain. */
/* Note: TAB SIZE = 4 */
/* History:
added version string (still V1.0)
V1.1: reduced chip buffer size to 1K
V1.2: rewritten for loading constantly while playing
added dummy NotePlayer interface, makes Stereoscope etc. work
*/
/* Includes */
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <libraries/dos.h>
#include <dos/dostags.h>
#include <utility/tagitem.h>
#include <devices/audio.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <string.h>
#include <stdarg.h>
#include "DeliPlayer.h"
/* Version String */
#define PLAYER_VERSION 1
#define PLAYER_REVISION 2
UBYTE Version[]="$VER: ADPCM-Player 1.2 "__AMIGADATE__" by Christian Buchner";
/* Externals */
extern struct DosLibrary *DOSBase;
extern struct IntuitionBase *IntuitionBase;
/* DeliTracker's stuff */
struct DeliTrackerGlobals *DeliBase;
struct MsgPort *DeliPort;
/* Copyright and info */
UBYTE AboutString[]="a player for ADPCM audio samples\n"
"in MONO ADPCM2 or ADPCM3 format.\n"
"(c) 1995 by Christian Buchner";
void __asm __saveds DeliProcess(void);
ULONG __asm __saveds Check(void);
ULONG __asm __saveds InitPlayer(void);
ULONG __asm __saveds EndPlayer(void);
ULONG __asm __saveds InitSound(void);
ULONG __asm __saveds EndSound(void);
ULONG __asm __saveds StartInt(void);
ULONG __asm __saveds StopInt(void);
ULONG __asm __saveds Faster(void);
ULONG __asm __saveds Slower(void);
ULONG __asm __saveds VolBalance(void);
void SetPerVol(void);
void __stdargs Message(UBYTE *Msg,...);
struct NoteStruct *NotePlay;
extern __asm ULONG DecompressADPCM2( register __a0 UBYTE *Source,
register __d0 ULONG Length,
register __a1 UBYTE *Destination,
register __d1 ULONG JoinCode );
extern __asm ULONG DecompressADPCM3( register __a0 UBYTE *Source,
register __d0 ULONG Length,
register __a1 UBYTE *Destination,
register __d1 ULONG JoinCode );
/* Tag list for DeliTracker */
struct TagItem PlayerTagArray[]=
{
DTP_RequestDTVersion, 17,
DTP_PlayerVersion, (PLAYER_VERSION<<16)+10*PLAYER_REVISION,
DTP_PlayerName, (ULONG)"ADPCM-Player",
DTP_Creator, (ULONG)AboutString,
DTP_Description, (ULONG)"a player for ADPCM samples",
DTP_Flags, PLYF_SONGEND,
DTP_DeliBase, (ULONG)&DeliBase,
DTP_Check1, (ULONG)&Check,
DTP_Process, (ULONG)&DeliProcess,
DTP_Priority, 0,
DTP_StackSize, 4096,
DTP_MsgPort, (ULONG)&DeliPort,
DTP_NoteStruct, (ULONG)&NotePlay,
DTP_InitPlayer, (ULONG)&InitPlayer,
DTP_EndPlayer, (ULONG)&EndPlayer,
DTP_InitSound, (ULONG)&InitSound,
DTP_EndSound, (ULONG)&EndSound,
DTP_StartInt, (ULONG)&StartInt,
DTP_StopInt, (ULONG)&StopInt,
DTP_Volume, (ULONG)&VolBalance,
DTP_Balance, (ULONG)&VolBalance,
DTP_Faster, (ULONG)&Faster,
DTP_Slower, (ULONG)&Slower,
TAG_DONE
};
/* The primitive sample header */
struct ADPCMHeader
{
UBYTE Identifier[6];
ULONG Frequency;
};
UBYTE IDString[]="ADPCM";
struct Process *PlayerTask;
BOOL ChanInit;
struct MsgPort *LeftReply[3]; /* 2 for buffers, 1 for period/volume */
struct MsgPort *RightReply[3];
struct IOAudio *LeftAudio[3];
struct IOAudio *RightAudio[3];
#define CHIP_SIZE 1024
UBYTE *ChipBuffer[2];
/* specifies the buffer size in _decrunched_ bytes */
#define LOAD_SIZE (128*CHIP_SIZE)
/* specifies the length of the load queue */
#define QUEUE_LEN 2
BPTR LoadHandle;
ULONG FileSize;
struct LoadBuffer
{
struct MinNode lb_Node;
ULONG lb_ADPCMPosition;
UBYTE *lb_ADPCMData;
ULONG lb_ADPCMLen;
ULONG lb_PlayOffset;
};
struct List BufferList;
UWORD NumBuffers;
struct SignalSemaphore BufferSemaphore;
struct SignalSemaphore LoadQuitSemaphore;
struct Process *LoadProc;
void __saveds LoadBuffers(void);
ULONG Bits;
ULONG Frequency;
ULONG LeftVolume=64;
ULONG RightVolume=64;
ULONG ADPCMLen;
ULONG ADPCMPosition;
BOOL Loading=FALSE;
BOOL LoadingStopped=TRUE;
BOOL Playing;
BOOL BufPlaying[2];
ULONG PlayPosition;
ULONG JoinCode;
/*** NotePlayer interface ***/
BOOL NoteInit=FALSE;
UBYTE *NotePosition=NULL;
ULONG NoteLength=0;
UWORD NotePeriod=0;
struct NoteChannel NoteChannels[2]=
{
&NoteChannels[1], /* NextChannel */
0, /* for use by NotePlayer */
0, /* Reserved0 */
0, /* Private */
0, /* Changed */
NCHD_FarLeft,0, /* StereoPos, Stereo */
0,0, /* SampleStart, SampleLength */
0,0, /* RepeatStart, RepeatLength */
0, /* Frequency */
0, /* Volume */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* Reserved1 */
NULL, /* NextChannel */
0, /* for use by NotePlayer */
0, /* Reserved0 */
0, /* Private */
0, /* Changed */
NCHD_FarRight,0, /* StereoPos, Stereo */
0,0, /* SampleStart, SampleLength */
0,0, /* RepeatStart, RepeatLength */
0, /* Frequency */
0, /* Volume */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* Reserved1 */
};
struct NoteStruct NoteStruct=
{
&NoteChannels[0], /* Channels */
NSTF_Dummy|NSTF_Period|NSTF_Signed|NSTF_8Bit, /* Flags */
28867, /* Max Frequency */
64, /* Max Volume */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* reserved */
};
struct NoteStruct *NotePlay = &NoteStruct;
/****************************************************************************/
/* Our player's Process */
void __asm __saveds DeliProcess(void)
{
BOOL ProcActive=TRUE;
ULONG Signals;
struct DeliMessage *DeliMessage;
DOSBase=(struct DosLibrary*)DeliBase->DOSBase;
IntuitionBase=(struct IntuitionBase*)DeliBase->IntuitionBase;
PlayerTask=(struct Process*)FindTask(NULL);
PlayerTask->pr_Task.tc_Node.ln_Pri=22;
NewList(&BufferList);
InitSemaphore(&BufferSemaphore);
InitSemaphore(&LoadQuitSemaphore);
if (LoadProc=CreateNewProcTags( NP_Entry, &LoadBuffers,
NP_Name, "ADPCM Loader",
NP_Priority, 21,
TAG_DONE ))
{
while(ProcActive)
{
ULONG SigMask = SIGBREAKF_CTRL_C | (1L<<DeliPort->mp_SigBit);
if (ChanInit) SigMask |= (1L<<LeftReply[0]->mp_SigBit) |
(1L<<LeftReply[1]->mp_SigBit) ;
Signals=Wait(SigMask);
if (Signals & SIGBREAKF_CTRL_C)
{
ProcActive=FALSE;
}
if (Signals & (1L<<DeliPort->mp_SigBit))
{
if (DeliMessage=(struct DeliMessage*)GetMsg(DeliPort))
{
DeliMessage->Result=(*DeliMessage->Function)();
ReplyMsg((struct Message*)DeliMessage);
}
}
if (ChanInit)
{
UWORD i;
for (i=0;i<2;i++)
{
if (Signals & (1L<<LeftReply[i]->mp_SigBit))
{
if (BufPlaying[i])
{
WaitPort(LeftReply[i]); GetMsg(LeftReply[i]);
WaitPort(RightReply[i]); GetMsg(RightReply[i]);
BufPlaying[i]=FALSE;
}
if (Playing)
{
if (NoteInit)
{
NoteChannels[0].nch_SampleStart=
NoteChannels[0].nch_RepeatStart=
NoteChannels[1].nch_SampleStart=
NoteChannels[1].nch_RepeatStart=NotePosition;
NoteChannels[0].nch_SampleLength=
NoteChannels[0].nch_RepeatLength=
NoteChannels[1].nch_SampleLength=
NoteChannels[1].nch_RepeatLength=NoteLength;
NoteChannels[0].nch_Frequency=
NoteChannels[1].nch_Frequency=NotePeriod;
NoteChannels[0].nch_Volume=64;
NoteChannels[1].nch_Volume=64;
NoteChannels[0].nch_Changed=
NoteChannels[1].nch_Changed=NCHF_Sample|NCHF_Repeat|NCHF_Frequency|NCHF_Volume;
dt_NotePlayer();
NoteInit=FALSE;
}
if (PlayPosition > ADPCMLen)
{
Message("WARNING! PlayPosition > ADPCMLen!?!");
}
if (PlayPosition>=ADPCMLen)
{
/* Signal Songend */
dt_SongEnd();
}
ObtainSemaphore(&BufferSemaphore);
if (NumBuffers > 0)
{
struct LoadBuffer *lb;
ULONG Do;
ULONG ChipMax;
ULONG DMALen;
lb=(struct LoadBuffer*)BufferList.lh_Head;
if ( lb->lb_ADPCMPosition==0 &&
lb->lb_PlayOffset==0 )
{
JoinCode=0;
}
if (Bits==2) ChipMax = (CHIP_SIZE+3)/4;
if (Bits==3) ChipMax = (CHIP_SIZE+7)/8*3;
Do=lb->lb_ADPCMLen-lb->lb_PlayOffset;
if (Do>ChipMax) Do=ChipMax;
if (Do>0)
{
UWORD Period=(*(struct ExecBase**)(4))->ex_EClockFrequency*5/Frequency;
if (Bits==2) JoinCode=DecompressADPCM2(lb->lb_ADPCMData+lb->lb_PlayOffset, Do, ChipBuffer[i], JoinCode);
if (Bits==3) JoinCode=DecompressADPCM3(lb->lb_ADPCMData+lb->lb_PlayOffset, Do, ChipBuffer[i], JoinCode);
lb->lb_PlayOffset += Do;
PlayPosition=lb->lb_ADPCMPosition+lb->lb_PlayOffset;
if (Bits==2) DMALen = Do*4;
if (Bits==3) DMALen = Do*8/3;
LeftAudio[i]->ioa_Data =
RightAudio[i]->ioa_Data = ChipBuffer[i];
LeftAudio[i]->ioa_Length =
RightAudio[i]->ioa_Length = DMALen;
LeftAudio[i]->ioa_Period =
RightAudio[i]->ioa_Period= Period;
LeftAudio[i]->ioa_Volume=LeftVolume;
RightAudio[i]->ioa_Volume=RightVolume;
LeftAudio[i]->ioa_Cycles=
RightAudio[i]->ioa_Cycles=1;
LeftAudio[i]->ioa_Request.io_Flags|=ADIOF_PERVOL;
RightAudio[i]->ioa_Request.io_Flags|=ADIOF_PERVOL;
LeftAudio[i]->ioa_Request.io_Command=
RightAudio[i]->ioa_Request.io_Command=CMD_WRITE;
Forbid();
BeginIO(LeftAudio[i]);
BeginIO(RightAudio[i]);
BufPlaying[i]=TRUE;
Permit();
NotePosition=ChipBuffer[i];
NoteLength=DMALen;
NotePeriod=Period;
NoteInit=TRUE;
}
if (ADPCMPosition > ADPCMLen)
{
Message("WARNING! lb_PlayOffset > lb_ADPCMLen!?!");
}
if (lb->lb_PlayOffset >= lb->lb_ADPCMLen)
{
Remove((struct Node*)lb);
NumBuffers--;
Signal((struct Task*)LoadProc, SIGBREAKF_CTRL_D);
if (lb->lb_ADPCMData)
{
FreeVec(lb->lb_ADPCMData);
lb->lb_ADPCMData=NULL;
}
FreeVec(lb);
lb=NULL;
}
}
ReleaseSemaphore(&BufferSemaphore);
}
}
}
}
}
Signal((struct Task*)LoadProc, SIGBREAKF_CTRL_C);
ObtainSemaphore(&LoadQuitSemaphore);
}
}
/****************************************************************************/
void __saveds LoadBuffers(void)
{
ULONG Signals;
BOOL LoadActive=TRUE;
ObtainSemaphore(&LoadQuitSemaphore);
while (LoadActive)
{
Signals=Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D);
if (Signals & SIGBREAKF_CTRL_C)
{
LoadActive=FALSE;
}
if (Signals & SIGBREAKF_CTRL_D)
{
if (Loading==FALSE)
{
LoadingStopped=TRUE;
Signal(PlayerTask, SIGBREAKF_CTRL_D);
}
else
{
LoadingStopped=FALSE;
if (LoadHandle && ADPCMLen>sizeof(struct ADPCMHeader))
{
while (NumBuffers < QUEUE_LEN)
{
struct LoadBuffer *lb;
if (lb=AllocVec(sizeof(struct LoadBuffer),MEMF_ANY|MEMF_CLEAR))
{
BOOL Success=FALSE;
ULONG Do = ADPCMLen - ADPCMPosition;
ULONG Max;
if (Bits==2) Max=(LOAD_SIZE+3)/4;
if (Bits==3) Max=(LOAD_SIZE+7)/8*3;
if (Do > Max) Do=Max;
if (Do)
{
if (lb->lb_ADPCMData=AllocVec(Do, MEMF_ANY))
{
LONG Got;
Seek( LoadHandle,
ADPCMPosition+sizeof(struct ADPCMHeader),
OFFSET_BEGINNING );
Got=Read(LoadHandle, lb->lb_ADPCMData, Do);
if (Got < 0)
{
Message("Read error!");
}
else
{
if (Got != Do)
{
Message("Warning, short read! Wanted %ld, got %ld",Do,Got);
}
if (Got != 0) Success=TRUE;
lb->lb_ADPCMPosition=ADPCMPosition;
lb->lb_ADPCMLen=Got;
ADPCMPosition+=Got;
if (ADPCMPosition > ADPCMLen)
{
Message("WARNING! Position > Filesize!?!");
}
/* Restart loading */
if (ADPCMPosition >= ADPCMLen)
{
ADPCMPosition = 0;
}
}
}
}
if (Success)
{
ObtainSemaphore(&BufferSemaphore);
AddTail(&BufferList,(struct Node*)lb);
NumBuffers++;
if ( NumBuffers == QUEUE_LEN &&
BufPlaying[0] == FALSE &&
BufPlaying[1] == FALSE )
{
Signal(PlayerTask,(1L<<LeftReply[0]->mp_SigBit));
Signal(PlayerTask,(1L<<LeftReply[1]->mp_SigBit));
}
ReleaseSemaphore(&BufferSemaphore);
}
else
{
if (lb->lb_ADPCMData)
{
FreeVec(lb->lb_ADPCMData);
lb->lb_ADPCMData=NULL;
}
FreeVec(lb);
lb=NULL;
}
}
}
}
}
}
}
Forbid();
ReleaseSemaphore(&LoadQuitSemaphore);
}
/****************************************************************************/
/* Module check routine */
ULONG __asm __saveds Check(void)
{
BOOL Result=TRUE;
struct ADPCMHeader *Header=(struct ADPCMHeader*)(DeliBase->ChkData);
if (!strncmp(IDString,Header->Identifier,strlen(IDString)))
{
if ( Header->Identifier[5]=='2' ||
Header->Identifier[5]=='3' )
{
if (Header->Identifier[5]=='2') Bits=2;
if (Header->Identifier[5]=='3') Bits=3;
Frequency=Header->Frequency;
Result=FALSE;
}
}
return(Result);
}
/****************************************************************************/
/* Init player (alloc channels, etc...) */
ULONG __asm __saveds InitPlayer(void)
{
BOOL Error=TRUE;
if (LoadHandle=Open(DeliBase->PathArrayPtr,MODE_OLDFILE))
{
struct FileInfoBlock *fib;
if (fib=(struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_ANY))
{
UBYTE LeftArray[2]={1,8};
UBYTE RightArray[2]={2,4};
UWORD i;
if (ExamineFH(LoadHandle, fib))
{
FileSize = fib->fib_Size;
}
else
{
Seek(LoadHandle, 0, OFFSET_END);
FileSize = Seek(LoadHandle, 0, OFFSET_BEGINNING);
}
FreeMem(fib, sizeof(struct FileInfoBlock));
ADPCMLen = FileSize-sizeof(struct ADPCMHeader);
for (i=0;i<3;i++)
{
if (!(LeftReply[i]=CreateMsgPort())) break;
if (!(RightReply[i]=CreateMsgPort())) break;
if (!(LeftAudio[i]=CreateIORequest(LeftReply[i],sizeof(struct IOAudio)))) break;
if (!(RightAudio[i]=CreateIORequest(RightReply[i],sizeof(struct IOAudio)))) break;
if (i<2) if (!(ChipBuffer[i]=AllocVec(CHIP_SIZE,MEMF_CHIP))) break;
}
if (i==3)
{
LeftAudio[0]->ioa_Request.io_Message.mn_Node.ln_Pri=127;
LeftAudio[0]->ioa_Length=sizeof(LeftArray);
LeftAudio[0]->ioa_Data=LeftArray;
LeftAudio[0]->ioa_Request.io_Flags|=ADIOF_NOWAIT;
if (!OpenDevice("audio.device",0L,(struct IORequest *)LeftAudio[0],0))
{
for (i=1;i<3;i++)
{
LeftAudio[i]->ioa_Request.io_Device=LeftAudio[0]->ioa_Request.io_Device;
LeftAudio[i]->ioa_Request.io_Unit=LeftAudio[0]->ioa_Request.io_Unit;
LeftAudio[i]->ioa_AllocKey=LeftAudio[0]->ioa_AllocKey;
}
RightAudio[0]->ioa_Length=sizeof(RightArray);
RightAudio[0]->ioa_Request.io_Message.mn_Node.ln_Pri=127;
RightAudio[0]->ioa_Data=RightArray;
RightAudio[0]->ioa_Request.io_Flags|=ADIOF_NOWAIT;
if (!OpenDevice("audio.device",0L,(struct IORequest *)RightAudio[0],0))
{
for (i=1;i<3;i++)
{
RightAudio[i]->ioa_Request.io_Device=RightAudio[0]->ioa_Request.io_Device;
RightAudio[i]->ioa_Request.io_Unit=RightAudio[0]->ioa_Request.io_Unit;
RightAudio[i]->ioa_AllocKey=RightAudio[0]->ioa_AllocKey;
}
ChanInit=TRUE;
Error=FALSE;
}
}
}
}
}
if (Error)
{
EndPlayer();
}
DeliBase->SndNum=1;
return(Error);
}
/****************************************************************************/
/* Clean up the Player (deallocate, etc..) */
ULONG __asm __saveds EndPlayer(void)
{
WORD i;
for (i=2;i>=0;i--)
{
if (i<2)
{
if (ChipBuffer[i])
{
FreeVec(ChipBuffer[i]);
ChipBuffer[i]=NULL;
}
}
if (RightAudio[i])
{
if (i==0 && RightAudio[i]->ioa_Request.io_Device)
{
CloseDevice(RightAudio[i]);
RightAudio[i]->ioa_Request.io_Device=NULL;
}
DeleteIORequest(RightAudio[i]);
RightAudio[i]=NULL;
}
if (RightReply[i])
{
DeleteMsgPort(RightReply[i]);
RightReply[i]=NULL;
}
if (LeftAudio[i])
{
if (i==0 && LeftAudio[i]->ioa_Request.io_Device)
{
CloseDevice(LeftAudio[i]);
LeftAudio[i]->ioa_Request.io_Device=NULL;
}
DeleteIORequest(LeftAudio[i]);
LeftAudio[i]=NULL;
}
if (LeftReply[i])
{
DeleteMsgPort(LeftReply[i]);
LeftReply[i]=NULL;
}
}
if (LoadHandle)
{
Close(LoadHandle);
LoadHandle=NULL;
}
ChanInit=FALSE;
return(0);
}
/****************************************************************************/
/* Initialize the "Module" */
ULONG __asm __saveds InitSound(void)
{
ADPCMPosition = 0;
Loading = TRUE;
Signal((struct Task*)LoadProc, SIGBREAKF_CTRL_D);
return(0);
}
/****************************************************************************/
/* End sound */
ULONG __asm __saveds EndSound(void)
{
struct LoadBuffer *lb,*nextlb;
LoadingStopped=FALSE;
Loading=FALSE;
Forbid();
while (!LoadingStopped)
{
Signal((struct Task*)LoadProc, SIGBREAKF_CTRL_D);
Wait(SIGBREAKF_CTRL_D);
}
Permit();
ObtainSemaphore(&BufferSemaphore);
for( lb=(struct LoadBuffer*)BufferList.lh_Head ;
nextlb = (struct LoadBuffer*)lb->lb_Node.mln_Succ ;
lb = nextlb )
{
Remove((struct Node*)lb);
NumBuffers--;
if (lb->lb_ADPCMData)
{
FreeVec(lb->lb_ADPCMData);
lb->lb_ADPCMData=NULL;
}
FreeVec(lb);
lb=NULL;
}
ReleaseSemaphore(&BufferSemaphore);
return(0);
}
/****************************************************************************/
/* Start sound */
ULONG __asm __saveds StartInt(void)
{
PlayPosition=0;
Playing=TRUE;
if (NumBuffers == QUEUE_LEN)
{
Signal(PlayerTask,(1L<<LeftReply[0]->mp_SigBit));
Signal(PlayerTask,(1L<<LeftReply[1]->mp_SigBit));
}
return(0);
}
/****************************************************************************/
/* Stop sound */
ULONG __asm __saveds StopInt(void)
{
UWORD i;
Playing=FALSE;
for (i=0;i<2;i++)
{
if (BufPlaying[i])
{
AbortIO(LeftAudio[i]);
AbortIO(RightAudio[i]);
WaitPort(LeftReply[i]); GetMsg(LeftReply[i]);
WaitPort(RightReply[i]); GetMsg(RightReply[i]);
BufPlaying[i]=FALSE;
}
}
NoteInit=FALSE;
return(0);
}
/****************************************************************************/
/* Play Faster */
ULONG __asm __saveds Faster(void)
{
Frequency+=100;
SetPerVol();
return(0);
}
/****************************************************************************/
/* Slower */
ULONG __asm __saveds Slower(void)
{
Frequency-=100;
SetPerVol();
return(0);
}
/****************************************************************************/
/* Volume and Balance */
ULONG __asm __saveds VolBalance(void)
{
LeftVolume= DeliBase->SndVol*DeliBase->SndLBal/64;
RightVolume=DeliBase->SndVol*DeliBase->SndRBal/64;
SetPerVol();
return(0);
}
/****************************************************************************/
/* Set Period and Volume */
void SetPerVol(void)
{
UWORD i;
UWORD Period= (*(struct ExecBase**)(4))->ex_EClockFrequency*5/Frequency;
for (i=0;i<3;i++)
{
LeftAudio[i]->ioa_Period =
RightAudio[i]->ioa_Period=Period;
LeftAudio[i]->ioa_Volume=LeftVolume;
RightAudio[i]->ioa_Volume=RightVolume;
}
LeftAudio[2]->ioa_Request.io_Command=
RightAudio[2]->ioa_Request.io_Command=ADCMD_PERVOL;
DoIO((struct IORequest*)LeftAudio[2]);
DoIO((struct IORequest*)RightAudio[2]);
}
/*******************************************************************************/
/* Show a message to the user */
void __stdargs Message(UBYTE *Msg,...)
{
va_list Arg;
struct EasyStruct Req={sizeof(struct EasyStruct),0,"ADPCM-Player message",0,"Okay"};
Req.es_TextFormat=Msg;
va_start(Arg,Msg);
if (IntuitionBase)
{
EasyRequestArgs(NULL,&Req,0,Arg);
}
else
{
VPrintf(Msg,Arg);
Printf("\n");
}
va_end(Arg);
}