home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1998 #6
/
amigamamagazinepolishissue1998.iso
/
packery
/
fp_adpcm
/
adpcm_dt
/
source
/
dispatch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1977-12-31
|
7KB
|
276 lines
/******************************************************************************
*
* ADPCM Datatype, based on the sourcecode found in OS3.1 Native Developer Kit
*
* Written by Christian Buchner
*
******************************************************************************
* dispatch.c
*/
#include "classbase.h"
/*****************************************************************************/
#define TARGET_SIZE 16384
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 );
/*****************************************************************************/
#define DEBUG 1
#if DEBUG
#define DB(x) x
#include <stdarg.h>
void __stdargs Error(struct ClassBase *cb,UBYTE *Msg,...)
{
va_list Arg;
struct EasyStruct Req={sizeof(struct EasyStruct),0,"ADPCM debug message",0,"Okay"};
va_start(Arg,Msg);
Req.es_TextFormat=Msg;
EasyRequestArgs(NULL,&Req,0,Arg);
va_end(Arg);
}
#else
#define DB(x)
#endif
/*****************************************************************************/
Class *initClass (struct ClassBase * cb)
{
Class *cl;
if (cl = MakeClass (LibName, SOUNDDTCLASS, NULL, NULL, 0L))
{
cl->cl_Dispatcher.h_Entry = (ULONG (*)())Dispatch;
cl->cl_UserData = (ULONG) cb;
AddClass (cl);
}
return (cl);
}
/*****************************************************************************/
ULONG __asm Dispatch (register __a0 Class * cl, register __a2 Object * o, register __a1 Msg msg)
{
struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
ULONG retval = 0L;
switch (msg->MethodID)
{
case OM_NEW:
if (retval = DoSuperMethodA (cl, o, msg))
{
if (!(ConvertObjectData (cb, cl, (Object *) retval, ((struct opSet *) msg)->ops_AttrList)))
{
CoerceMethod (cl, (Object *) retval, OM_DISPOSE);
retval = NULL;
}
}
break;
/* Let the superclass handle everything else */
default:
retval = (ULONG) DoSuperMethodA (cl, o, msg);
break;
}
return (retval);
}
/*****************************************************************************/
struct ADPCMHeader
{
UBYTE Identifier[6]; /* $00 */
ULONG Frequency; /* $06 */
};
/*****************************************************************************/
BOOL ConvertObjectData (struct ClassBase * cb, Class * cl, Object * o, struct TagItem * attrs)
{
LONG ErrorCode=0;
struct FileInfoBlock *fib;
struct VoiceHeader *vhdr;
STRPTR Title;
BPTR FH;
struct ADPCMHeader ADPCMHeader;
ULONG Memory;
UBYTE *Sample;
ULONG Size;
ULONG SampleSize;
Title = (STRPTR) GetTagData (DTA_Name, NULL, attrs);
getdtattrs (cb, o,
SDTA_VoiceHeader, &vhdr,
DTA_Handle, &FH,
TAG_DONE);
if (FH && vhdr)
{
/* Allocate a temporary file info block */
if (!(fib = (struct FileInfoBlock *) AllocMem (sizeof (struct FileInfoBlock), NULL)))
{
ErrorCode=ERROR_NO_FREE_STORE;
}
else
{
/* Get the size of the file */
if (ExamineFH (FH, fib))
{
Size = fib->fib_Size;
}
else
{
Seek (FH, 0, OFFSET_END);
Size = Seek (FH, 0, OFFSET_BEGINNING);
}
/* Free the temporary file info block */
FreeMem (fib, sizeof (struct FileInfoBlock));
/* Calculate size from actual file length */
Size-=sizeof(struct ADPCMHeader);
/* Read in sample header */
if (Read(FH,&ADPCMHeader,sizeof(struct ADPCMHeader))==sizeof(struct ADPCMHeader))
{
/* Check if it is a supported ADPCM format */
if (ADPCMHeader.Identifier[5] != '2' && ADPCMHeader.Identifier[5] != '3')
{
ErrorCode=ERROR_OBJECT_WRONG_TYPE;
}
else
{
ULONG Bits;
/* Retrieve the number of compression bits */
if (ADPCMHeader.Identifier[5] == '2') Bits=2;
if (ADPCMHeader.Identifier[5] == '3') Bits=3;
/* Calculate the real sample size */
if (Bits==2) SampleSize=Size*4 ;
if (Bits==3) SampleSize=Size*8/3;
/* sound.datatype V40 can replay */
/* directly from Fast RAM */
Memory = (SuperClassBase->lib_Version>39) ?
MEMF_ANY : MEMF_CHIP;
/* Allocate a buffer with the calculated size */
if (!(Sample=AllocVec(SampleSize,Memory)))
{
ErrorCode=ERROR_NO_FREE_STORE;
}
else
{
UBYTE *ADPCMBuffer;
ULONG ADPCMSize;
if (Bits==2) ADPCMSize=(TARGET_SIZE+3)/4;
if (Bits==3) ADPCMSize=(TARGET_SIZE+7)/8*3;
if (ADPCMBuffer=AllocVec(ADPCMSize, MEMF_ANY))
{
ULONG Position,SampleOffset;
ULONG JoinCode=0;
for (Position=0,SampleOffset=0; Position<Size; )
{
ULONG Left=Size-Position;
ULONG Do = Left < ADPCMSize ?
Left : ADPCMSize ;
LONG Got;
if (Got=Read(FH, ADPCMBuffer, Do) != Do)
{
if (Got<0) ErrorCode=IoErr();
else ErrorCode=ERROR_BAD_HUNK;
break;
}
if (Bits==2) JoinCode=DecompressADPCM2(ADPCMBuffer, Do, Sample+SampleOffset, JoinCode);
if (Bits==3) JoinCode=DecompressADPCM3(ADPCMBuffer, Do, Sample+SampleOffset, JoinCode);
Position+=Do;
if (Bits==2) SampleOffset+=Do*4;
if (Bits==3) SampleOffset+=Do*8/3;
}
if (!ErrorCode)
{
/* Fill in the VoiceHeader */
memset(vhdr,0,sizeof(struct VoiceHeader));
vhdr->vh_OneShotHiSamples = Size;
vhdr->vh_SamplesPerSec = ADPCMHeader.Frequency;
vhdr->vh_Octaves = 1;
vhdr->vh_Compression = CMP_NONE;
vhdr->vh_Volume = 64;
/* Tell the super-class about the attributes */
setdtattrs (cb, o,
DTA_ObjName, Title,
SDTA_Sample, Sample,
SDTA_SampleLength, SampleSize,
SDTA_Period, (ULONG)(SysBase->ex_EClockFrequency*5)/(ULONG)vhdr->vh_SamplesPerSec,
SDTA_Volume, 64,
SDTA_Cycles, 1,
TAG_DONE);
}
else
{
FreeVec(Sample);
}
FreeVec(ADPCMBuffer);
}
}
}
}
}
}
if (ErrorCode)
{
SetIoErr(ErrorCode);
return(FALSE);
}
return(TRUE);
}
/*****************************************************************************/
ULONG setdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
{
return (SetDTAttrsA (o, NULL, NULL, (struct TagItem *) & data));
}
/*****************************************************************************/
ULONG getdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
{
return (GetDTAttrsA (o, (struct TagItem *) & data));
}