home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / packery / fp_adpcm / deliplayers / source / adpcm-player.c next >
C/C++ Source or Header  |  1977-12-31  |  21KB  |  936 lines

  1.  
  2. /*         DeliTracker-Player for ADPCM audio samples           */
  3. /* Written in 1995 by Christian Buchner. This is Public Domain. */
  4.  
  5. /* Note: TAB SIZE = 4 */
  6.  
  7. /* History:
  8.  
  9.    added version string (still V1.0)
  10.  
  11.    V1.1: reduced chip buffer size to 1K
  12.  
  13.    V1.2: rewritten for loading constantly while playing
  14.          added dummy NotePlayer interface, makes Stereoscope etc. work
  15.  
  16. */
  17.  
  18. /* Includes */
  19.  
  20. #include <proto/dos.h>
  21. #include <proto/exec.h>
  22. #include <proto/intuition.h>
  23. #include <libraries/dos.h>
  24. #include <dos/dostags.h>
  25. #include <utility/tagitem.h>
  26. #include <devices/audio.h>
  27. #include <exec/execbase.h>
  28. #include <exec/memory.h>
  29. #include <string.h>
  30. #include <stdarg.h>
  31. #include "DeliPlayer.h"
  32.  
  33.  
  34. /* Version String */
  35.  
  36. #define PLAYER_VERSION 1
  37. #define PLAYER_REVISION 2
  38.  
  39. UBYTE Version[]="$VER: ADPCM-Player 1.2 "__AMIGADATE__" by Christian Buchner";
  40.  
  41.  
  42. /* Externals */
  43.  
  44. extern struct DosLibrary *DOSBase;
  45. extern struct IntuitionBase *IntuitionBase;
  46.  
  47. /* DeliTracker's stuff */
  48.  
  49. struct DeliTrackerGlobals *DeliBase;
  50. struct MsgPort *DeliPort;
  51.  
  52. /* Copyright and info */
  53.  
  54. UBYTE AboutString[]="a player for ADPCM audio samples\n"
  55.                     "in MONO ADPCM2 or ADPCM3 format.\n"
  56.                     "(c) 1995 by Christian Buchner";
  57.  
  58.  
  59. void __asm __saveds DeliProcess(void);
  60. ULONG __asm __saveds Check(void);
  61. ULONG __asm __saveds InitPlayer(void);
  62. ULONG __asm __saveds EndPlayer(void);
  63. ULONG __asm __saveds InitSound(void);
  64. ULONG __asm __saveds EndSound(void);
  65. ULONG __asm __saveds StartInt(void);
  66. ULONG __asm __saveds StopInt(void);
  67. ULONG __asm __saveds Faster(void);
  68. ULONG __asm __saveds Slower(void);
  69. ULONG __asm __saveds VolBalance(void);
  70. void SetPerVol(void);
  71. void __stdargs Message(UBYTE *Msg,...);
  72.  
  73. struct NoteStruct *NotePlay;
  74.  
  75. extern __asm ULONG DecompressADPCM2(    register __a0 UBYTE *Source,
  76.                                         register __d0 ULONG Length,
  77.                                         register __a1 UBYTE *Destination,
  78.                                         register __d1 ULONG JoinCode    );
  79.  
  80. extern __asm ULONG DecompressADPCM3(    register __a0 UBYTE *Source,
  81.                                         register __d0 ULONG Length,
  82.                                         register __a1 UBYTE *Destination,
  83.                                         register __d1 ULONG JoinCode    );
  84.  
  85.  
  86. /* Tag list for DeliTracker */
  87.  
  88. struct TagItem PlayerTagArray[]=
  89. {
  90.     DTP_RequestDTVersion,    17,
  91.     DTP_PlayerVersion,        (PLAYER_VERSION<<16)+10*PLAYER_REVISION,
  92.     DTP_PlayerName,            (ULONG)"ADPCM-Player",
  93.     DTP_Creator,            (ULONG)AboutString,
  94.     DTP_Description,        (ULONG)"a player for ADPCM samples",
  95.     DTP_Flags,                PLYF_SONGEND,
  96.     DTP_DeliBase,            (ULONG)&DeliBase,
  97.     DTP_Check1,                (ULONG)&Check,
  98.     DTP_Process,            (ULONG)&DeliProcess,
  99.     DTP_Priority,            0,
  100.     DTP_StackSize,            4096,
  101.     DTP_MsgPort,            (ULONG)&DeliPort,
  102.     DTP_NoteStruct,            (ULONG)&NotePlay,
  103.     DTP_InitPlayer,            (ULONG)&InitPlayer,
  104.     DTP_EndPlayer,            (ULONG)&EndPlayer,
  105.     DTP_InitSound,            (ULONG)&InitSound,
  106.     DTP_EndSound,            (ULONG)&EndSound,
  107.     DTP_StartInt,            (ULONG)&StartInt,
  108.     DTP_StopInt,            (ULONG)&StopInt,
  109.     DTP_Volume,                (ULONG)&VolBalance,
  110.     DTP_Balance,            (ULONG)&VolBalance,
  111.     DTP_Faster,                (ULONG)&Faster,
  112.     DTP_Slower,                (ULONG)&Slower,
  113.     TAG_DONE
  114. };
  115.  
  116.  
  117. /* The primitive sample header */
  118.  
  119. struct ADPCMHeader
  120. {
  121.     UBYTE Identifier[6];
  122.     ULONG Frequency;
  123. };
  124.  
  125. UBYTE IDString[]="ADPCM";
  126.  
  127. struct Process *PlayerTask;
  128.  
  129. BOOL ChanInit;
  130. struct MsgPort *LeftReply[3];        /* 2 for buffers, 1 for period/volume */
  131. struct MsgPort *RightReply[3];
  132. struct IOAudio *LeftAudio[3];
  133. struct IOAudio *RightAudio[3];
  134.  
  135. #define CHIP_SIZE 1024
  136. UBYTE *ChipBuffer[2];
  137.  
  138. /* specifies the buffer size in _decrunched_ bytes */
  139. #define LOAD_SIZE (128*CHIP_SIZE)
  140.  
  141. /* specifies the length of the load queue */
  142. #define QUEUE_LEN 2
  143.  
  144. BPTR LoadHandle;
  145. ULONG FileSize;
  146.  
  147. struct LoadBuffer
  148. {
  149.     struct MinNode lb_Node;
  150.     ULONG lb_ADPCMPosition;
  151.     UBYTE *lb_ADPCMData;
  152.     ULONG lb_ADPCMLen;
  153.     ULONG lb_PlayOffset;
  154. };
  155.  
  156. struct List BufferList;
  157. UWORD NumBuffers;
  158. struct SignalSemaphore BufferSemaphore;
  159. struct SignalSemaphore LoadQuitSemaphore;
  160.  
  161. struct Process *LoadProc;
  162. void __saveds LoadBuffers(void);
  163.  
  164. ULONG Bits;
  165. ULONG Frequency;
  166. ULONG LeftVolume=64;
  167. ULONG RightVolume=64;
  168.  
  169. ULONG ADPCMLen;
  170. ULONG ADPCMPosition;
  171. BOOL Loading=FALSE;
  172. BOOL LoadingStopped=TRUE;
  173.  
  174. BOOL Playing;
  175. BOOL BufPlaying[2];
  176. ULONG PlayPosition;
  177. ULONG JoinCode;
  178.  
  179.  
  180. /*** NotePlayer interface ***/
  181.  
  182. BOOL NoteInit=FALSE;
  183. UBYTE *NotePosition=NULL;
  184. ULONG NoteLength=0;
  185. UWORD NotePeriod=0;
  186.  
  187. struct NoteChannel NoteChannels[2]=
  188. {
  189.     &NoteChannels[1],        /* NextChannel */
  190.     0,                        /* for use by NotePlayer */
  191.     0,                        /* Reserved0 */
  192.     0,                        /* Private */
  193.     0,                        /* Changed */
  194.     NCHD_FarLeft,0,            /* StereoPos, Stereo */
  195.     0,0,                    /* SampleStart, SampleLength */
  196.     0,0,                    /* RepeatStart, RepeatLength */
  197.     0,                        /* Frequency */
  198.     0,                        /* Volume */
  199.     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 */
  200.     
  201.     NULL,                    /* NextChannel */
  202.     0,                        /* for use by NotePlayer */
  203.     0,                        /* Reserved0 */
  204.     0,                        /* Private */
  205.     0,                        /* Changed */
  206.     NCHD_FarRight,0,        /* StereoPos, Stereo */
  207.     0,0,                    /* SampleStart, SampleLength */
  208.     0,0,                    /* RepeatStart, RepeatLength */
  209.     0,                        /* Frequency */
  210.     0,                        /* Volume */                      
  211.     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 */
  212. };
  213.  
  214. struct NoteStruct NoteStruct=
  215. {
  216.     &NoteChannels[0],                                /* Channels */
  217.     NSTF_Dummy|NSTF_Period|NSTF_Signed|NSTF_8Bit,    /* Flags */
  218.     28867,                                            /* Max Frequency */
  219.     64,                                                /* Max Volume */
  220.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0                /* reserved */
  221. };
  222.  
  223. struct NoteStruct *NotePlay = &NoteStruct;
  224.  
  225.  
  226. /****************************************************************************/
  227.  
  228. /* Our player's Process */
  229.  
  230. void __asm __saveds DeliProcess(void)
  231. {
  232.     BOOL ProcActive=TRUE;
  233.     ULONG Signals;
  234.     struct DeliMessage *DeliMessage;
  235.     
  236.     DOSBase=(struct DosLibrary*)DeliBase->DOSBase;
  237.     IntuitionBase=(struct IntuitionBase*)DeliBase->IntuitionBase;
  238.     
  239.     PlayerTask=(struct Process*)FindTask(NULL);
  240.     PlayerTask->pr_Task.tc_Node.ln_Pri=22;
  241.     
  242.     NewList(&BufferList);
  243.     InitSemaphore(&BufferSemaphore);
  244.     InitSemaphore(&LoadQuitSemaphore);
  245.     
  246.     if (LoadProc=CreateNewProcTags(    NP_Entry, &LoadBuffers,
  247.                                     NP_Name, "ADPCM Loader",
  248.                                     NP_Priority, 21,
  249.                                     TAG_DONE ))
  250.     {
  251.         while(ProcActive)
  252.         {
  253.             ULONG SigMask = SIGBREAKF_CTRL_C | (1L<<DeliPort->mp_SigBit);
  254.             
  255.             if (ChanInit) SigMask |=    (1L<<LeftReply[0]->mp_SigBit) | 
  256.                                         (1L<<LeftReply[1]->mp_SigBit) ;
  257.             
  258.             Signals=Wait(SigMask);
  259.             
  260.             if (Signals & SIGBREAKF_CTRL_C)
  261.             {
  262.                 ProcActive=FALSE;
  263.             }
  264.             
  265.             if (Signals & (1L<<DeliPort->mp_SigBit))
  266.             {
  267.                 if (DeliMessage=(struct DeliMessage*)GetMsg(DeliPort))
  268.                 {
  269.                     DeliMessage->Result=(*DeliMessage->Function)();
  270.                     ReplyMsg((struct Message*)DeliMessage);
  271.                 }
  272.             }
  273.             
  274.             if (ChanInit)
  275.             {
  276.                 UWORD i;
  277.                 
  278.                 for (i=0;i<2;i++)
  279.                 {
  280.                     if (Signals & (1L<<LeftReply[i]->mp_SigBit))
  281.                     {
  282.                         if (BufPlaying[i])
  283.                         {
  284.                             WaitPort(LeftReply[i]);        GetMsg(LeftReply[i]);
  285.                             WaitPort(RightReply[i]);    GetMsg(RightReply[i]);
  286.                             BufPlaying[i]=FALSE;
  287.                         }
  288.                         
  289.                         if (Playing)
  290.                         {
  291.                             if (NoteInit)
  292.                             {
  293.                                 NoteChannels[0].nch_SampleStart=
  294.                                 NoteChannels[0].nch_RepeatStart=
  295.                                 NoteChannels[1].nch_SampleStart=
  296.                                 NoteChannels[1].nch_RepeatStart=NotePosition;
  297.                                 
  298.                                 NoteChannels[0].nch_SampleLength=
  299.                                 NoteChannels[0].nch_RepeatLength=
  300.                                 NoteChannels[1].nch_SampleLength=
  301.                                 NoteChannels[1].nch_RepeatLength=NoteLength;
  302.                                 
  303.                                 NoteChannels[0].nch_Frequency=
  304.                                 NoteChannels[1].nch_Frequency=NotePeriod;
  305.                                 
  306.                                 NoteChannels[0].nch_Volume=64;
  307.                                 NoteChannels[1].nch_Volume=64;
  308.                                 
  309.                                 NoteChannels[0].nch_Changed=
  310.                                 NoteChannels[1].nch_Changed=NCHF_Sample|NCHF_Repeat|NCHF_Frequency|NCHF_Volume;
  311.                                 
  312.                                 dt_NotePlayer();
  313.                                 
  314.                                 NoteInit=FALSE;
  315.                             }
  316.                             
  317.                             if (PlayPosition > ADPCMLen)
  318.                             {
  319.                                 Message("WARNING! PlayPosition > ADPCMLen!?!");
  320.                             }
  321.                             
  322.                             if (PlayPosition>=ADPCMLen)
  323.                             {
  324.                                 /* Signal Songend */
  325.                                 dt_SongEnd();
  326.                             }
  327.                             
  328.                             ObtainSemaphore(&BufferSemaphore);
  329.                             
  330.                             if (NumBuffers > 0)
  331.                             {
  332.                                 struct LoadBuffer *lb;
  333.                                 
  334.                                 ULONG Do;
  335.                                 ULONG ChipMax;
  336.                                 ULONG DMALen;
  337.                                 
  338.                                 lb=(struct LoadBuffer*)BufferList.lh_Head;
  339.                                 
  340.                                 if (    lb->lb_ADPCMPosition==0 &&
  341.                                         lb->lb_PlayOffset==0        )
  342.                                 {
  343.                                     JoinCode=0;
  344.                                 }
  345.                                 
  346.                                 if (Bits==2) ChipMax = (CHIP_SIZE+3)/4;
  347.                                 if (Bits==3) ChipMax = (CHIP_SIZE+7)/8*3;
  348.                                 
  349.                                 Do=lb->lb_ADPCMLen-lb->lb_PlayOffset;
  350.                                 if (Do>ChipMax) Do=ChipMax;
  351.                                 
  352.                                 if (Do>0)
  353.                                 {
  354.                                     UWORD Period=(*(struct ExecBase**)(4))->ex_EClockFrequency*5/Frequency;
  355.                                     
  356.                                     if (Bits==2) JoinCode=DecompressADPCM2(lb->lb_ADPCMData+lb->lb_PlayOffset, Do, ChipBuffer[i], JoinCode);
  357.                                     if (Bits==3) JoinCode=DecompressADPCM3(lb->lb_ADPCMData+lb->lb_PlayOffset, Do, ChipBuffer[i], JoinCode);
  358.                                     
  359.                                     lb->lb_PlayOffset += Do;
  360.                                     PlayPosition=lb->lb_ADPCMPosition+lb->lb_PlayOffset;
  361.                                     
  362.                                     if (Bits==2) DMALen = Do*4;
  363.                                     if (Bits==3) DMALen = Do*8/3;
  364.                                     
  365.                                     LeftAudio[i]->ioa_Data =
  366.                                     RightAudio[i]->ioa_Data = ChipBuffer[i];
  367.                                     
  368.                                     LeftAudio[i]->ioa_Length =
  369.                                     RightAudio[i]->ioa_Length = DMALen;
  370.                                     
  371.                                     LeftAudio[i]->ioa_Period = 
  372.                                     RightAudio[i]->ioa_Period= Period;
  373.                                     
  374.                                     LeftAudio[i]->ioa_Volume=LeftVolume;
  375.                                     RightAudio[i]->ioa_Volume=RightVolume;
  376.                                     
  377.                                     LeftAudio[i]->ioa_Cycles=
  378.                                     RightAudio[i]->ioa_Cycles=1;
  379.                                     
  380.                                     LeftAudio[i]->ioa_Request.io_Flags|=ADIOF_PERVOL;
  381.                                     RightAudio[i]->ioa_Request.io_Flags|=ADIOF_PERVOL;
  382.                                     
  383.                                     LeftAudio[i]->ioa_Request.io_Command=
  384.                                     RightAudio[i]->ioa_Request.io_Command=CMD_WRITE;
  385.                                     
  386.                                     Forbid();
  387.                                     BeginIO(LeftAudio[i]);
  388.                                     BeginIO(RightAudio[i]);
  389.                                     BufPlaying[i]=TRUE;
  390.                                     Permit();
  391.                                     
  392.                                     NotePosition=ChipBuffer[i];
  393.                                     NoteLength=DMALen;
  394.                                     NotePeriod=Period;
  395.                                     NoteInit=TRUE;
  396.                                 }
  397.                                 
  398.                                 if (ADPCMPosition > ADPCMLen)
  399.                                 {
  400.                                     Message("WARNING! lb_PlayOffset > lb_ADPCMLen!?!");
  401.                                 }
  402.                                 
  403.                                 if (lb->lb_PlayOffset >= lb->lb_ADPCMLen)
  404.                                 {
  405.                                     Remove((struct Node*)lb);
  406.                                     NumBuffers--;
  407.                                     
  408.                                     Signal((struct Task*)LoadProc, SIGBREAKF_CTRL_D);
  409.                                     
  410.                                     if (lb->lb_ADPCMData)
  411.                                     {
  412.                                         FreeVec(lb->lb_ADPCMData);
  413.                                         lb->lb_ADPCMData=NULL;
  414.                                     }
  415.                                     
  416.                                     FreeVec(lb);
  417.                                     lb=NULL;
  418.                                 }
  419.                             }
  420.                             
  421.                             ReleaseSemaphore(&BufferSemaphore);
  422.                         }
  423.                     }
  424.                 }
  425.             }
  426.         }
  427.         Signal((struct Task*)LoadProc, SIGBREAKF_CTRL_C);
  428.         ObtainSemaphore(&LoadQuitSemaphore);
  429.     }
  430. }
  431.  
  432.  
  433. /****************************************************************************/
  434.  
  435. void __saveds LoadBuffers(void)
  436. {
  437.     ULONG Signals;
  438.     BOOL LoadActive=TRUE;
  439.     
  440.     ObtainSemaphore(&LoadQuitSemaphore);
  441.     
  442.     while (LoadActive)
  443.     {
  444.         Signals=Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D);
  445.         
  446.         if (Signals & SIGBREAKF_CTRL_C)
  447.         {
  448.             LoadActive=FALSE;
  449.         }
  450.         
  451.         if (Signals & SIGBREAKF_CTRL_D)
  452.         {
  453.             if (Loading==FALSE)
  454.             {
  455.                 LoadingStopped=TRUE;
  456.                 
  457.                 Signal(PlayerTask, SIGBREAKF_CTRL_D);
  458.             }
  459.             else
  460.             {
  461.                 LoadingStopped=FALSE;
  462.                 
  463.                 if (LoadHandle && ADPCMLen>sizeof(struct ADPCMHeader))
  464.                 {
  465.                     while (NumBuffers < QUEUE_LEN)
  466.                     {
  467.                         struct LoadBuffer *lb;
  468.                         if (lb=AllocVec(sizeof(struct LoadBuffer),MEMF_ANY|MEMF_CLEAR))
  469.                         {
  470.                             BOOL Success=FALSE;
  471.                             
  472.                             ULONG Do = ADPCMLen - ADPCMPosition;
  473.                             ULONG Max;
  474.                             if (Bits==2) Max=(LOAD_SIZE+3)/4;
  475.                             if (Bits==3) Max=(LOAD_SIZE+7)/8*3;
  476.                             if (Do > Max) Do=Max;
  477.                             
  478.                             if (Do)
  479.                             {
  480.                                 if (lb->lb_ADPCMData=AllocVec(Do, MEMF_ANY))
  481.                                 {
  482.                                     LONG Got;
  483.                                     Seek(    LoadHandle,
  484.                                             ADPCMPosition+sizeof(struct ADPCMHeader),
  485.                                             OFFSET_BEGINNING );
  486.                                     
  487.                                     Got=Read(LoadHandle, lb->lb_ADPCMData, Do);
  488.                                     
  489.                                     if (Got < 0)
  490.                                     {
  491.                                         Message("Read error!");
  492.                                     }
  493.                                     else
  494.                                     {
  495.                                         if (Got != Do)
  496.                                         {
  497.                                             Message("Warning, short read! Wanted %ld, got %ld",Do,Got);
  498.                                         }
  499.                                         
  500.                                         if (Got != 0) Success=TRUE;
  501.                                         
  502.                                         lb->lb_ADPCMPosition=ADPCMPosition;
  503.                                         lb->lb_ADPCMLen=Got;
  504.                                         ADPCMPosition+=Got;
  505.                                         
  506.                                         if (ADPCMPosition > ADPCMLen)
  507.                                         {
  508.                                             Message("WARNING! Position > Filesize!?!");
  509.                                         }
  510.                                         
  511.                                         /* Restart loading */
  512.                                         if (ADPCMPosition >= ADPCMLen)
  513.                                         {
  514.                                             ADPCMPosition = 0;
  515.                                         }
  516.                                     }
  517.                                 }
  518.                             }
  519.                             
  520.                             if (Success)
  521.                             {
  522.                                 ObtainSemaphore(&BufferSemaphore);
  523.                                 AddTail(&BufferList,(struct Node*)lb);
  524.                                 NumBuffers++;
  525.                                 
  526.                                 if (    NumBuffers    == QUEUE_LEN &&
  527.                                         BufPlaying[0] == FALSE     &&
  528.                                         BufPlaying[1] == FALSE          )
  529.                                 {
  530.                                     Signal(PlayerTask,(1L<<LeftReply[0]->mp_SigBit));
  531.                                     Signal(PlayerTask,(1L<<LeftReply[1]->mp_SigBit));
  532.                                 }
  533.                                 
  534.                                 ReleaseSemaphore(&BufferSemaphore);
  535.                             }
  536.                             else
  537.                             {
  538.                                 if (lb->lb_ADPCMData)
  539.                                 {
  540.                                     FreeVec(lb->lb_ADPCMData);
  541.                                     lb->lb_ADPCMData=NULL;
  542.                                 }
  543.                                 FreeVec(lb);
  544.                                 lb=NULL;
  545.                             }
  546.                         }
  547.                     }
  548.                 }
  549.             }
  550.         }
  551.     }
  552.     
  553.     Forbid();
  554.     ReleaseSemaphore(&LoadQuitSemaphore);
  555. }
  556.  
  557.  
  558. /****************************************************************************/
  559.  
  560. /* Module check routine */
  561.  
  562. ULONG __asm __saveds Check(void)
  563. {
  564.     BOOL Result=TRUE;
  565.     
  566.     struct ADPCMHeader *Header=(struct ADPCMHeader*)(DeliBase->ChkData);
  567.     
  568.     if (!strncmp(IDString,Header->Identifier,strlen(IDString)))
  569.     {
  570.         if ( Header->Identifier[5]=='2' ||
  571.              Header->Identifier[5]=='3' )
  572.         {
  573.             if (Header->Identifier[5]=='2') Bits=2;
  574.             if (Header->Identifier[5]=='3') Bits=3;
  575.             Frequency=Header->Frequency;
  576.             
  577.             Result=FALSE;
  578.         }
  579.     }
  580.     return(Result);
  581. }
  582.  
  583.  
  584. /****************************************************************************/
  585.  
  586. /* Init player (alloc channels, etc...) */
  587.  
  588. ULONG __asm __saveds InitPlayer(void)
  589. {
  590.     BOOL Error=TRUE;
  591.     
  592.     if (LoadHandle=Open(DeliBase->PathArrayPtr,MODE_OLDFILE))
  593.     {
  594.         struct FileInfoBlock *fib;
  595.         if (fib=(struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_ANY))
  596.         {
  597.             UBYTE LeftArray[2]={1,8};
  598.             UBYTE RightArray[2]={2,4};
  599.             UWORD i;
  600.             
  601.             if (ExamineFH(LoadHandle, fib))
  602.             {
  603.                 FileSize = fib->fib_Size;
  604.             }
  605.             else
  606.             {
  607.                 Seek(LoadHandle, 0, OFFSET_END);
  608.                 FileSize = Seek(LoadHandle, 0, OFFSET_BEGINNING);
  609.             }
  610.             
  611.             FreeMem(fib, sizeof(struct FileInfoBlock));
  612.             
  613.             ADPCMLen = FileSize-sizeof(struct ADPCMHeader);
  614.             
  615.             for (i=0;i<3;i++)
  616.             {
  617.                 if (!(LeftReply[i]=CreateMsgPort())) break;
  618.                 if (!(RightReply[i]=CreateMsgPort())) break;
  619.                 
  620.                 if (!(LeftAudio[i]=CreateIORequest(LeftReply[i],sizeof(struct IOAudio)))) break;
  621.                 if (!(RightAudio[i]=CreateIORequest(RightReply[i],sizeof(struct IOAudio)))) break;
  622.                 
  623.                 if (i<2) if (!(ChipBuffer[i]=AllocVec(CHIP_SIZE,MEMF_CHIP))) break;
  624.             }
  625.             if (i==3)
  626.             {
  627.                 LeftAudio[0]->ioa_Request.io_Message.mn_Node.ln_Pri=127;
  628.                 LeftAudio[0]->ioa_Length=sizeof(LeftArray);
  629.                 LeftAudio[0]->ioa_Data=LeftArray;
  630.                 LeftAudio[0]->ioa_Request.io_Flags|=ADIOF_NOWAIT;
  631.                 if (!OpenDevice("audio.device",0L,(struct IORequest *)LeftAudio[0],0))
  632.                 {
  633.                     for (i=1;i<3;i++)
  634.                     {
  635.                         LeftAudio[i]->ioa_Request.io_Device=LeftAudio[0]->ioa_Request.io_Device;
  636.                         LeftAudio[i]->ioa_Request.io_Unit=LeftAudio[0]->ioa_Request.io_Unit;
  637.                         LeftAudio[i]->ioa_AllocKey=LeftAudio[0]->ioa_AllocKey;
  638.                     }
  639.                     RightAudio[0]->ioa_Length=sizeof(RightArray);
  640.                     RightAudio[0]->ioa_Request.io_Message.mn_Node.ln_Pri=127;
  641.                     RightAudio[0]->ioa_Data=RightArray;
  642.                     RightAudio[0]->ioa_Request.io_Flags|=ADIOF_NOWAIT;
  643.                     if (!OpenDevice("audio.device",0L,(struct IORequest *)RightAudio[0],0))
  644.                     {
  645.                         for (i=1;i<3;i++)
  646.                         {
  647.                             RightAudio[i]->ioa_Request.io_Device=RightAudio[0]->ioa_Request.io_Device;
  648.                             RightAudio[i]->ioa_Request.io_Unit=RightAudio[0]->ioa_Request.io_Unit;
  649.                             RightAudio[i]->ioa_AllocKey=RightAudio[0]->ioa_AllocKey;
  650.                         }
  651.                         
  652.                         ChanInit=TRUE;
  653.                         
  654.                         Error=FALSE;
  655.                     }
  656.                 }
  657.             }
  658.         }
  659.     }
  660.     
  661.     if (Error)
  662.     {
  663.         EndPlayer();
  664.     }
  665.     
  666.     DeliBase->SndNum=1;
  667.     
  668.     return(Error);
  669. }
  670.  
  671.  
  672. /****************************************************************************/
  673.  
  674. /* Clean up the Player (deallocate, etc..) */
  675.  
  676. ULONG __asm __saveds EndPlayer(void)
  677. {
  678.     WORD i;
  679.     
  680.     for (i=2;i>=0;i--)
  681.     {
  682.         if (i<2)
  683.         {
  684.             if (ChipBuffer[i])
  685.             {
  686.                 FreeVec(ChipBuffer[i]);
  687.                 ChipBuffer[i]=NULL;
  688.             }
  689.         }
  690.         
  691.         if (RightAudio[i])
  692.         {
  693.             if (i==0 && RightAudio[i]->ioa_Request.io_Device)
  694.             {
  695.                 CloseDevice(RightAudio[i]);
  696.                 RightAudio[i]->ioa_Request.io_Device=NULL;
  697.             }
  698.             DeleteIORequest(RightAudio[i]);
  699.             RightAudio[i]=NULL;
  700.         }
  701.         
  702.         if (RightReply[i])
  703.         {
  704.             DeleteMsgPort(RightReply[i]);
  705.             RightReply[i]=NULL;
  706.         }
  707.         
  708.         if (LeftAudio[i])
  709.         {
  710.             if (i==0 && LeftAudio[i]->ioa_Request.io_Device)
  711.             {
  712.                 CloseDevice(LeftAudio[i]);
  713.                 LeftAudio[i]->ioa_Request.io_Device=NULL;
  714.             }
  715.             DeleteIORequest(LeftAudio[i]);
  716.             LeftAudio[i]=NULL;
  717.         }
  718.         
  719.         if (LeftReply[i])
  720.         {
  721.             DeleteMsgPort(LeftReply[i]);
  722.             LeftReply[i]=NULL;
  723.         }
  724.     }
  725.     
  726.     if (LoadHandle)
  727.     {
  728.         Close(LoadHandle);
  729.         LoadHandle=NULL;
  730.     }
  731.     
  732.     ChanInit=FALSE;
  733.     
  734.     return(0);
  735. }
  736.  
  737.  
  738. /****************************************************************************/
  739.  
  740. /* Initialize the "Module" */
  741.  
  742. ULONG __asm __saveds InitSound(void)
  743. {
  744.     ADPCMPosition = 0;
  745.     Loading = TRUE;
  746.     Signal((struct Task*)LoadProc, SIGBREAKF_CTRL_D);
  747.     
  748.     return(0);
  749. }
  750.  
  751.  
  752. /****************************************************************************/
  753.  
  754. /* End sound */
  755.  
  756. ULONG __asm __saveds EndSound(void)
  757. {
  758.     struct LoadBuffer *lb,*nextlb;
  759.     
  760.     LoadingStopped=FALSE;
  761.     
  762.     Loading=FALSE;
  763.     
  764.     Forbid();
  765.     
  766.     while (!LoadingStopped)
  767.     {
  768.         Signal((struct Task*)LoadProc, SIGBREAKF_CTRL_D);
  769.         Wait(SIGBREAKF_CTRL_D);
  770.     }
  771.     
  772.     Permit();
  773.     
  774.     ObtainSemaphore(&BufferSemaphore);
  775.     
  776.     for(    lb=(struct LoadBuffer*)BufferList.lh_Head ;
  777.             nextlb = (struct LoadBuffer*)lb->lb_Node.mln_Succ ;
  778.             lb = nextlb    )
  779.     {
  780.         Remove((struct Node*)lb);
  781.         NumBuffers--;
  782.         
  783.         if (lb->lb_ADPCMData)
  784.         {
  785.             FreeVec(lb->lb_ADPCMData);
  786.             lb->lb_ADPCMData=NULL;
  787.         }
  788.         
  789.         FreeVec(lb);
  790.         lb=NULL;
  791.     }
  792.     
  793.     ReleaseSemaphore(&BufferSemaphore);
  794.     
  795.     return(0);
  796. }
  797.  
  798.  
  799. /****************************************************************************/
  800.  
  801. /* Start sound */
  802.  
  803. ULONG __asm __saveds StartInt(void)
  804. {
  805.     PlayPosition=0;
  806.     Playing=TRUE;
  807.     
  808.     if (NumBuffers == QUEUE_LEN)
  809.     {
  810.         Signal(PlayerTask,(1L<<LeftReply[0]->mp_SigBit));
  811.         Signal(PlayerTask,(1L<<LeftReply[1]->mp_SigBit));
  812.     }
  813.     
  814.     return(0);
  815. }
  816.  
  817.  
  818. /****************************************************************************/
  819.  
  820. /* Stop sound */
  821.  
  822. ULONG __asm __saveds StopInt(void)
  823. {
  824.     UWORD i;
  825.     
  826.     Playing=FALSE;
  827.     
  828.     for (i=0;i<2;i++)
  829.     {
  830.         if (BufPlaying[i])
  831.         {
  832.             AbortIO(LeftAudio[i]);
  833.             AbortIO(RightAudio[i]);
  834.             WaitPort(LeftReply[i]);        GetMsg(LeftReply[i]);
  835.             WaitPort(RightReply[i]);    GetMsg(RightReply[i]);
  836.             BufPlaying[i]=FALSE;
  837.         }
  838.     }
  839.     
  840.     NoteInit=FALSE;
  841.     
  842.     return(0);
  843. }
  844.  
  845.  
  846. /****************************************************************************/
  847.  
  848. /* Play Faster */
  849.  
  850. ULONG __asm __saveds Faster(void)
  851. {
  852.     Frequency+=100;
  853.     
  854.     SetPerVol();
  855.     return(0);
  856. }
  857.  
  858.  
  859. /****************************************************************************/
  860.  
  861. /* Slower */
  862.  
  863. ULONG __asm __saveds Slower(void)
  864. {
  865.     Frequency-=100;
  866.     
  867.     SetPerVol();
  868.     return(0);
  869. }
  870.  
  871.  
  872. /****************************************************************************/
  873.  
  874. /* Volume and Balance */
  875.  
  876. ULONG __asm __saveds VolBalance(void)
  877. {
  878.     LeftVolume= DeliBase->SndVol*DeliBase->SndLBal/64;
  879.     RightVolume=DeliBase->SndVol*DeliBase->SndRBal/64;
  880.     
  881.     SetPerVol();
  882.     return(0);
  883. }
  884.  
  885.  
  886. /****************************************************************************/
  887.  
  888. /* Set Period and Volume */
  889.  
  890. void SetPerVol(void)
  891. {
  892.     UWORD i;
  893.     
  894.     UWORD Period= (*(struct ExecBase**)(4))->ex_EClockFrequency*5/Frequency;
  895.     
  896.     for (i=0;i<3;i++)
  897.     {
  898.         LeftAudio[i]->ioa_Period = 
  899.         RightAudio[i]->ioa_Period=Period;
  900.         
  901.         LeftAudio[i]->ioa_Volume=LeftVolume;
  902.         RightAudio[i]->ioa_Volume=RightVolume;
  903.     }
  904.     
  905.     LeftAudio[2]->ioa_Request.io_Command=
  906.     RightAudio[2]->ioa_Request.io_Command=ADCMD_PERVOL;
  907.     
  908.     DoIO((struct IORequest*)LeftAudio[2]);
  909.     DoIO((struct IORequest*)RightAudio[2]);
  910. }
  911.  
  912.  
  913. /*******************************************************************************/
  914.  
  915. /* Show a message to the user */
  916.  
  917. void __stdargs Message(UBYTE *Msg,...)
  918. {
  919.     va_list Arg;
  920.     struct EasyStruct Req={sizeof(struct EasyStruct),0,"ADPCM-Player message",0,"Okay"};
  921.     Req.es_TextFormat=Msg;
  922.     va_start(Arg,Msg);
  923.     
  924.     if (IntuitionBase)
  925.     {
  926.         EasyRequestArgs(NULL,&Req,0,Arg);
  927.     }
  928.     else
  929.     {
  930.         VPrintf(Msg,Arg);
  931.         Printf("\n");
  932.     }
  933.     
  934.     va_end(Arg);
  935. }
  936.