home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Sound / Misc / ADPCMPCK.LHA / FP_ADPCM / DeliPlayers / Source / ADPCM-Player.c next >
Encoding:
C/C++ Source or Header  |  1995-04-27  |  10.9 KB  |  513 lines

  1.  
  2. /* DeliTracker-Player for ADPCM audio samples */
  3.  
  4. #define PLAYER_VERSION 1
  5. #define PLAYER_REVISION 0
  6.  
  7. /* Note: TAB SIZE = 4 */
  8.  
  9. /* Includes */
  10.  
  11. #include <proto/dos.h>
  12. #include <proto/exec.h>
  13. #include <proto/intuition.h>
  14. #include <libraries/dos.h>
  15. #include <dos/rdargs.h>
  16. #include <utility/tagitem.h>
  17. #include <devices/audio.h>
  18. #include <exec/execbase.h>
  19. #include <exec/memory.h>
  20. #include <string.h>
  21. #include <stdarg.h>
  22. #include "DeliPlayer.h"
  23.  
  24. /* Externals */
  25.  
  26. extern struct DosLibrary *DOSBase;
  27. extern struct IntuitionBase *IntuitionBase;
  28.  
  29. /* DeliTracker's stuff */
  30.  
  31. struct DeliTrackerGlobals *DeliBase;
  32. struct MsgPort *DeliPort;
  33.  
  34. /* Copyright and info */
  35.  
  36. UBYTE AboutString[]="a player for ADPCM audio samples\n"
  37.                     "in MONO ADPCM2 or ADPCM3 format.\n"
  38.                     "(c) 1995 by Christian Buchner";
  39.  
  40.  
  41. void __asm __saveds DeliProcess(void);
  42. ULONG __asm __saveds Check(void);
  43. ULONG __asm __saveds InitPlayer(void);
  44. ULONG __asm __saveds EndPlayer(void);
  45. ULONG __asm __saveds InitSound(void);
  46. ULONG __asm __saveds EndSound(void);
  47. ULONG __asm __saveds StartInt(void);
  48. ULONG __asm __saveds StopInt(void);
  49. ULONG __asm __saveds Faster(void);
  50. ULONG __asm __saveds Slower(void);
  51. ULONG __asm __saveds VolBalance(void);
  52. void __stdargs Message(UBYTE *Msg,...);
  53.  
  54. extern __asm ULONG DecompressADPCM2(    register __a0 UBYTE *Source,
  55.                                         register __d0 ULONG Length,
  56.                                         register __a1 UBYTE *Destination,
  57.                                         register __d1 ULONG JoinCode    );
  58.  
  59. extern __asm ULONG DecompressADPCM3(    register __a0 UBYTE *Source,
  60.                                         register __d0 ULONG Length,
  61.                                         register __a1 UBYTE *Destination,
  62.                                         register __d1 ULONG JoinCode    );
  63.  
  64.  
  65. /* Tag list for DeliTracker */
  66.  
  67. struct TagItem PlayerTagArray[]=
  68. {
  69.     DTP_RequestDTVersion,    16,
  70.     DTP_PlayerVersion,        (PLAYER_VERSION<<16)+PLAYER_REVISION,
  71.     DTP_PlayerName,            (ULONG)"ADPCM-Player",
  72.     DTP_Creator,            (ULONG)AboutString,
  73.     DTP_Description,        (ULONG)"a player for ADPCM samples",
  74.     DTP_Flags,                PLYF_SONGEND|PLYF_ANYMEM,
  75.     DTP_DeliBase,            (ULONG)&DeliBase,
  76.     DTP_Check2,                (ULONG)&Check,
  77.     DTP_Process,            (ULONG)&DeliProcess,
  78.     DTP_Priority,            0,
  79.     DTP_StackSize,            4096,
  80.     DTP_MsgPort,            (ULONG)&DeliPort,
  81.     DTP_InitPlayer,            (ULONG)&InitPlayer,
  82.     DTP_EndPlayer,            (ULONG)&EndPlayer,
  83.     DTP_InitSound,            (ULONG)&InitSound,
  84.     DTP_EndSound,            (ULONG)&EndSound,
  85.     DTP_StartInt,            (ULONG)&StartInt,
  86.     DTP_StopInt,            (ULONG)&StopInt,
  87.     DTP_Volume,                (ULONG)&VolBalance,
  88.     DTP_Balance,            (ULONG)&VolBalance,
  89.     DTP_Faster,                (ULONG)&Faster,
  90.     DTP_Slower,                (ULONG)&Slower,
  91.     TAG_DONE
  92. };
  93.  
  94.  
  95. /* Variables and data for parsing the options (same as in CLIInterface.c) */
  96.  
  97. UBYTE IDString[]="ADPCM";
  98.  
  99. struct Process *MyProc;
  100.  
  101. BOOL ChanInit;
  102. struct MsgPort *LeftReply[2];
  103. struct MsgPort *RightReply[2];
  104. struct IOAudio *LeftAudio[2];
  105. struct IOAudio *RightAudio[2];
  106.  
  107. BOOL Playing;
  108.  
  109. #define CHIP_SIZE 4096
  110. UBYTE *ChipBuffer[2];
  111.  
  112. UBYTE *ModMem;
  113. ULONG ModLen;
  114.  
  115. ULONG Bits;
  116. ULONG Frequency;
  117. ULONG LeftVolume=64;
  118. ULONG RightVolume=64;
  119. ULONG RealLen;
  120.  
  121. BOOL BufPlaying[2];
  122. ULONG Position;
  123. ULONG JoinCode;
  124.  
  125.  
  126. /****************************************************************************/
  127.  
  128. /* Our player's Process */
  129.  
  130. void __asm __saveds DeliProcess(void)
  131. {
  132.     BOOL ProcActive=TRUE;
  133.     ULONG Signals;
  134.     struct DeliMessage *DeliMessage;
  135.     UWORD i;
  136.     
  137.     DOSBase=(struct DosLibrary*)DeliBase->DOSBase;
  138.     IntuitionBase=(struct IntuitionBase*)DeliBase->IntuitionBase;
  139.     
  140.     MyProc=(struct Process*)FindTask(NULL);
  141.     MyProc->pr_Task.tc_Node.ln_Pri=21;
  142.     
  143.     while(ProcActive)
  144.     {
  145.         ULONG SigMask = SIGBREAKF_CTRL_C | (1L<<DeliPort->mp_SigBit);
  146.         
  147.         if (ChanInit) SigMask |=    (1L<<LeftReply[0]->mp_SigBit) | 
  148.                                     (1L<<LeftReply[1]->mp_SigBit) ;
  149.         
  150.         Signals=Wait(SigMask);
  151.         
  152.         if (Signals & SIGBREAKF_CTRL_C)
  153.         {
  154.             ProcActive=FALSE;
  155.         }
  156.         
  157.         if (Signals & (1L<<DeliPort->mp_SigBit))
  158.         {
  159.             if (DeliMessage=(struct DeliMessage*)GetMsg(DeliPort))
  160.             {
  161.                 DeliMessage->Result=(DeliMessage->Function)();
  162.                 ReplyMsg((struct Message*)DeliMessage);
  163.             }
  164.         }
  165.         
  166.         if (ChanInit)
  167.         {
  168.             LONG ChipMax, Left, Do, DMALen;
  169.             
  170.             for (i=0;i<2;i++)
  171.             {
  172.                 if (Signals & (1L<<LeftReply[i]->mp_SigBit))
  173.                 {
  174.                     if (BufPlaying[i])
  175.                     {
  176.                         WaitPort(LeftReply[i]);        GetMsg(LeftReply[i]);
  177.                         WaitPort(RightReply[i]);    GetMsg(RightReply[i]);
  178.                         BufPlaying[i]=FALSE;
  179.                     }
  180.                     
  181.                     if (Playing)
  182.                     {
  183.                         if (Bits==2) ChipMax = (CHIP_SIZE+3)/4;
  184.                         if (Bits==3) ChipMax = (CHIP_SIZE+7)/8*3;
  185.                         
  186.                         if (Position>=RealLen)
  187.                         {
  188.                             /* Signal Songend */
  189.                             dt_SongEnd();
  190.                             
  191.                             Position=0;
  192.                         }
  193.                         
  194.                         Left = RealLen-Position;
  195.                         Do = Left < ChipMax ? Left : ChipMax;
  196.                         
  197.                         if (Do>0)
  198.                         {
  199.                             UBYTE *Source=ModMem+10+Position;
  200.                             
  201.                             if (Bits==2) JoinCode=DecompressADPCM2(Source, Do, ChipBuffer[i], JoinCode);
  202.                             if (Bits==3) JoinCode=DecompressADPCM3(Source, Do, ChipBuffer[i], JoinCode);
  203.                             
  204.                             Position+=Do;
  205.                             
  206.                             if (Bits==2) DMALen = Do*4;
  207.                             if (Bits==3) DMALen = Do*8/3;
  208.                             
  209.                             LeftAudio[i]->ioa_Data =
  210.                             RightAudio[i]->ioa_Data = ChipBuffer[i];
  211.                             
  212.                             LeftAudio[i]->ioa_Length =
  213.                             RightAudio[i]->ioa_Length = DMALen;
  214.                             
  215.                             LeftAudio[i]->ioa_Period = 
  216.                             RightAudio[i]->ioa_Period=(*(struct ExecBase**)(4))->ex_EClockFrequency*5/Frequency;
  217.                             
  218.                             LeftAudio[i]->ioa_Volume=LeftVolume;
  219.                             RightAudio[i]->ioa_Volume=RightVolume;
  220.                             
  221.                             LeftAudio[i]->ioa_Cycles=
  222.                             RightAudio[i]->ioa_Cycles=1;
  223.                             
  224.                             LeftAudio[i]->ioa_Request.io_Flags|=ADIOF_PERVOL;
  225.                             RightAudio[i]->ioa_Request.io_Flags|=ADIOF_PERVOL;
  226.                             
  227.                             LeftAudio[i]->ioa_Request.io_Command=
  228.                             RightAudio[i]->ioa_Request.io_Command=CMD_WRITE;
  229.                             
  230.                             Forbid();
  231.                             BeginIO(LeftAudio[i]);
  232.                             BeginIO(RightAudio[i]);
  233.                             BufPlaying[i]=TRUE;
  234.                             Permit();
  235.                         }
  236.                     }
  237.                 }
  238.             }
  239.         }
  240.     }
  241. }
  242.  
  243.  
  244. /****************************************************************************/
  245.  
  246. /* Module check routine */
  247.  
  248. ULONG __asm __saveds Check(void)
  249. {
  250.     BOOL Result=TRUE;
  251.     
  252.     if (!strncmp(IDString,DeliBase->ChkData,5))
  253.     {
  254.         if ( ((UBYTE*)DeliBase->ChkData)[5]=='2' ||
  255.              ((UBYTE*)DeliBase->ChkData)[5]=='3' )
  256.         {
  257.             Result=FALSE;
  258.         }
  259.     }
  260.     return(Result);
  261. }
  262.  
  263.  
  264. /****************************************************************************/
  265.  
  266. /* Init player (alloc channels, etc...) */
  267.  
  268. ULONG __asm __saveds InitPlayer(void)
  269. {
  270.     BOOL Error=TRUE;
  271.     UWORD i;
  272.     
  273.     UBYTE LeftArray[2]={1,8};
  274.     UBYTE RightArray[2]={2,4};
  275.     
  276.     for (i=0;i<2;i++)
  277.     {
  278.         if (!(LeftReply[i]=CreateMsgPort())) break;
  279.         if (!(RightReply[i]=CreateMsgPort())) break;
  280.         
  281.         if (!(LeftAudio[i]=CreateIORequest(LeftReply[i],sizeof(struct IOAudio)))) break;
  282.         if (!(RightAudio[i]=CreateIORequest(RightReply[i],sizeof(struct IOAudio)))) break;
  283.         
  284.         if (!(ChipBuffer[i]=AllocVec(CHIP_SIZE,MEMF_CHIP))) break;
  285.     }
  286.     if (i==2)
  287.     {
  288.         LeftAudio[0]->ioa_Request.io_Message.mn_Node.ln_Pri=127;
  289.         LeftAudio[0]->ioa_Length=sizeof(LeftArray);
  290.         LeftAudio[0]->ioa_Data=LeftArray;
  291.         LeftAudio[0]->ioa_Request.io_Flags|=ADIOF_NOWAIT;
  292.         if (!OpenDevice("audio.device",0L,(struct IORequest *)LeftAudio[0],0))
  293.         {
  294.             LeftAudio[1]->ioa_Request.io_Device=LeftAudio[0]->ioa_Request.io_Device;
  295.             LeftAudio[1]->ioa_Request.io_Unit=LeftAudio[0]->ioa_Request.io_Unit;
  296.             LeftAudio[1]->ioa_AllocKey=LeftAudio[0]->ioa_AllocKey;
  297.             
  298.             RightAudio[0]->ioa_Length=sizeof(RightArray);
  299.             RightAudio[0]->ioa_Request.io_Message.mn_Node.ln_Pri=127;
  300.             RightAudio[0]->ioa_Data=RightArray;
  301.             RightAudio[0]->ioa_Request.io_Flags|=ADIOF_NOWAIT;
  302.             if (!OpenDevice("audio.device",0L,(struct IORequest *)RightAudio[0],0))
  303.             {
  304.                 RightAudio[1]->ioa_Request.io_Device=RightAudio[0]->ioa_Request.io_Device;
  305.                 RightAudio[1]->ioa_Request.io_Unit=RightAudio[0]->ioa_Request.io_Unit;
  306.                 RightAudio[1]->ioa_AllocKey=RightAudio[0]->ioa_AllocKey;
  307.                 
  308.                 ModMem=dt_GetListDataPos(0);
  309.                 ModLen=dt_GetListDataSize(0);
  310.                 if (ModMem[5]=='2') Bits=2;
  311.                 if (ModMem[5]=='3') Bits=3;
  312.                 Frequency= *(ULONG*)(ModMem+6);
  313.                 RealLen=ModLen-10;
  314.                 
  315.                 ChanInit=TRUE;
  316.                 
  317.                 Error=FALSE;
  318.             }
  319.         }
  320.     }
  321.     
  322.     if (Error)
  323.     {
  324.         EndPlayer();
  325.     }
  326.     
  327.     DeliBase->SndNum=1;
  328.     
  329.     return(Error);
  330. }
  331.  
  332.  
  333. /****************************************************************************/
  334.  
  335. /* Clean up the Player (deallocate, etc..) */
  336.  
  337. ULONG __asm __saveds EndPlayer(void)
  338. {
  339.     WORD i;
  340.     
  341.     for (i=1;i>=0;i--)
  342.     {
  343.         if (ChipBuffer[i])
  344.         {
  345.             FreeVec(ChipBuffer[i]);
  346.             ChipBuffer[i]=NULL;
  347.         }
  348.         
  349.         if (RightAudio[i])
  350.         {
  351.             if (i==0 && RightAudio[i]->ioa_Request.io_Device)
  352.             {
  353.                 CloseDevice(RightAudio[i]);
  354.                 RightAudio[i]->ioa_Request.io_Device=NULL;
  355.             }
  356.             DeleteIORequest(RightAudio[i]);
  357.             RightAudio[i]=NULL;
  358.         }
  359.         
  360.         if (RightReply[i])
  361.         {
  362.             DeleteMsgPort(RightReply[i]);
  363.             RightReply[i]=NULL;
  364.         }
  365.         
  366.         if (LeftAudio[i])
  367.         {
  368.             if (i==0 && LeftAudio[i]->ioa_Request.io_Device)
  369.             {
  370.                 CloseDevice(LeftAudio[i]);
  371.                 LeftAudio[i]->ioa_Request.io_Device=NULL;
  372.             }
  373.             DeleteIORequest(LeftAudio[i]);
  374.             LeftAudio[i]=NULL;
  375.         }
  376.         
  377.         if (LeftReply[i])
  378.         {
  379.             DeleteMsgPort(LeftReply[i]);
  380.             LeftReply[i]=NULL;
  381.         }
  382.     }
  383.     
  384.     ChanInit=FALSE;
  385.     
  386.     return(0);
  387. }
  388.  
  389.  
  390. /****************************************************************************/
  391.  
  392. /* Initialize the "Module" */
  393.  
  394. ULONG __asm __saveds InitSound(void)
  395. {
  396.     Playing=FALSE;
  397.     BufPlaying[0]=BufPlaying[1]=FALSE;
  398.     Position=0;
  399.     JoinCode=0;
  400.     
  401.     return(0);
  402. }
  403.  
  404.  
  405. /****************************************************************************/
  406.  
  407. /* End sound */
  408.  
  409. ULONG __asm __saveds EndSound(void)
  410. {
  411.     return(0);
  412. }
  413.  
  414.  
  415. /****************************************************************************/
  416.  
  417. /* Start sound */
  418.  
  419. ULONG __asm __saveds StartInt(void)
  420. {
  421.     Playing=TRUE;
  422.     
  423.     Signal(MyProc,(1L<<LeftReply[0]->mp_SigBit));
  424.     Signal(MyProc,(1L<<LeftReply[1]->mp_SigBit));
  425.     
  426.     return(0);
  427. }
  428.  
  429.  
  430. /****************************************************************************/
  431.  
  432. /* Stop sound */
  433.  
  434. ULONG __asm __saveds StopInt(void)
  435. {
  436.     UWORD i;
  437.     
  438.     Playing=FALSE;
  439.     
  440.     for (i=0;i<2;i++)
  441.     {
  442.         if (BufPlaying[i])
  443.         {
  444.             AbortIO(LeftAudio[i]);
  445.             AbortIO(RightAudio[i]);
  446.             WaitPort(LeftReply[i]);        GetMsg(LeftReply[i]);
  447.             WaitPort(RightReply[i]);    GetMsg(RightReply[i]);
  448.             BufPlaying[i]=FALSE;
  449.         }
  450.     }
  451.     
  452.     return(0);
  453. }
  454.  
  455.  
  456. /****************************************************************************/
  457.  
  458. /* Play Faster */
  459.  
  460. ULONG __asm __saveds Faster(void)
  461. {
  462.     Frequency+=100;
  463.     return(0);
  464. }
  465.  
  466.  
  467. /****************************************************************************/
  468.  
  469. /* Slower */
  470.  
  471. ULONG __asm __saveds Slower(void)
  472. {
  473.     Frequency-=100;
  474.     return(0);
  475. }
  476.  
  477.  
  478. /****************************************************************************/
  479.  
  480. /* Volume and Balance */
  481.  
  482. ULONG __asm __saveds VolBalance(void)
  483. {
  484.     LeftVolume= DeliBase->SndVol*DeliBase->SndLBal/64;
  485.     RightVolume=DeliBase->SndVol*DeliBase->SndRBal/64;
  486.     return(0);
  487. }
  488.  
  489.  
  490. /*******************************************************************************/
  491.  
  492. /* Show a message to the user */
  493.  
  494. void __stdargs Message(UBYTE *Msg,...)
  495. {
  496.     va_list Arg;
  497.     struct EasyStruct Req={sizeof(struct EasyStruct),0,"ADPCM-Player message",0,"Okay"};
  498.     Req.es_TextFormat=Msg;
  499.     va_start(Arg,Msg);
  500.     
  501.     if (IntuitionBase)
  502.     {
  503.         EasyRequestArgs(NULL,&Req,0,Arg);
  504.     }
  505.     else
  506.     {
  507.         VPrintf(Msg,Arg);
  508.         Printf("\n");
  509.     }
  510.     
  511.     va_end(Arg);
  512. }
  513.