home *** CD-ROM | disk | FTP | other *** search
-
- /* Stand-Alone Player for ADPCM audio samples */
- /* Written in 1995 by Christian Buchner. This is Public Domain. */
- /* Also look out for xPlay, also available on AmiNet */
-
- /* Note: TAB SIZE = 4 */
-
- /* History:
-
- V1.1: Now recognizes when channels have been stolen
- Uses WaitIO() instead of WaitPort()/GetMsg() pair.
- */
-
- /* Includes */
-
- #include <clib/dos_protos.h>
- #include <clib/exec_protos.h>
- #include <clib/alib_protos.h>
- #include <pragmas/dos_pragmas.h>
- #include <pragmas/exec_pragmas.h>
-
- #include <libraries/dos.h>
- #include <dos/rdargs.h>
- #include <utility/tagitem.h>
- #include <devices/audio.h>
- #include <exec/execbase.h>
- #include <exec/memory.h>
- #include <string.h>
- #include <hardware/cia.h>
-
-
- /* Version string */
-
- UBYTE Version[]="$VER: PlayADPCM 1.1 "__AMIGADATE__" by Christian Buchner";
-
-
- /* Prototypes */
-
- BOOL PlayADPCM(struct MyVars *mv, UBYTE *Filename, ULONG Size, ULONG Filter, ULONG NoFilter, ULONG Quiet);
- BOOL OpenAudio(struct MyVars *mv, ULONG Filter, ULONG NoFilter);
- void CloseAudio(struct MyVars *mv);
- void AbortPlay(struct MyVars *mv);
- void WaitPlay(struct MyVars *mv);
-
-
- 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 );
-
-
- /* Replay Buffer size */
-
- #define CHIP_SIZE 16384
-
-
- /* CLI Arguments */
-
- UBYTE Template[]="FILES/M/A,ALL/S,FL=FILTER/S,NFL=NOFILTER/S,QUIET/S";
-
- struct ArgArray
- {
- UBYTE **aa_Files;
- ULONG aa_All;
- ULONG aa_Filter;
- ULONG aa_NoFilter;
- ULONG aa_Quiet;
- };
-
-
- /* Library Bases */
-
- struct DosLibrary *DOSBase;
-
-
- /* Local Variables */
-
- struct MyVars
- {
- struct Process *MyProc;
-
- struct MsgPort *LeftReply[2];
- struct MsgPort *RightReply[2];
- struct IOAudio *LeftAudio[2];
- struct IOAudio *RightAudio[2];
-
- BOOL Playing;
-
- UBYTE *ChipBuffer[2];
-
- BOOL BufPlaying[2];
- };
-
-
- /* Access to CIA registers */
-
- struct CIA *ciaa=(struct CIA*)0xbfe001;
-
-
- /* CLI interface and Pattern Matching */
-
- LONG __saveds main(void)
- {
- struct MyVars *mv;
- UBYTE ProgName[60];
- struct RDArgs *RDArgs;
- struct ArgArray AA={NULL,FALSE,FALSE,FALSE,FALSE};
- char **Files;
- struct AnchorPath *AnchorPath;
- ULONG ReturnCode=RETURN_FAIL;
-
- if (mv=AllocVec(sizeof(struct MyVars),MEMF_ANY|MEMF_CLEAR))
- {
- if (DOSBase=(struct DosLibrary*)OpenLibrary("dos.library",37))
- {
- if (!GetProgramName(ProgName,sizeof(ProgName))) strcpy(ProgName,"PlayADPCM");
-
- if (!(RDArgs=ReadArgs(Template,(LONG *)&AA,0)))
- {
- PrintFault(IoErr(),ProgName);
- }
- else
- {
- if (Files=AA.aa_Files)
- {
- if (!(AnchorPath=(struct AnchorPath *)AllocVec(sizeof(struct AnchorPath)+256,MEMF_PUBLIC|MEMF_CLEAR)))
- {
- PrintFault(ERROR_NO_FREE_STORE,ProgName);
- }
- else
- {
- ReturnCode=RETURN_OK;
-
- AnchorPath->ap_BreakBits=SIGBREAKF_CTRL_C;
- AnchorPath->ap_Strlen=256;
-
- while ((!ReturnCode) && *Files)
- {
- LONG RetVal;
-
- RetVal=MatchFirst(*Files,AnchorPath);
- while(!RetVal)
- {
- if (AnchorPath->ap_Info.fib_DirEntryType>0L)
- {
- if ((!(AnchorPath->ap_Flags&APF_DIDDIR))&&AA.aa_All)
- {
- AnchorPath->ap_Flags|=APF_DODIR;
- }
- AnchorPath->ap_Flags&=~APF_DIDDIR;
- }
- else
- {
- if (PlayADPCM(mv, AnchorPath->ap_Buf, AnchorPath->ap_Info.fib_Size, AA.aa_Filter, AA.aa_NoFilter, AA.aa_Quiet))
- {
- RetVal=ERROR_BREAK;
- break;
- }
- }
- RetVal=MatchNext(AnchorPath);
- }
- MatchEnd(AnchorPath);
-
- if (RetVal==ERROR_BREAK)
- {
- PrintFault(RetVal,NULL);
- ReturnCode=RETURN_WARN;
- }
- else
- {
- if (RetVal!=ERROR_NO_MORE_ENTRIES)
- {
- PrintFault(RetVal,*Files);
- ReturnCode=RETURN_ERROR;
- }
- }
- Files++;
- }
- FreeVec((APTR)AnchorPath);
- }
- }
- FreeArgs(RDArgs);
- }
- CloseLibrary((struct Library*)DOSBase);
- }
- FreeVec(mv);
- }
- }
-
-
- /* The primitive sample header */
-
- struct ADPCMHeader
- {
- UBYTE Identifier[6];
- ULONG Frequency;
- };
-
-
- /* The playback routine */
-
- BOOL PlayADPCM(struct MyVars *mv, UBYTE *Filename, ULONG Size, ULONG Filter, ULONG NoFilter, ULONG Quiet)
- {
- BOOL Break=FALSE;
-
- BPTR File;
- struct ADPCMHeader ADPCMHeader;
-
- if (!(File=Open(Filename,MODE_OLDFILE)))
- {
- PrintFault(IoErr(),Filename);
- }
- else
- {
- /* Read in sample header */
- if (Read(File,&ADPCMHeader,sizeof(struct ADPCMHeader))==sizeof(struct ADPCMHeader))
- {
- if (strncmp("ADPCM",ADPCMHeader.Identifier,5))
- {
- Printf("%s: Not ADPCM format!\n",Filename);
- }
- else
- {
- Size-=sizeof(ADPCMHeader);
-
- /* Check if it is a supported ADPCM format */
- if (ADPCMHeader.Identifier[5] != '2' && ADPCMHeader.Identifier[5] != '3')
- {
- Printf("%s: Unsupported ADPCM format!\n",Filename);
- }
- else
- {
- ULONG Bits;
-
- /* Retrieve the number of compression bits */
- if (ADPCMHeader.Identifier[5] == '2') Bits=2;
- if (ADPCMHeader.Identifier[5] == '3') Bits=3;
-
- if (!OpenAudio(mv,Filter,NoFilter))
- {
- Printf("%s: Can't get audio channels!\n",Filename);
- }
- else
- {
- UBYTE *ADPCMBuffer;
- ULONG ADPCMSize;
-
- if (Bits==2) ADPCMSize=(CHIP_SIZE+3)/4;
- if (Bits==3) ADPCMSize=(CHIP_SIZE+7)/8*3;
-
- if (!(ADPCMBuffer=AllocVec(ADPCMSize, MEMF_ANY|MEMF_CLEAR)))
- {
- Printf("%s: Out of memory!\n",Filename);
- }
- else
- {
- struct Process *MyProc;
- ULONG Position=0;
- ULONG JoinCode=0;
- BOOL ProcActive=TRUE;
- ULONG Signals;
- UWORD i;
- LONG ChipMax, Left, Do, DMALen;
- BOOL Aborted=FALSE;
-
- if (!Quiet) Printf("\rPlaying %s",Filename);
-
- MyProc=(struct Process*)FindTask(NULL);
-
- Signal(MyProc,(1L<<mv->LeftReply[0]->mp_SigBit));
- Signal(MyProc,(1L<<mv->LeftReply[1]->mp_SigBit));
-
- while(ProcActive)
- {
- ULONG SigMask = SIGBREAKF_CTRL_C |
- (1L<<mv->LeftReply[0]->mp_SigBit) |
- (1L<<mv->LeftReply[1]->mp_SigBit) ;
-
- Signals=Wait(SigMask);
-
- if (Signals & SIGBREAKF_CTRL_C)
- {
- Printf("\n");
-
- AbortPlay(mv);
-
- Break=TRUE;
- Aborted=TRUE;
- ProcActive=FALSE;
- }
-
- for (i=0;ProcActive && i<2;i++)
- {
- if (Signals & (1L<<mv->LeftReply[i]->mp_SigBit))
- {
- if (mv->BufPlaying[i])
- {
- BYTE LError, RError;
-
- LError=WaitIO(mv->LeftAudio[i]);
- RError=WaitIO(mv->RightAudio[i]);
- mv->BufPlaying[i]=FALSE;
-
- if (LError || RError)
- {
- Printf("\r%s: Channels have been stolen!\n",Filename);
-
- AbortPlay(mv);
-
- Aborted=TRUE;
- ProcActive=FALSE;
- break;
- }
- }
-
- if (Bits==2) ChipMax = (CHIP_SIZE+3)/4;
- if (Bits==3) ChipMax = (CHIP_SIZE+7)/8*3;
-
- if (Position>=Size)
- {
- Position=0;
-
- ProcActive=FALSE;
- break;
- }
-
- Left = Size-Position;
- Do = Left < ChipMax ? Left : ChipMax;
-
- if (Do>0)
- {
- LONG Got;
-
- if (!Quiet) Printf("\rPlaying %s (%02ld%%)",Filename,100*Position/Size);
-
- if (Got=Read(File, ADPCMBuffer, Do) != Do)
- {
- if (Got<0) PrintFault(IoErr(),Filename);
- else Printf("\r%s: Error, short read!\n",Filename);
- Aborted=TRUE;
- ProcActive=FALSE;
- break;
- }
-
- if (Bits==2) JoinCode=DecompressADPCM2(ADPCMBuffer, Do, mv->ChipBuffer[i], JoinCode);
- if (Bits==3) JoinCode=DecompressADPCM3(ADPCMBuffer, Do, mv->ChipBuffer[i], JoinCode);
-
- Position+=Do;
-
- if (Bits==2) DMALen = Do*4;
- if (Bits==3) DMALen = Do*8/3;
-
- mv->LeftAudio[i]->ioa_Data =
- mv->RightAudio[i]->ioa_Data = mv->ChipBuffer[i];
-
- mv->LeftAudio[i]->ioa_Length =
- mv->RightAudio[i]->ioa_Length = DMALen;
-
- mv->LeftAudio[i]->ioa_Period =
- mv->RightAudio[i]->ioa_Period=(*(struct ExecBase**)(4))->ex_EClockFrequency*5/ADPCMHeader.Frequency;
-
- mv->LeftAudio[i]->ioa_Volume=64;
- mv->RightAudio[i]->ioa_Volume=64;
-
- mv->LeftAudio[i]->ioa_Cycles=
- mv->RightAudio[i]->ioa_Cycles=1;
-
- mv->LeftAudio[i]->ioa_Request.io_Flags|=ADIOF_PERVOL;
- mv->RightAudio[i]->ioa_Request.io_Flags|=ADIOF_PERVOL;
-
- mv->LeftAudio[i]->ioa_Request.io_Command=
- mv->RightAudio[i]->ioa_Request.io_Command=CMD_WRITE;
-
- Forbid();
- BeginIO(mv->LeftAudio[i]);
- BeginIO(mv->RightAudio[i]);
- mv->BufPlaying[i]=TRUE;
- Permit();
- }
- }
- }
- }
-
- WaitPlay(mv);
-
- if ((!Quiet) && (!Aborted)) Printf("\rPlayed %s - OK \n",Filename);
-
- FreeVec(ADPCMBuffer);
- }
- CloseAudio(mv);
- }
- }
- }
- }
- Close(File);
- }
- return(Break);
- }
-
-
- /* Allocate audio channels */
-
- BOOL OpenAudio(struct MyVars *mv, ULONG Filter, ULONG NoFilter)
- {
- BOOL Success=FALSE;
- UWORD i;
-
- UBYTE LeftArray[2]={1,8};
- UBYTE RightArray[2]={2,4};
-
- for (i=0;i<2;i++)
- {
- if (!(mv->LeftReply[i]=CreateMsgPort())) break;
- if (!(mv->RightReply[i]=CreateMsgPort())) break;
-
- if (!(mv->LeftAudio[i]=CreateIORequest(mv->LeftReply[i],sizeof(struct IOAudio)))) break;
- if (!(mv->RightAudio[i]=CreateIORequest(mv->RightReply[i],sizeof(struct IOAudio)))) break;
-
- if (!(mv->ChipBuffer[i]=AllocVec(CHIP_SIZE,MEMF_CHIP))) break;
- }
- if (i==2)
- {
- mv->LeftAudio[0]->ioa_Request.io_Message.mn_Node.ln_Pri=0;
- mv->LeftAudio[0]->ioa_Length=sizeof(LeftArray);
- mv->LeftAudio[0]->ioa_Data=LeftArray;
- mv->LeftAudio[0]->ioa_Request.io_Flags|=ADIOF_NOWAIT;
- if (!OpenDevice("audio.device",0L,(struct IORequest *)mv->LeftAudio[0],0))
- {
- mv->LeftAudio[1]->ioa_Request.io_Device=mv->LeftAudio[0]->ioa_Request.io_Device;
- mv->LeftAudio[1]->ioa_Request.io_Unit=mv->LeftAudio[0]->ioa_Request.io_Unit;
- mv->LeftAudio[1]->ioa_AllocKey=mv->LeftAudio[0]->ioa_AllocKey;
-
- mv->RightAudio[0]->ioa_Length=sizeof(RightArray);
- mv->RightAudio[0]->ioa_Request.io_Message.mn_Node.ln_Pri=0;
- mv->RightAudio[0]->ioa_Data=RightArray;
- mv->RightAudio[0]->ioa_Request.io_Flags|=ADIOF_NOWAIT;
- if (!OpenDevice("audio.device",0L,(struct IORequest *)mv->RightAudio[0],0))
- {
- mv->RightAudio[1]->ioa_Request.io_Device=mv->RightAudio[0]->ioa_Request.io_Device;
- mv->RightAudio[1]->ioa_Request.io_Unit=mv->RightAudio[0]->ioa_Request.io_Unit;
- mv->RightAudio[1]->ioa_AllocKey=mv->RightAudio[0]->ioa_AllocKey;
-
- mv->BufPlaying[0]=mv->BufPlaying[1]=FALSE;
-
- if (Filter)
- {
- ciaa->ciapra &= ~(CIAF_LED);
- }
- if (NoFilter)
- {
- ciaa->ciapra |= CIAF_LED;
- }
-
- Success=TRUE;
- }
- }
- }
-
- if (!Success)
- {
- CloseAudio(mv);
- }
-
- return(Success);
- }
-
-
- /* Abort playing */
-
- void AbortPlay(struct MyVars *mv)
- {
- WORD i;
-
- for (i=0;i<2;i++)
- {
- if (mv->BufPlaying[i])
- {
- AbortIO(mv->LeftAudio[i]);
- AbortIO(mv->RightAudio[i]);
- }
- }
-
- WaitPlay(mv);
- }
-
-
- /* Wait for audio requests */
-
- void WaitPlay(struct MyVars *mv)
- {
- WORD i;
-
- for (i=0;i<2;i++)
- {
- if (mv->BufPlaying[i])
- {
- WaitIO(mv->LeftAudio[i]);
- WaitIO(mv->RightAudio[i]);
- mv->BufPlaying[i]=FALSE;
- }
- }
- }
-
-
- /* Close the audio channels */
-
- void CloseAudio(struct MyVars *mv)
- {
- WORD i;
-
- for (i=0;i<2;i++)
- {
- if (mv->BufPlaying[i])
- {
- AbortIO(mv->LeftAudio[i]);
- AbortIO(mv->RightAudio[i]);
- WaitIO(mv->LeftAudio[i]);
- WaitIO(mv->RightAudio[i]);
- mv->BufPlaying[i]=FALSE;
- }
- }
-
- for (i=1;i>=0;i--)
- {
- if (mv->ChipBuffer[i])
- {
- FreeVec(mv->ChipBuffer[i]);
- mv->ChipBuffer[i]=NULL;
- }
-
- if (mv->RightAudio[i])
- {
- if (i==0 && mv->RightAudio[i]->ioa_Request.io_Device)
- {
- CloseDevice(mv->RightAudio[i]);
- mv->RightAudio[i]->ioa_Request.io_Device=NULL;
- }
- DeleteIORequest(mv->RightAudio[i]);
- mv->RightAudio[i]=NULL;
- }
-
- if (mv->RightReply[i])
- {
- DeleteMsgPort(mv->RightReply[i]);
- mv->RightReply[i]=NULL;
- }
-
- if (mv->LeftAudio[i])
- {
- if (i==0 && mv->LeftAudio[i]->ioa_Request.io_Device)
- {
- CloseDevice(mv->LeftAudio[i]);
- mv->LeftAudio[i]->ioa_Request.io_Device=NULL;
- }
- DeleteIORequest(mv->LeftAudio[i]);
- mv->LeftAudio[i]=NULL;
- }
-
- if (mv->LeftReply[i])
- {
- DeleteMsgPort(mv->LeftReply[i]);
- mv->LeftReply[i]=NULL;
- }
- }
- }
-