home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / datatypes / fp_adpcm / adpcm_dt / source / dispatch.c < prev    next >
C/C++ Source or Header  |  1995-04-26  |  7KB  |  276 lines

  1. /******************************************************************************
  2.  *
  3.  * ADPCM Datatype, based on the sourcecode found in OS3.1 Native Developer Kit
  4.  *
  5.  * Written by Christian Buchner
  6.  *
  7.  ******************************************************************************
  8.  * dispatch.c
  9.  */
  10.  
  11. #include "classbase.h"
  12.  
  13. /*****************************************************************************/
  14.  
  15. #define TARGET_SIZE 16384
  16.  
  17. extern __asm ULONG DecompressADPCM2(    register __a0 UBYTE *Source,
  18.                                         register __d0 ULONG Length,
  19.                                         register __a1 UBYTE *Destination,
  20.                                         register __d1 ULONG JoinCode    );
  21.  
  22. extern __asm ULONG DecompressADPCM3(    register __a0 UBYTE *Source,
  23.                                         register __d0 ULONG Length,
  24.                                         register __a1 UBYTE *Destination,
  25.                                         register __d1 ULONG JoinCode    );
  26.  
  27. /*****************************************************************************/
  28.  
  29. #define DEBUG 1
  30.  
  31. #if DEBUG
  32.  
  33. #define    DB(x)    x
  34.  
  35. #include <stdarg.h>
  36. void __stdargs Error(struct ClassBase *cb,UBYTE *Msg,...)
  37. {
  38.     va_list Arg;
  39.     struct EasyStruct Req={sizeof(struct EasyStruct),0,"ADPCM debug message",0,"Okay"};
  40.     va_start(Arg,Msg);
  41.     Req.es_TextFormat=Msg;
  42.     EasyRequestArgs(NULL,&Req,0,Arg);
  43.     va_end(Arg);
  44. }
  45.  
  46. #else
  47.  
  48. #define    DB(x)    
  49.  
  50. #endif
  51.  
  52.  
  53.  
  54. /*****************************************************************************/
  55.  
  56. Class *initClass (struct ClassBase * cb)
  57. {
  58.     Class *cl;
  59.     
  60.     if (cl = MakeClass (LibName, SOUNDDTCLASS, NULL, NULL, 0L))
  61.     {
  62.         cl->cl_Dispatcher.h_Entry = (ULONG (*)())Dispatch;
  63.         cl->cl_UserData = (ULONG) cb;
  64.         AddClass (cl);
  65.     }
  66.     
  67.     return (cl);
  68. }
  69.  
  70. /*****************************************************************************/
  71.  
  72. ULONG __asm Dispatch (register __a0 Class * cl, register __a2 Object * o, register __a1 Msg msg)
  73. {
  74.     struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
  75.     ULONG retval = 0L;
  76.     
  77.     switch (msg->MethodID)
  78.     {
  79.     case OM_NEW:
  80.         if (retval = DoSuperMethodA (cl, o, msg))
  81.         {
  82.             if (!(ConvertObjectData (cb, cl, (Object *) retval, ((struct opSet *) msg)->ops_AttrList)))
  83.             {
  84.                 CoerceMethod (cl, (Object *) retval, OM_DISPOSE);
  85.                 retval = NULL;
  86.             }
  87.         }
  88.         break;
  89.         
  90.      /* Let the superclass handle everything else */
  91.     
  92.     default:
  93.         retval = (ULONG) DoSuperMethodA (cl, o, msg);
  94.         break;
  95.     }
  96.     
  97.     return (retval);
  98. }
  99.  
  100. /*****************************************************************************/
  101.  
  102. struct ADPCMHeader
  103. {
  104.     UBYTE Identifier[6];    /* $00 */
  105.     ULONG Frequency;        /* $06 */
  106. };
  107.  
  108. /*****************************************************************************/
  109.  
  110. BOOL ConvertObjectData (struct ClassBase * cb, Class * cl, Object * o, struct TagItem * attrs)
  111. {
  112.     LONG ErrorCode=0;
  113.     struct FileInfoBlock *fib;
  114.     struct VoiceHeader *vhdr;
  115.     STRPTR Title;
  116.     BPTR FH;
  117.     struct ADPCMHeader ADPCMHeader;
  118.     ULONG Memory;
  119.     UBYTE *Sample;
  120.     ULONG Size;
  121.     ULONG SampleSize;
  122.     
  123.     Title = (STRPTR) GetTagData (DTA_Name, NULL, attrs);
  124.     
  125.     getdtattrs (cb, o,
  126.         SDTA_VoiceHeader, &vhdr,
  127.         DTA_Handle, &FH,
  128.         TAG_DONE);
  129.     
  130.     if (FH && vhdr)
  131.     {
  132.         /* Allocate a temporary file info block */
  133.         if (!(fib = (struct FileInfoBlock *) AllocMem (sizeof (struct FileInfoBlock), NULL)))
  134.         {
  135.             ErrorCode=ERROR_NO_FREE_STORE;
  136.         }
  137.         else
  138.         {
  139.             /* Get the size of the file */
  140.             if (ExamineFH (FH, fib))
  141.             {
  142.                 Size = fib->fib_Size;
  143.             }
  144.             else
  145.             {
  146.                 Seek (FH, 0, OFFSET_END);
  147.                 Size = Seek (FH, 0, OFFSET_BEGINNING);
  148.             }
  149.             
  150.             /* Free the temporary file info block */
  151.             FreeMem (fib, sizeof (struct FileInfoBlock));
  152.             
  153.             /* Calculate size from actual file length */
  154.             Size-=sizeof(struct ADPCMHeader);
  155.             
  156.             /* Read in sample header */
  157.             if (Read(FH,&ADPCMHeader,sizeof(struct ADPCMHeader))==sizeof(struct ADPCMHeader))
  158.             {
  159.                 /* Check if it is a supported ADPCM format */
  160.                 if (ADPCMHeader.Identifier[5] != '2' && ADPCMHeader.Identifier[5] != '3')
  161.                 {
  162.                     ErrorCode=ERROR_OBJECT_WRONG_TYPE;
  163.                 }
  164.                 else
  165.                 {
  166.                     ULONG Bits;
  167.                     
  168.                     /* Retrieve the number of compression bits */
  169.                     if (ADPCMHeader.Identifier[5] == '2') Bits=2;
  170.                     if (ADPCMHeader.Identifier[5] == '3') Bits=3;
  171.                     
  172.                     /* Calculate the real sample size */
  173.                     if (Bits==2) SampleSize=Size*4 ;
  174.                     if (Bits==3) SampleSize=Size*8/3;
  175.                     
  176.                     /* sound.datatype V40 can replay */
  177.                     /* directly from Fast RAM */
  178.                     
  179.                     Memory = (SuperClassBase->lib_Version>39) ?
  180.                                 MEMF_ANY : MEMF_CHIP;
  181.                     
  182.                     /* Allocate a buffer with the calculated size */
  183.                     if (!(Sample=AllocVec(SampleSize,Memory)))
  184.                     {
  185.                         ErrorCode=ERROR_NO_FREE_STORE;
  186.                     }
  187.                     else
  188.                     {
  189.                         UBYTE *ADPCMBuffer;
  190.                         ULONG ADPCMSize;
  191.                         
  192.                         if (Bits==2) ADPCMSize=(TARGET_SIZE+3)/4;
  193.                         if (Bits==3) ADPCMSize=(TARGET_SIZE+7)/8*3;
  194.                         
  195.                         if (ADPCMBuffer=AllocVec(ADPCMSize, MEMF_ANY))
  196.                         {
  197.                             ULONG Position,SampleOffset;
  198.                             ULONG JoinCode=0;
  199.                             
  200.                             for (Position=0,SampleOffset=0; Position<Size; )
  201.                             {
  202.                                 ULONG Left=Size-Position;
  203.                                 ULONG Do = Left < ADPCMSize ?
  204.                                            Left : ADPCMSize ;
  205.                                 LONG Got;
  206.                                 
  207.                                 if (Got=Read(FH, ADPCMBuffer, Do) != Do)
  208.                                 {
  209.                                     if (Got<0) ErrorCode=IoErr();
  210.                                     else ErrorCode=ERROR_BAD_HUNK;
  211.                                     break;
  212.                                 }
  213.                                 
  214.                                 if (Bits==2) JoinCode=DecompressADPCM2(ADPCMBuffer, Do, Sample+SampleOffset, JoinCode);
  215.                                 if (Bits==3) JoinCode=DecompressADPCM3(ADPCMBuffer, Do, Sample+SampleOffset, JoinCode);
  216.                                 
  217.                                 Position+=Do;
  218.                                 
  219.                                 if (Bits==2) SampleOffset+=Do*4;
  220.                                 if (Bits==3) SampleOffset+=Do*8/3;
  221.                             }
  222.                             
  223.                             if (!ErrorCode)
  224.                             {
  225.                                 /* Fill in the VoiceHeader */
  226.                                 memset(vhdr,0,sizeof(struct VoiceHeader));
  227.                                 vhdr->vh_OneShotHiSamples    = Size;
  228.                                 vhdr->vh_SamplesPerSec        = ADPCMHeader.Frequency;
  229.                                 vhdr->vh_Octaves            = 1;
  230.                                 vhdr->vh_Compression        = CMP_NONE;
  231.                                 vhdr->vh_Volume                = 64;
  232.                                 
  233.                                 /* Tell the super-class about the attributes */
  234.                                 setdtattrs (cb, o,
  235.                                     DTA_ObjName,        Title,
  236.                                     SDTA_Sample,        Sample,
  237.                                     SDTA_SampleLength,    SampleSize,
  238.                                     SDTA_Period,        (ULONG)(SysBase->ex_EClockFrequency*5)/(ULONG)vhdr->vh_SamplesPerSec,
  239.                                     SDTA_Volume,        64,
  240.                                     SDTA_Cycles,        1,
  241.                                     TAG_DONE);
  242.                             }
  243.                             else
  244.                             {
  245.                                 FreeVec(Sample);
  246.                             }
  247.                             FreeVec(ADPCMBuffer);
  248.                         }
  249.                     }
  250.                 }
  251.             }
  252.         }
  253.     }
  254.     if (ErrorCode)
  255.     {
  256.         SetIoErr(ErrorCode);
  257.         return(FALSE);
  258.     }
  259.     return(TRUE);
  260. }
  261.  
  262.  
  263. /*****************************************************************************/
  264.  
  265. ULONG setdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
  266. {
  267.     return (SetDTAttrsA (o, NULL, NULL, (struct TagItem *) & data));
  268. }
  269.  
  270. /*****************************************************************************/
  271.  
  272. ULONG getdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
  273. {
  274.     return (GetDTAttrsA (o, (struct TagItem *) & data));
  275. }
  276.