home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- *
- * VOC Datatype, based on the sourcecode found in OS3.1 Native Developer Kit
- *
- * Written by Christian Buchner
- *
- ******************************************************************************
- * dispatch.c
- */
-
- #include "classbase.h"
-
- /*****************************************************************************/
-
- #define DEBUG 0
-
- #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,"VOC 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 (VOCDTCLASS, SOUNDDTCLASS, NULL, NULL, 0L))
- {
- cl->cl_Dispatcher.h_Entry = (ULONG (*)())Dispatch;
- cl->cl_UserData = (ULONG) cb;
- AddClass (cl);
- }
-
- return (cl);
- }
-
- /*****************************************************************************/
-
- ULONG ASM Dispatch (REG (a0) Class * cl, REG (a2) Object * o, REG (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);
- }
-
- /*****************************************************************************/
-
- #define GETLONG(a) ( (*(a)) + (*(a+1)<<8) + (*(a+2)<<16) + (*(a+3)<<24) )
- #define GETTRIPLE(a) ( (*(a)) + (*(a+1)<<8) + (*(a+2)<<16) )
- #define GETWORD(a) ( (*(a)) + (*(a+1)<<8) )
-
- #define SWAPW(a) (WORD)(((UWORD)a>>8)+((((UWORD)a&0xff)<<8)))
- #define SWAPU(a) (UWORD)(((UWORD)a>>8)+((((UWORD)a&0xff)<<8)))
- #define SWAPL(a) (LONG)(((ULONG)a>>24)+(((ULONG)a&0xff0000)>>8)+(((ULONG)a&0xff00)<<8)+(((ULONG)a&0xff)<<24))
-
-
- /*****************************************************************************/
-
- #define ID_Terminator 0
- #define ID_Sounddata 1
- #define ID_Soundcontinue 2
- #define ID_Silence 3
- #define ID_Marker 4
- #define ID_ASCII 5
- #define ID_Repeat 6
- #define ID_Endrepeat 7
- #define ID_Extended 8
-
- /*****************************************************************************/
-
- struct SoundInfo
- {
- UBYTE soi_SampleRate;
- UBYTE soi_Compression;
- UBYTE soi_Data;
- };
-
- #define VOCFORMAT_8BIT 0
- #define VOCFORMAT_4BIT 1
- #define VOCFORMAT_26BIT 2
- #define VOCFORMAT_2BIT 3
- #define VOCFORMAT_MDAC 4
-
- struct SilenceInfo
- {
- UWORD sil_Length;
- UBYTE sil_SampleRate;
- };
-
- struct ExtendedInfo
- {
- UWORD exi_TimeConstant;
- UBYTE exi_Compression;
- UBYTE exi_Mode;
- };
-
- #define MODE_MONO 0
- #define MODE_STEREO 1
-
-
- /*****************************************************************************/
-
-
- /*****************************************************************************/
-
- BOOL ConvertObjectData (struct ClassBase * cb, Class * cl, Object * o, struct TagItem * attrs)
- {
- LONG ErrorCode=0;
- struct FileInfoBlock *fib;
- struct VoiceHeader *vhdr;
- STRPTR title;
- LONG size;
- ULONG len;
- BPTR fh;
- STRPTR buffer, ptr;
-
- UBYTE pass;
- UBYTE ID;
-
- ULONG Memory;
- ULONG SampleLength;
- ULONG SampleFreq;
- ULONG Frequency=10000;
- UBYTE Mode=MODE_MONO;
- UBYTE *Sample;
- UBYTE *Dest=0;
- ULONG DestLength;
-
- 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;
- DB(Error(cb,"not enough memory"));
- }
- 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));
-
- /* Buffered IO block */
- if (!(buffer = AllocVec (size, NULL)))
- {
- ErrorCode=ERROR_NO_FREE_STORE;
- DB(Error(cb,"not enough memory"));
- }
- else
- {
- /* Read the whole file into the buffer */
- if (Read (fh, buffer, size) != size)
- {
- DB(Error(cb,"couldn't read %ld bytes : error=%ld", size, IoErr ()));
- }
- else
- {
- if (strncmp(buffer, "Creative Voice File\32",20))
- {
- ErrorCode=ERROR_OBJECT_WRONG_TYPE;
- DB(Error(cb,"unknown format"));
- }
- else
- {
- /* 3-Pass loop over whole VOC Sample */
- /* 1. Pass: find out highest sample rate */
- /* 2. Pass: determine length of whole sample */
- /* 3. Pass: synthesize 8-Bit sample by using */
- /* highest samplerate */
-
- SampleFreq=0;
- SampleLength=0;
-
- for (pass=1;(!ErrorCode) && pass<=3;pass++)
- {
- /* get offset of the first data block to ptr */
-
- ptr=buffer+GETWORD(buffer+20);
-
- /* loop through cunks until end of buffer reached */
-
- while((!ErrorCode) && (ID=*ptr) && (ptr<buffer+size))
- {
- len=GETTRIPLE(ptr+1);
- ptr+=4;
-
- /* Handle the different chunks */
-
- switch(ID)
- {
- case ID_Sounddata:
- {
- struct SoundInfo *soi=(struct SoundInfo*)ptr;
- /* MUST be uncompressed 8 bit PCM data */
- if (soi->soi_Compression == VOCFORMAT_8BIT)
- {
- Mode=MODE_MONO; /* Force MONO mode */
- /* don't know whether this is correct */
- /* missing some documentation! */
- Frequency=1000000/(256-soi->soi_SampleRate);
- DestLength=ScaleLength(len-sizeof(struct SoundInfo),Frequency,SampleFreq);
- /* pass 1: Determine highest freq */
- if (pass==1) if (Frequency>SampleFreq) SampleFreq=Frequency;
- /* pass 2: calculate sample size */
- if (pass==2) SampleLength+=DestLength;
- /* pass 3: convert sample data */
- if (pass==3) Convert(ptr+sizeof(struct SoundInfo), &Dest, DestLength, Frequency, SampleFreq, Mode);
- }
- else
- {
- ErrorCode=DTERROR_UNKNOWN_COMPRESSION;
- DB(Error(cb,"unknown compression"));
- }
- }
- break;
-
- case ID_Soundcontinue:
- {
- /* Frequency and Mode may have been */
- /* initialized by ID_Extended */
- DestLength=ScaleLength(len,Frequency,SampleFreq);
- if (Mode==MODE_STEREO) DestLength/=2;
- /* pass 1: Determine highest freq */
- if (pass==1) if (Frequency>SampleFreq) SampleFreq=Frequency;
- /* pass 2: calculate sample size */
- if (pass==2) SampleLength+=DestLength;
- /* pass 3: convert sample data */
- if (pass==3) Convert(ptr, &Dest, DestLength, Frequency, SampleFreq, Mode);
- }
- break;
-
- case ID_Silence:
- {
- struct SilenceInfo *sil=(struct SilenceInfo*)ptr;
- Frequency=1000000/(256-sil->sil_SampleRate);
- DestLength=ScaleLength(((ULONG)(SWAPW(sil->sil_Length)+1)),Frequency,SampleFreq);
- /* pass 2: calculate sample size */
- if (pass==2) SampleLength+=DestLength;
- /* pass 3: just skip (leave silent) */
- if (pass==3) Dest+=DestLength;
- }
- break;
-
- case ID_Extended:
- {
- struct ExtendedInfo *exi=(struct ExtendedInfo*)ptr;
- if (exi->exi_Compression != VOCFORMAT_8BIT)
- {
- ErrorCode=DTERROR_UNKNOWN_COMPRESSION;
- DB(Error(cb,"unknown compression"));
- }
- else
- {
- if (exi->exi_Mode != MODE_MONO && exi->exi_Mode != MODE_STEREO)
- {
- ErrorCode=ERROR_OBJECT_WRONG_TYPE;
- DB(Error(cb,"unknown type"));
- }
- else
- {
- Mode=exi->exi_Mode;
- Frequency=256000000/(65536-SWAPW(exi->exi_TimeConstant));
- if (Mode==MODE_STEREO) Frequency/=2;
- }
- }
- }
-
- default:
- {
- DB(Error(cb,"unknown chunk: %ld, Len: %ld",(long)ID,len));
- }
- break;
-
- }
- ptr=ptr+len;
- }
- if (pass==2)
- {
- /* sound.datatype V40 can replay */
- /* directly from Fast RAM */
-
- Memory = (SuperClassBase->lib_Version>39) ?
- MEMF_ANY : MEMF_CHIP;
-
- if (Sample=AllocVec(SampleLength, Memory | MEMF_CLEAR))
- {
- /* Fill in the voice header */
-
- memset(vhdr,0,sizeof(struct VoiceHeader));
- vhdr->vh_OneShotHiSamples = SampleLength;
- vhdr->vh_SamplesPerSec = SampleFreq;
- 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, SampleLength,
- SDTA_Period, (ULONG)(SysBase->ex_EClockFrequency*5)/SampleFreq,
- SDTA_Volume, 64,
- SDTA_Cycles, 1,
- TAG_DONE);
-
- Dest=Sample;
- }
- else
- {
- ErrorCode=ERROR_NO_FREE_STORE;
- DB(Error(cb,"not enough memory"));
- }
- }
- }
- }
- }
- /* Free the buffer */
- FreeVec(buffer);
- }
- }
- }
- if (ErrorCode)
- {
- SetIoErr(ErrorCode);
- return(FALSE);
- }
- return(TRUE);
- }
-
-
- /*****************************************************************************/
-
- /* Convert the unsigned sample data to 8 bit signed PCM format */
- /* and do a time stretching if necessary */
- /* Destination pointer will be incremented */
- /* This one calls assembly routines for speed reasons */
-
- void Convert(UBYTE *Source, UBYTE **Dest, ULONG DestLength, ULONG SourceFreq, ULONG DestFreq, UBYTE Mode)
- {
- if (Mode==MODE_MONO)
- {
- ConvertMono8(Source, *Dest, DestLength, SourceFreq, DestFreq);
- }
- if (Mode==MODE_STEREO)
- {
- ConvertStereo8(Source, *Dest, DestLength, SourceFreq, DestFreq);
- }
- *Dest+=DestLength;
- }
-
- /*****************************************************************************/
-
- 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));
- }
-