/**************************************************************************** | Digital Audio Processor | ======================= | | Filename : audiofile.c | | Object : None | | Description : Audiofile replacement code for linux | | (c) Richard Kent 1997 | | $Id: audiofile.c,v 1.1 2003/09/10 00:06:24 rk Exp $ | ****************************************************************************/ static char audiofile_c [] = "$Id: audiofile.c,v 1.1 2003/09/10 00:06:24 rk Exp $"; #include "audiofile.h" #include "raw.h" #include "wav.h" #include "macros.h" #ifndef LINUX #include #endif // Limitations :- // Only one track (AF_DEFAULT_TRACK) permitted // Only one instrument (AF_DEFAULT_INST) permitted // Only two's complement samples // No built in compression codecs (must be AF_COMPRESSION_NONE) // Maximum 65535 markers // Maximum 2 loops // Only one ANNO chunk // Only one MIDI chunk // Only one APPL chunk // // Advantages :- // Supports WAV and RAW formats (although you may lose details // such as loop points, textual details, etc) due to limitations // implicit in these sample formats - tough !! AFerrfunc audioFileErrorFunction = 0; /*--------------------------------------------------------------------------- | FUNCTION AFsetsampleformat ---------------------------------------------------------------------------*/ void AFsetsampleformat (AFfilesetup setup, int sampleFormat) { if (!setup) return; if (sampleFormat == AF_FORMAT_AIFF || sampleFormat == AF_FORMAT_WAV || sampleFormat == AF_FORMAT_RAW) setup->sampleFormat = sampleFormat; } /*--------------------------------------------------------------------------- | FUNCTION AFgetsampleformat ---------------------------------------------------------------------------*/ int AFgetsampleformat (AFfilesetup setup) { if (!setup) return AF_FORMAT_AIFF; return setup->sampleFormat; } /*--------------------------------------------------------------------------- | FUNCTION AFsetrawchannels ---------------------------------------------------------------------------*/ void AFsetrawchannels (AFfilesetup setup, int channels) { if (!setup) return; if (channels == 1 || channels == 2 || channels == 4) setup->rawDetails.channels = channels; } /*--------------------------------------------------------------------------- | FUNCTION AFgetrawchannels ---------------------------------------------------------------------------*/ int AFgetrawchannels (AFfilesetup setup) { if (!setup) return 1; return setup->rawDetails.channels; } /*--------------------------------------------------------------------------- | FUNCTION AFsetrawdataformat ---------------------------------------------------------------------------*/ void AFsetrawdataformat (AFfilesetup setup, int dataFormat) { if (!setup) return; if (dataFormat == AF_BYTE_FORMAT || dataFormat == AF_SHORT_FORMAT || dataFormat == AF_LONG24_FORMAT || dataFormat == AF_LONG32_FORMAT || dataFormat == AF_FLOAT_FORMAT || dataFormat == AF_DOUBLE_FORMAT) setup->rawDetails.dataFormat = dataFormat; } /*--------------------------------------------------------------------------- | FUNCTION AFgetrawdataformat ---------------------------------------------------------------------------*/ int AFgetrawdataformat (AFfilesetup setup) { if (!setup) return AF_BYTE_FORMAT; return setup->rawDetails.dataFormat; } /*--------------------------------------------------------------------------- | FUNCTION AFsetrawsigneddata ---------------------------------------------------------------------------*/ void AFsetrawsigneddata (AFfilesetup setup, int signedData) { if (!setup) return; if (signedData == AF_SIGNED_FORMAT || signedData == AF_UNSIGNED_FORMAT) setup->rawDetails.signedData = signedData; } /*--------------------------------------------------------------------------- | FUNCTION AFgetrawsigneddata ---------------------------------------------------------------------------*/ int AFgetrawsigneddata (AFfilesetup setup) { if (!setup) return TRUE; return setup->rawDetails.signedData; } /*--------------------------------------------------------------------------- | FUNCTION AFsetrawendian ---------------------------------------------------------------------------*/ void AFsetrawendian (AFfilesetup setup, int endian) { if (!setup) return; if (endian == AF_DEF_ENDIAN_FORMAT || endian == AF_BIG_ENDIAN_FORMAT || endian == AF_LITTLE_ENDIAN_FORMAT) setup->rawDetails.endian = endian; } /*--------------------------------------------------------------------------- | FUNCTION AFgetrawendian ---------------------------------------------------------------------------*/ int AFgetrawendian (AFfilesetup setup) { if (!setup) return AF_DEF_ENDIAN_FORMAT; return setup->rawDetails.endian; } /*--------------------------------------------------------------------------- | FUNCTION AFseterrorhandler ---------------------------------------------------------------------------*/ AFerrfunc AFseterrorhandler (AFerrfunc efunc) { AFerrfunc temp; temp = audioFileErrorFunction; audioFileErrorFunction = efunc; return temp; } /*--------------------------------------------------------------------------- | FUNCTION AFnewfilesetup ---------------------------------------------------------------------------*/ AFfilesetup AFnewfilesetup (void) { AFfilesetup setup; setup = (aiffType *) calloc (1,sizeof (aiffType)); initialiseSetup (setup); return setup; } /*--------------------------------------------------------------------------- | FUNCTION AFfreefilesetup ---------------------------------------------------------------------------*/ void AFfreefilesetup (AFfilesetup setup) { if (!setup) return; freeSetup (setup); free (setup); } /*--------------------------------------------------------------------------- | FUNCTION AFinitfilefmt ---------------------------------------------------------------------------*/ void AFinitfilefmt (AFfilesetup setup,int fmt) { if (!setup) return; if (fmt == AF_FILE_AIFFC || fmt == AF_FILE_AIFF) setup->filefmt = fmt; } /*--------------------------------------------------------------------------- | FUNCTION AFinitrate ---------------------------------------------------------------------------*/ void AFinitrate (AFfilesetup setup,int trackid,double rate) { if (!setup) return; if (trackid == AF_DEFAULT_TRACK) if (rate > 0.0) setup->rate = rate; } /*--------------------------------------------------------------------------- | FUNCTION AFinitsampfmt ---------------------------------------------------------------------------*/ void AFinitsampfmt (AFfilesetup setup,int trackid,int fmt,int width) { if (!setup) return; if (trackid == AF_DEFAULT_TRACK) { if (fmt == AF_SAMPFMT_TWOSCOMP) setup->sampfmt = fmt; if (width >= 1 && width <= 32) setup->width = width; } } /*--------------------------------------------------------------------------- | FUNCTION AFinitchannels ---------------------------------------------------------------------------*/ void AFinitchannels (AFfilesetup setup,int trackid,int channels) { if (!setup) return; if (trackid == AF_DEFAULT_TRACK) if (channels == 1 || channels == 2 || channels == 4) setup->channels = channels; } /*--------------------------------------------------------------------------- | FUNCTION AFinitaeschanneldata ---------------------------------------------------------------------------*/ void AFinitaeschanneldata (AFfilesetup setup,int trackid) { if (!setup) return; if (trackid == AF_DEFAULT_TRACK) setup->aesdatapresent = 1; } /*--------------------------------------------------------------------------- | FUNCTION AFsetaeschanneldata ---------------------------------------------------------------------------*/ void AFsetaeschanneldata ( AFfilehandle file, int trackid, unsigned char buf [24]) { int i; if (!file) return; if (trackid == AF_DEFAULT_TRACK) for (i=0; i<24; i++) file->aiff.aesdata [i] = buf [i]; } /*--------------------------------------------------------------------------- | FUNCTION AFinitcompression ---------------------------------------------------------------------------*/ void AFinitcompression (AFfilesetup setup,int trackid,int compression) { if (!setup) return; if (trackid == AF_DEFAULT_TRACK) if (compression == AF_COMPRESSION_NONE) setup->compression = compression; } /*--------------------------------------------------------------------------- | FUNCTION AFinitmarkids ---------------------------------------------------------------------------*/ void AFinitmarkids ( AFfilesetup setup, int trackid, long *markids, int nmarks) { int i; if (!setup) return; if (trackid == AF_DEFAULT_TRACK) { if (nmarks >= 0 && nmarks <= 65535) { if (setup->mark) { for (i=0; imarks; i++) if (setup->mark [i].name) free (setup->mark [i].name); free (setup->mark); } if (!nmarks || !markids) { setup->marks = 0; setup->mark = 0; } else { setup->marks = nmarks; setup->mark = (markType *) calloc (nmarks,sizeof (markType)); for (i=0; imark [i].id = markids [i]; setup->mark [i].name = 0; setup->mark [i].position = 0; } } } } } /*--------------------------------------------------------------------------- | FUNCTION AFinitmarkname ---------------------------------------------------------------------------*/ void AFinitmarkname ( AFfilesetup setup, int trackid, int markid, const char *name) { int i; if (!setup) return; if (trackid == AF_DEFAULT_TRACK) { for (i=0; imarks; i++) { if (setup->mark [i].id == markid) { if (setup->mark [i].name) free (setup->mark [i].name); if (name) { setup->mark [i].name = (char *) calloc (strlen (name) + 1,sizeof (char)); strcpy (setup->mark [i].name,name); } else { setup->mark [i].name = 0; } } } } } /*--------------------------------------------------------------------------- | FUNCTION AFinitinstids ---------------------------------------------------------------------------*/ void AFinitinstids (AFfilesetup setup,long *instids,int ninsts) { int i; if (!setup) return; if (ninsts >= 0 && ninsts <= 1) { if (setup->inst) free (setup->inst); if (!ninsts || !instids || instids [0] != AF_DEFAULT_INST) { setup->insts = 0; setup->inst = 0; } else { setup->insts = ninsts; setup->inst = (instType *) calloc (ninsts,sizeof (instType)); for (i=0; iinst [i].id = instids [i]; setup->inst [i].midibasenote = 60; setup->inst [i].midihinote = 127; setup->inst [i].midihivelocity = 127; setup->inst [i].midilonote = 0; setup->inst [i].midilovelocity = 1; setup->inst [i].numcentsdetune = 0; setup->inst [i].numdbsgain = 0; setup->inst [i].susloopid = 1; setup->inst [i].relloopid = 2; } } } } /*--------------------------------------------------------------------------- | FUNCTION AFinitloopids ---------------------------------------------------------------------------*/ void AFinitloopids (AFfilesetup setup,int instid,long *loopids,int nloops) { int i; if (!setup) return; if (instid == AF_DEFAULT_INST) { if (nloops >= 0 && nloops <= 2) { if (setup->loop) free (setup->loop); if (!nloops || !loopids) { setup->loops = 0; setup->loop = 0; } else { setup->loops = nloops; setup->loop = (loopType *) calloc (nloops,sizeof (loopType)); for (i=0; iloop [i].id = loopids [i]; setup->loop [i].mode = AF_LOOP_MODE_NOLOOP; setup->loop [i].start = (2 * i) + 1; setup->loop [i].end = (2 * i) + 2; } } } } } /*--------------------------------------------------------------------------- | FUNCTION AFinitmiscids ---------------------------------------------------------------------------*/ void AFinitmiscids (AFfilesetup setup,long *miscids,int nmiscs) { int i; if (!setup) return; if (nmiscs >= 0) { if (setup->misc) { for (i=0; imiscs; i++) if (setup->misc [i].data) free (setup->misc [i].data); free (setup->misc); } if (!nmiscs || !miscids) { setup->miscs = 0; setup->misc = 0; } else { setup->miscs = nmiscs; setup->misc = (miscType *) calloc (nmiscs,sizeof (miscType)); for (i=0; imisc [i].id = miscids [i]; setup->misc [i].type = AF_MISC_AIFF_ANNO; setup->misc [i].size = 0; setup->misc [i].current = 0; setup->misc [i].data = 0; } } } } /*--------------------------------------------------------------------------- | FUNCTION AFinitmisctype ---------------------------------------------------------------------------*/ void AFinitmisctype (AFfilesetup setup,int miscid,int type) { int i; if (!setup) return; for (i=0; imiscs; i++) { if (setup->misc [i].id == miscid) if (type == AF_MISC_AIFF_ANNO || type == AF_MISC_AIFF_APPL || type == AF_MISC_AIFF_AUTH || type == AF_MISC_AIFF_COPY || type == AF_MISC_AIFF_MIDI || type == AF_MISC_AIFF_NAME) setup->misc [i].type = type; } } /*--------------------------------------------------------------------------- | FUNCTION AFinitmiscsize ---------------------------------------------------------------------------*/ void AFinitmiscsize (AFfilesetup setup,int miscid,int size) { int i; if (!setup) return; for (i=0; imiscs; i++) { if (setup->misc [i].id == miscid) { if (size >= 0) { if (setup->misc [i].data) free (setup->misc [i].data); setup->misc [i].size = size; if (size) setup->misc [i].data = (char *) calloc (size,sizeof (char)); else setup->misc [i].data = 0; } } } } /*--------------------------------------------------------------------------- | FUNCTION AUchecklicense ---------------------------------------------------------------------------*/ int AUchecklicense (int product,int *errorval,char **message) { if (product == AU_LICENSE_AWARE_MPEG_ENCODER || product == AU_LICENSE_AWARE_MPEG_DECODER || product == AU_LICENSE_AWARE_MULTIRATE_ENCODER || product == AU_LICENSE_AWARE_MULTIRATE_DECODER) { *errorval = 0; *message = "License not available"; return AU_LICENSE_ERR; } else { return AU_BAD_PRODUCT; } /* return AU_LICENSE_OK; */ } /*--------------------------------------------------------------------------- | FUNCTION AFopenfile ---------------------------------------------------------------------------*/ AFfilehandle AFopenfile ( const char *name, const char *mode, AFfilesetup setup) { FHandle file; AFfilehandle tempHandle; if (!mode) return AF_NULL_FILEHANDLE; if (!strcmp (mode,"r")) { file = mOpenRead (name); if (!mCheckFile (file)) return AF_NULL_FILEHANDLE; if ((tempHandle = AFopenfd (file,mode,setup)) == AF_NULL_FILEHANDLE) mClose (file); } else if (!strcmp (mode,"w")) { file = mOpenWrite (name); if (!mCheckFile (file)) return AF_NULL_FILEHANDLE; if ((tempHandle = AFopenfd (file,mode,setup)) == AF_NULL_FILEHANDLE) mClose (file); } else { return AF_NULL_FILEHANDLE; } return tempHandle; } /*--------------------------------------------------------------------------- | FUNCTION AFopenfd ---------------------------------------------------------------------------*/ AFfilehandle AFopenfd (FHandle file,const char *mode,AFfilesetup setup) { if (!mode) return AF_NULL_FILEHANDLE; if (!strcmp (mode,"r")) { // Read mode - if setup check for type to load - otherwise AIFF if (!setup || setup->sampleFormat == AF_FORMAT_AIFF) { // AIFF files are always little endian setBigEndian (FALSE); return AFreadAIFF (file); } else if (setup->sampleFormat == AF_FORMAT_WAV) { // WAV files are always big endian setBigEndian (TRUE); return AFreadWAV (file); } else if (setup->sampleFormat == AF_FORMAT_RAW) { AFfilehandle handle; // RAW files can be big or little setEndian (setup->rawDetails.endian); handle = AFreadRAW (file,setup->rawDetails); return handle; } else { return AF_NULL_FILEHANDLE; } } else if (!strcmp (mode,"w")) { // Write mode - must have setup to check for type to load if (!setup) return AF_NULL_FILEHANDLE; if (setup->sampleFormat == AF_FORMAT_AIFF) { // AIFF files are always little endian setBigEndian (FALSE); return AFwriteAIFF (file,setup); } else if (setup->sampleFormat == AF_FORMAT_WAV) { // WAV files are always big endian setBigEndian (TRUE); return AFwriteWAV (file,setup); } else if (setup->sampleFormat == AF_FORMAT_RAW) { // RAW files can be big or little setEndian (setup->rawDetails.endian); return AFwriteRAW (file,setup); } else { return AF_NULL_FILEHANDLE; } } else { // Neither read nor write specified return AF_NULL_FILEHANDLE; } } /*--------------------------------------------------------------------------- | FUNCTION AFreadAIFF ---------------------------------------------------------------------------*/ AFfilehandle AFreadAIFF (FHandle file) { int i; int j; aiffHandle handleAct; AFfilehandle handle = &handleAct; char id [4]; int chunksize; int seeksize; int itemp; unsigned int uitemp; short stemp; unsigned short ustemp; signed char ctemp; unsigned char uctemp; double dtemp; char idtemp [4]; char *tempstring; unsigned int offset; unsigned int blocksize; int done = FALSE; int error = FALSE; int fver = FALSE; int comm = FALSE; int ssnd = FALSE; int mark = FALSE; int comt = FALSE; int inst = FALSE; int aesd = FALSE; int name = FALSE; int auth = FALSE; int copy = FALSE; int anno = FALSE; int midi = FALSE; int appl = FALSE; handle->mode = READONLY; handle->file = file; handle->actualBytes = 0; handle->actualFrames = 0; handle->ssndStart = 0; // Setup defaults in handle->aiff blankSetup (&(handle->aiff)); // Read info from file into handle->aiff if (!file) return AF_NULL_FILEHANDLE; // Check FORM chunk if (!idRead (file,id) || strncmp (id,"FORM",4)) fail ("AIFF header does not begin with magic word 'FORM'\n") if (!iRead (file,&(handle->actualBytes))) fail ("No overall chunk size\n") if (!idRead (file,id)) fail ("AIFF header does not contain a form type\n") if (!strncmp (id,"AIFF",4)) handle->aiff.filefmt = AF_FILE_AIFF; else if (!strncmp (id,"AIFC",4)) handle->aiff.filefmt = AF_FILE_AIFFC; else fail ("AIFF header does not contain a valid form type\n") while (!done && !error && !mEof (file)) { if (!idRead (file,id)) { // message ("done\n"); done = TRUE; break; } else if (!strncmp (id,"FVER",4)) { // fver // message ("fver\n"); if (fver) aiffError iread (chunksize) if (chunksize != 4) aiffError uiread (handle->aiff.version) fver = TRUE; } else if (!strncmp (id,"COMM",4)) { // comm // message ("comm\n"); if (comm) aiffError iread (chunksize) if (handle->aiff.filefmt == AF_FILE_AIFF && chunksize != 18) aiffError sread (handle->aiff.channels) uiread (handle->aiff.framecount) sread (handle->aiff.width) edread (handle->aiff.rate) if (handle->aiff.filefmt == AF_FILE_AIFFC) { idread (idtemp) // No compression supported so if idtemp not "NONE" set // handle->aiff.compression to AF_COMPRESSION_UNKNOWN // Ignore compression string as it is not needed if (!strncmp (idtemp,"NONE",4)) handle->aiff.compression = AF_COMPRESSION_NONE; else handle->aiff.compression = AF_COMPRESSION_UNKNOWN; pstringread (tempstring) if (tempstring) free (tempstring); } comm = TRUE; } else if (!strncmp (id,"SSND",4)) { // ssnd // message ("ssnd\n"); if (ssnd) aiffError iread (chunksize) // offset and blocksize not used (should be zero anyway) uiread (offset) uiread (blocksize) // Skip past data for now handle->ssndStart = mTell (file); if (handle->ssndStart == -1) aiffError handle->ssndStart += offset; if (chunksize >= 8) { seeksize = chunksize - 8; if (seeksize % 2) seeksize++; if (mSeek (file,seeksize,SEEK_CUR) == -1) aiffError } else { aiffError } ssnd = TRUE; } else if (!strncmp (id,"MARK",4)) { // mark // message ("mark\n"); if (mark) aiffError iread (chunksize) usread (handle->aiff.marks) if (handle->aiff.marks) { handle->aiff.mark = (markType *) calloc (handle->aiff.marks,sizeof (markType)); for (i=0; iaiff.marks; i++) { usread (handle->aiff.mark [i].id) uiread (handle->aiff.mark [i].position) pstringread (handle->aiff.mark [i].name) } } else { handle->aiff.mark = 0; } mark = TRUE; } else if (!strncmp (id,"COMT",4)) { // comt // message ("comt\n"); int comments; commentType *comment; if (comt) aiffError iread (chunksize) usread (comments) if (comments) { comment = (commentType *) calloc (comments,sizeof (commentType)); for (i=0; iaiff.insts = 1; handle->aiff.inst = (instType *) calloc (handle->aiff.insts,sizeof (instType)); for (i=0; iaiff.insts; i++) { handle->aiff.inst [i].id = AF_DEFAULT_INST; cread (handle->aiff.inst [i].midibasenote) cread (handle->aiff.inst [i].numcentsdetune) cread (handle->aiff.inst [i].midilonote) cread (handle->aiff.inst [i].midihinote) cread (handle->aiff.inst [i].midilovelocity) cread (handle->aiff.inst [i].midihivelocity) sread (handle->aiff.inst [i].numdbsgain) handle->aiff.inst [i].susloopid = 1; handle->aiff.inst [i].relloopid = 2; handle->aiff.loops = 2; handle->aiff.loop = (loopType *) calloc (handle->aiff.loops,sizeof (loopType)); for (j=0; jaiff.loops; j++) { handle->aiff.loop [j].id = j + 1; sread (handle->aiff.loop [j].mode) usread (handle->aiff.loop [j].start) usread (handle->aiff.loop [j].end) } } inst = TRUE; } else if (!strncmp (id,"AESD",4)) { // aesd // message ("aesd\n"); if (aesd) aiffError iread (chunksize) if (chunksize != 24) aiffError handle->aiff.aesdatapresent = TRUE; if (!mRead (file,handle->aiff.aesdata,24)) aiffError aesd = TRUE; } else if (!strncmp (id,"NAME",4)) { // name // message ("name\n"); if (name) aiffError if (!name && !auth && !copy && !anno && !midi && !appl) initialiseMiscs (handle); iread (chunksize) if (chunksize) { handle->aiff.misc [0].size = chunksize; handle->aiff.misc [0].current = 0; handle->aiff.misc [0].data = (char *) calloc (chunksize,sizeof (char)); if (!mRead (file,handle->aiff.misc [0].data,chunksize)) aiffError if (chunksize % 2) ucread (uctemp) } else { handle->aiff.misc [0].size = 0; handle->aiff.misc [0].data = 0; } name = TRUE; } else if (!strncmp (id,"AUTH",4)) { // auth // message ("auth\n"); if (auth) aiffError if (!name && !auth && !copy && !anno && !midi && !appl) initialiseMiscs (handle); iread (chunksize) if (chunksize) { handle->aiff.misc [1].size = chunksize; handle->aiff.misc [1].current = 0; handle->aiff.misc [1].data = (char *) calloc (chunksize,sizeof (char)); if (!mRead (file,handle->aiff.misc [1].data,chunksize)) aiffError if (chunksize % 2) ucread (uctemp) } else { handle->aiff.misc [1].size = 0; handle->aiff.misc [1].data = 0; } auth = TRUE; } else if (!strncmp (id,"(c) ",4)) { // copy // message ("copy\n"); if (copy) aiffError if (!name && !auth && !copy && !anno && !midi && !appl) initialiseMiscs (handle); iread (chunksize) if (chunksize) { handle->aiff.misc [2].size = chunksize; handle->aiff.misc [2].current = 0; handle->aiff.misc [2].data = (char *) calloc (chunksize,sizeof (char)); if (!mRead (file,handle->aiff.misc [2].data,chunksize)) aiffError if (chunksize % 2) ucread (uctemp) } else { handle->aiff.misc [2].size = 0; handle->aiff.misc [2].data = 0; } copy = TRUE; } else if (!strncmp (id,"ANNO",4)) { // anno // message ("anno\n"); if (anno) { // Simply replace current anno (ie only supports one) if (handle->aiff.misc [3].data) { free (handle->aiff.misc [3].data); handle->aiff.misc [3].size = 0; handle->aiff.misc [3].current = 0; handle->aiff.misc [3].data = 0; } } if (!name && !auth && !copy && !anno && !midi && !appl) initialiseMiscs (handle); iread (chunksize) if (chunksize) { handle->aiff.misc [3].size = chunksize; handle->aiff.misc [3].current = 0; handle->aiff.misc [3].data = (char *) calloc (chunksize,sizeof (char)); if (!mRead (file,handle->aiff.misc [3].data,chunksize)) aiffError if (chunksize % 2) ucread (uctemp) } else { handle->aiff.misc [3].size = 0; handle->aiff.misc [3].data = 0; } anno = TRUE; } else if (!strncmp (id,"MIDI",4)) { // midi // message ("midi\n"); if (midi) { // Simply replace current midi (ie only supports one) if (handle->aiff.misc [4].data) { free (handle->aiff.misc [4].data); handle->aiff.misc [4].size = 0; handle->aiff.misc [4].current = 0; handle->aiff.misc [4].data = 0; } } if (!name && !auth && !copy && !anno && !midi && !appl) initialiseMiscs (handle); iread (chunksize) if (chunksize) { handle->aiff.misc [4].size = chunksize; handle->aiff.misc [4].current = 0; handle->aiff.misc [4].data = (char *) calloc (chunksize,sizeof (char)); if (!mRead (file,handle->aiff.misc [4].data,chunksize)) aiffError if (chunksize % 2) ucread (uctemp) } else { handle->aiff.misc [4].size = 0; handle->aiff.misc [4].data = 0; } midi = TRUE; } else if (!strncmp (id,"APPL",4)) { // appl // message ("appl\n"); if (appl) { // Simply replace current appl (ie only supports one) if (handle->aiff.misc [5].data) { free (handle->aiff.misc [5].data); handle->aiff.misc [5].size = 0; handle->aiff.misc [5].current = 0; handle->aiff.misc [5].data = 0; } } if (!name && !auth && !copy && !anno && !midi && !appl) initialiseMiscs (handle); iread (chunksize) if (chunksize) { handle->aiff.misc [5].size = chunksize; handle->aiff.misc [5].current = 0; handle->aiff.misc [5].data = (char *) calloc (chunksize,sizeof (char)); if (!mRead (file,handle->aiff.misc [5].data,chunksize)) aiffError if (chunksize % 2) ucread (uctemp) } else { handle->aiff.misc [5].size = 0; handle->aiff.misc [5].data = 0; } appl = TRUE; } else { // other // message ("other\n"); iread (chunksize) // Skip past data seeksize = chunksize; if (seeksize % 2) seeksize++; if (mSeek (file,seeksize,SEEK_CUR) == -1) aiffError } } if (error) fail ("error while reading file\n") // Check for necessary chunks if (!comm) fail ("no COMM chunk\n") if (handle->aiff.framecount > 0 && !ssnd) fail ("framecount > 0 but no SSND chunk\n") if (handle->aiff.filefmt == AF_FILE_AIFFC) { if (!fver) fail ("no FVER chunk\n") if (handle->aiff.version != AIFCVersion1) alert ("possibly incompatible AIFFC version\n") } // Read to start of sound data if (mSeek (file,handle->ssndStart,SEEK_SET) == -1) fail ("error seeking to start of sound data\n") handle = (AFfilehandle) calloc (1,sizeof (aiffHandle)); *handle = handleAct; return handle; } /*--------------------------------------------------------------------------- | FUNCTION AFwriteAIFF ---------------------------------------------------------------------------*/ AFfilehandle AFwriteAIFF (FHandle file,AFfilesetup setup) { int i; int j; int found; aiffHandle handleAct; AFfilehandle handle = &handleAct; int chunksize; int itemp; unsigned int uitemp; short stemp; unsigned short ustemp; signed char ctemp; unsigned char uctemp; double dtemp; char idtemp [4]; char *tempstring; int bytes; if (!setup) return AF_NULL_FILEHANDLE; handle->mode = WRITEONLY; handle->file = file; handle->actualBytes = 0; handle->actualFrames = 0; handle->ssndStart = 0; // Copy info from setup into handle->aiff copySetup (setup,&(handle->aiff)); // Write info from handle->aiff to file (without closing) if (!file) return AF_NULL_FILEHANDLE; idwrite ("FORM") // Don't know length yet (will update later) iwrite (0); // Reset counter as count doesn't include FORM or count itself handle->actualBytes = 0; if (handle->aiff.filefmt == AF_FILE_AIFF) idwrite ("AIFF") else if (handle->aiff.filefmt == AF_FILE_AIFFC) idwrite ("AIFC") else return AF_NULL_FILEHANDLE; if (handle->aiff.filefmt == AF_FILE_AIFFC) { idwrite ("FVER") chunksize = 4; iwrite (chunksize) uiwrite (handle->aiff.version) } idwrite ("COMM") if (handle->aiff.filefmt == AF_FILE_AIFF) chunksize = 18; else chunksize = 24; // Assume no compression name iwrite (chunksize) swrite (handle->aiff.channels) uiwrite (handle->aiff.framecount) swrite (handle->aiff.width) edwrite (handle->aiff.rate) if (handle->aiff.filefmt == AF_FILE_AIFFC) { if (handle->aiff.compression == AF_COMPRESSION_NONE) idwrite ("NONE") else if (handle->aiff.compression == AF_COMPRESSION_APPLE_ACE2) idwrite ("ACE2") else if (handle->aiff.compression == AF_COMPRESSION_APPLE_ACE8) idwrite ("ACE8") else if (handle->aiff.compression == AF_COMPRESSION_APPLE_MAC3) idwrite ("MAC3") else if (handle->aiff.compression == AF_COMPRESSION_APPLE_MAC6) idwrite ("MAC6") else idwrite ("UNKN") pstringwrite ("") } if (handle->aiff.marks) { idwrite ("MARK") chunksize = 2; /* Space for number of markers */ for (i=0; iaiff.marks; i++) { chunksize += 7; /* 6 for data plus 1 byte count */ if (handle->aiff.mark [i].name) { chunksize += strlen (handle->aiff.mark [i].name); if (!(strlen (handle->aiff.mark [i].name) % 2)) chunksize += 1; } else chunksize += 1; } iwrite (chunksize) uswrite (handle->aiff.marks) for (i=0; iaiff.marks; i++) { uswrite (handle->aiff.mark [i].id) uiwrite (handle->aiff.mark [i].position) pstringwrite (handle->aiff.mark [i].name) } } if (handle->aiff.insts) { for (i=0; iaiff.insts; i++) { idwrite ("INST") chunksize = 20; iwrite (chunksize) cwrite (handle->aiff.inst [i].midibasenote) cwrite (handle->aiff.inst [i].numcentsdetune) cwrite (handle->aiff.inst [i].midilonote) cwrite (handle->aiff.inst [i].midihinote) cwrite (handle->aiff.inst [i].midilovelocity) cwrite (handle->aiff.inst [i].midihivelocity) swrite (handle->aiff.inst [i].numdbsgain) // Find sustain loop details found = FALSE; j = 0; while (!found && jaiff.loops) { if (handle->aiff.loop [j].id == handle->aiff.inst [i].susloopid) found = TRUE; else j++; } if (found) { swrite (handle->aiff.loop [j].mode) uswrite (handle->aiff.loop [j].start) uswrite (handle->aiff.loop [j].end) } else { swrite (AF_LOOP_MODE_NOLOOP) uswrite (1) uswrite (2) } // Find release loop details found = FALSE; j = 0; while (!found && jaiff.loops) { if (handle->aiff.loop [j].id == handle->aiff.inst [i].relloopid) found = TRUE; else j++; } if (found) { swrite (handle->aiff.loop [j].mode) uswrite (handle->aiff.loop [j].start) uswrite (handle->aiff.loop [j].end) } else { swrite (AF_LOOP_MODE_NOLOOP) uswrite (3) uswrite (4) } } } if (handle->aiff.aesdatapresent) { idwrite ("AESD") chunksize = 24; iwrite (chunksize) if (!mWrite (file,handle->aiff.aesdata,24)) return AF_NULL_FILEHANDLE; handle->actualBytes += 24; } if (handle->aiff.miscs) { for (i=0; iaiff.miscs; i++) { if (handle->aiff.misc [i].type == AF_MISC_AIFF_NAME) idwrite ("NAME") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_AUTH) idwrite ("AUTH") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_COPY) idwrite ("(c) ") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_ANNO) idwrite ("ANNO") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_MIDI) idwrite ("MIDI") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_APPL) idwrite ("APPL") else idwrite ("APPL") if (handle->aiff.misc [i].data) { chunksize = handle->aiff.misc [i].size; iwrite (chunksize) if (chunksize) { if (!mWrite (file,handle->aiff.misc [i].data,chunksize)) return AF_NULL_FILEHANDLE; handle->actualBytes += chunksize; if (chunksize % 2) ucwrite (0) } } else { chunksize = 0; iwrite (chunksize) } } } // Write sample data chunk header and reset frame counter idwrite ("SSND") // Don't know length yet iwrite (0) // Offset and blocksize zero uiwrite (0) uiwrite (0) mFlush (file); handle = (AFfilehandle) calloc (1,sizeof (aiffHandle)); *handle = handleAct; return handle; } /*--------------------------------------------------------------------------- | FUNCTION AFgetfd ---------------------------------------------------------------------------*/ FHandle AFgetfd (AFfilehandle handle) { if (!handle) return 0; return handle->file; } /*--------------------------------------------------------------------------- | FUNCTION AFclosefile ---------------------------------------------------------------------------*/ int AFclosefile (AFfilehandle handle) { if (!handle) return -1; // Check for type to close if (handle->aiff.sampleFormat == AF_FORMAT_AIFF) { // AIFF files are always little endian setBigEndian (FALSE); return AFclosefileAIFF (handle); } else if (handle->aiff.sampleFormat == AF_FORMAT_WAV) { // WAV files are always big endian setBigEndian (TRUE); return AFclosefileWAV (handle); } else if (handle->aiff.sampleFormat == AF_FORMAT_RAW) { // RAW files can be big or little setEndian (handle->aiff.rawDetails.endian); return AFclosefileRAW (handle); } return -1; } /*--------------------------------------------------------------------------- | FUNCTION AFclosefileAIFF ---------------------------------------------------------------------------*/ int AFclosefileAIFF (AFfilehandle handle) { int i; int j; int found; int chunksize; int itemp; unsigned int uitemp; short stemp; unsigned short ustemp; char ctemp; unsigned char uctemp; double dtemp; char *tempString; char idtemp [4]; FHandle file; int byteWidth; int bytes; // If handle->mode is WRITEONLY update header info (as in handle->aiff) // If error then return negative number if (!handle) return -1; file = handle->file; if (handle->mode == READONLY) { if (mClose (handle->file) == -1) return -1; free (handle); return 0; } if (handle->mode == WRITEONLY) { // Update frame count handle->aiff.framecount = handle->actualFrames; // Add pad byte at end if necessary if (handle->actualBytes % 2) ucwrite (0) // Reset file descriptor if (mSeek (file,0L,SEEK_SET) == -1) { fprintf (stderr,"unable to seek on file\n"); return -1; } // Write info from handle->aiff to file (without closing) if (!file) fail ("file won't open for update\n") idupdate ("FORM") // Update length iupdate (handle->actualBytes); if (handle->aiff.filefmt == AF_FILE_AIFF) idupdate ("AIFF") else if (handle->aiff.filefmt == AF_FILE_AIFFC) idupdate ("AIFC") else return -1; if (handle->aiff.filefmt == AF_FILE_AIFFC) { idupdate ("FVER") chunksize = 4; iupdate (chunksize) uiupdate (handle->aiff.version) } idupdate ("COMM") if (handle->aiff.filefmt == AF_FILE_AIFF) chunksize = 18; else chunksize = 24; // Assume no compression name iupdate (chunksize) supdate (handle->aiff.channels) uiupdate (handle->aiff.framecount) supdate (handle->aiff.width) edupdate (handle->aiff.rate) if (handle->aiff.filefmt == AF_FILE_AIFFC) { if (handle->aiff.compression == AF_COMPRESSION_NONE) idupdate ("NONE") else if (handle->aiff.compression == AF_COMPRESSION_APPLE_ACE2) idupdate ("ACE2") else if (handle->aiff.compression == AF_COMPRESSION_APPLE_ACE8) idupdate ("ACE8") else if (handle->aiff.compression == AF_COMPRESSION_APPLE_MAC3) idupdate ("MAC3") else if (handle->aiff.compression == AF_COMPRESSION_APPLE_MAC6) idupdate ("MAC6") else idupdate ("UNKN") pstringupdate ("") } if (handle->aiff.marks) { idupdate ("MARK") chunksize = 2; /* Number of markers */ for (i=0; iaiff.marks; i++) { chunksize += 7; /* 6 for data plus 1 byte count */ if (handle->aiff.mark [i].name) { chunksize += strlen (handle->aiff.mark [i].name); if (!(strlen (handle->aiff.mark [i].name) % 2)) chunksize += 1; } else chunksize += 1; } iupdate (chunksize) usupdate (handle->aiff.marks) for (i=0; iaiff.marks; i++) { usupdate (handle->aiff.mark [i].id) uiupdate (handle->aiff.mark [i].position) pstringupdate (handle->aiff.mark [i].name) } } if (handle->aiff.insts) { for (i=0; iaiff.insts; i++) { idupdate ("INST") chunksize = 20; iupdate (chunksize) cupdate (handle->aiff.inst [i].midibasenote) cupdate (handle->aiff.inst [i].numcentsdetune) cupdate (handle->aiff.inst [i].midilonote) cupdate (handle->aiff.inst [i].midihinote) cupdate (handle->aiff.inst [i].midilovelocity) cupdate (handle->aiff.inst [i].midihivelocity) supdate (handle->aiff.inst [i].numdbsgain) // Find sustain loop details found = FALSE; j = 0; while (!found && jaiff.loops) { if (handle->aiff.loop [j].id == handle->aiff.inst [i].susloopid) found = TRUE; else j++; } if (found) { supdate (handle->aiff.loop [j].mode) usupdate (handle->aiff.loop [j].start) usupdate (handle->aiff.loop [j].end) } else { supdate (AF_LOOP_MODE_NOLOOP) usupdate (1) usupdate (2) } // Find release loop details found = FALSE; j = 0; while (!found && jaiff.loops) { if (handle->aiff.loop [j].id == handle->aiff.inst [i].relloopid) found = TRUE; else j++; } if (found) { supdate (handle->aiff.loop [j].mode) usupdate (handle->aiff.loop [j].start) usupdate (handle->aiff.loop [j].end) } else { supdate (AF_LOOP_MODE_NOLOOP) usupdate (3) usupdate (4) } } } if (handle->aiff.aesdatapresent) { idupdate ("AESD") chunksize = 24; iupdate (chunksize) if (!mWrite (file,handle->aiff.aesdata,24)) return AF_NULL_FILEHANDLE; } if (handle->aiff.miscs) { for (i=0; iaiff.miscs; i++) { if (handle->aiff.misc [i].type == AF_MISC_AIFF_NAME) idupdate ("NAME") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_AUTH) idupdate ("AUTH") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_COPY) idupdate ("(c) ") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_ANNO) idupdate ("ANNO") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_MIDI) idupdate ("MIDI") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_APPL) idupdate ("APPL") else idupdate ("APPL") if (handle->aiff.misc [i].data) { chunksize = handle->aiff.misc [i].size; iupdate (chunksize) if (chunksize) { if (!mWrite (file,handle->aiff.misc [i].data,chunksize)) return AF_NULL_FILEHANDLE; if (chunksize % 2) ucupdate (0) } } else { chunksize = 0; iupdate (chunksize) } } } // Update sample data chunk header and reset frame counter idupdate ("SSND") // Update chunk size chunksize = handle->aiff.framecount * handle->aiff.channels; byteWidth = ((handle->aiff.width + 7) / 8); if (byteWidth == 3) byteWidth++; chunksize *= byteWidth; chunksize += 8; // For offset and blocksize iupdate (chunksize) // Offset and blocksize zero uiupdate (0) uiupdate (0) if (mClose (handle->file) == -1) return -1; free (handle); return 0; } return -1; } /*--------------------------------------------------------------------------- | FUNCTION AFgetfilefmt ---------------------------------------------------------------------------*/ int AFgetfilefmt (AFfilehandle handle,long *version) { if (!handle) return 0; if (handle->aiff.filefmt == AF_FILE_AIFF) { *version = 0; return AF_FILE_AIFF; } if (handle->aiff.filefmt == AF_FILE_AIFFC) { *version = handle->aiff.version; return AF_FILE_AIFFC; } return AF_FILE_UNKNOWN; } /*--------------------------------------------------------------------------- | FUNCTION AFidentifyfd ---------------------------------------------------------------------------*/ int AFidentifyfd (FHandle file) { char id [4]; int bytes; // Read info from file if (!file) return AF_FILE_UNKNOWN; // Check FORM chunk if (!mRead (file,id,4) || strncmp (id,"FORM",4)) return AF_FILE_UNKNOWN; if (!iRead (file,&bytes)) return AF_FILE_UNKNOWN; if (!mRead (file,id,4)) return AF_FILE_UNKNOWN; if (!strncmp (id,"AIFF",4)) return AF_FILE_AIFF; else if (!strncmp (id,"AIFC",4)) return AF_FILE_AIFFC; else return AF_FILE_UNSUPPORTED; } /*--------------------------------------------------------------------------- | FUNCTION AFgetrate ---------------------------------------------------------------------------*/ double AFgetrate (AFfilehandle handle,int trackid) { if (!handle) return 0.0; return handle->aiff.rate; } /*--------------------------------------------------------------------------- | FUNCTION AFgetsampfmt ---------------------------------------------------------------------------*/ void AFgetsampfmt ( AFfilehandle handle, int trackid, long *sampfmt, long *width) { if (!handle || trackid != AF_DEFAULT_TRACK) { *sampfmt = 0; *width = 0; return; } *sampfmt = handle->aiff.sampfmt; *width = handle->aiff.width; } /*--------------------------------------------------------------------------- | FUNCTION AFgetchannels ---------------------------------------------------------------------------*/ int AFgetchannels (AFfilehandle handle,int trackid) { if (!handle || trackid != AF_DEFAULT_TRACK) return 0; return handle->aiff.channels; } /*--------------------------------------------------------------------------- | FUNCTION AFgetaeschanneldata ---------------------------------------------------------------------------*/ int AFgetaeschanneldata ( AFfilehandle handle, int trackid, unsigned char buf [24]) { int i; if (!handle || trackid != AF_DEFAULT_TRACK) return 0; if (!handle->aiff.aesdatapresent) return 0; for (i=0; i<24; i++) buf [i] = handle->aiff.aesdata [i]; return 1; } /*--------------------------------------------------------------------------- | FUNCTION AFgetcompression ---------------------------------------------------------------------------*/ int AFgetcompression (AFfilehandle handle,int trackid) { if (!handle || trackid != AF_DEFAULT_TRACK) return AF_COMPRESSION_NONE; return handle->aiff.compression; } /*--------------------------------------------------------------------------- | FUNCTION AFgetcompressionname ---------------------------------------------------------------------------*/ char *AFgetcompressionname (AFfilehandle handle,int trackid) { if (!handle || trackid != AF_DEFAULT_TRACK) return NULL; if (handle->aiff.compression == AF_COMPRESSION_NONE) return "No compression"; // Should really handle all compression cases return "Compression"; } /*--------------------------------------------------------------------------- | FUNCTION AFgetframecnt ---------------------------------------------------------------------------*/ int AFgetframecnt (AFfilehandle handle,int trackid) { if (!handle || trackid != AF_DEFAULT_TRACK) return 0; return handle->aiff.framecount; } /*--------------------------------------------------------------------------- | FUNCTION AFgetmarkids ---------------------------------------------------------------------------*/ int AFgetmarkids (AFfilehandle handle,int trackid,long *markids) { int i; if (!handle || trackid != AF_DEFAULT_TRACK) return 0; if (markids) for (i=0; iaiff.marks; i++) markids [i] = handle->aiff.mark [i].id; return handle->aiff.marks; } /*--------------------------------------------------------------------------- | FUNCTION AFgetmarkname ---------------------------------------------------------------------------*/ char *AFgetmarkname (AFfilehandle handle,int trackid,int markid) { int i; int found; if (!handle || trackid != AF_DEFAULT_TRACK) return 0; i = 0; found = FALSE; while (iaiff.marks && !found) { if (handle->aiff.mark [i].id == markid) found = TRUE; else i++; } if (!found) return 0; return handle->aiff.mark [i].name; } /*--------------------------------------------------------------------------- | FUNCTION AFgetmarkpos ---------------------------------------------------------------------------*/ int AFgetmarkpos (AFfilehandle handle,int trackid,int markid) { int i; int found; if (!handle || trackid != AF_DEFAULT_TRACK) return 0; i = 0; found = FALSE; while (iaiff.marks && !found) { if (handle->aiff.mark [i].id == markid) found = TRUE; else i++; } if (!found) return 0; return handle->aiff.mark [i].position; } /*--------------------------------------------------------------------------- | FUNCTION AFsetmarkpos ---------------------------------------------------------------------------*/ void AFsetmarkpos ( AFfilehandle handle, int trackid, int markid, int markpos) { int i; int found; if (!handle || trackid != AF_DEFAULT_TRACK) return; i = 0; found = FALSE; while (iaiff.marks && !found) { if (handle->aiff.mark [i].id == markid) found = TRUE; else i++; } if (!found) return; handle->aiff.mark [i].position = markpos; } /*--------------------------------------------------------------------------- | FUNCTION AFgetinstids ---------------------------------------------------------------------------*/ int AFgetinstids (AFfilehandle handle,long *instids) { int i; if (!handle) return 0; if (instids) for (i=0; iaiff.insts; i++) instids [i] = handle->aiff.inst [i].id; return handle->aiff.insts; } /*--------------------------------------------------------------------------- | FUNCTION AFgetinstparamint ---------------------------------------------------------------------------*/ int AFgetinstparamint (AFfilehandle handle,int instid,int param) { int i; int found; if (!handle || instid != AF_DEFAULT_INST) return 0; i = 0; found = FALSE; while (iaiff.insts && !found) { if (handle->aiff.inst [i].id == instid) found = TRUE; else i++; } if (!found) return 0; switch (param) { case AF_INST_MIDI_BASENOTE : return handle->aiff.inst [i].midibasenote; case AF_INST_NUMCENTS_DETUNE : return handle->aiff.inst [i].numcentsdetune; case AF_INST_MIDI_LONOTE : return handle->aiff.inst [i].midilonote; case AF_INST_MIDI_HINOTE : return handle->aiff.inst [i].midihinote; case AF_INST_MIDI_LOVELOCITY : return handle->aiff.inst [i].midilovelocity; case AF_INST_MIDI_HIVELOCITY : return handle->aiff.inst [i].midihivelocity; case AF_INST_NUMDBS_GAIN : return handle->aiff.inst [i].numdbsgain; case AF_INST_SUSLOOPID : return handle->aiff.inst [i].susloopid; case AF_INST_RELLOOPID : return handle->aiff.inst [i].relloopid; default : return 0; } } /*--------------------------------------------------------------------------- | FUNCTION AFsetinstparamint ---------------------------------------------------------------------------*/ void AFsetinstparamint ( AFfilehandle handle, int instid, int param, int value) { int i; int found; if (!handle || instid != AF_DEFAULT_INST) return; i = 0; found = FALSE; while (iaiff.insts && !found) { if (handle->aiff.inst [i].id == instid) found = TRUE; else i++; } if (!found) return; switch (param) { case AF_INST_MIDI_BASENOTE : handle->aiff.inst [i].midibasenote = value; case AF_INST_NUMCENTS_DETUNE : handle->aiff.inst [i].numcentsdetune = value; case AF_INST_MIDI_LONOTE : handle->aiff.inst [i].midilonote = value; case AF_INST_MIDI_HINOTE : handle->aiff.inst [i].midihinote = value; case AF_INST_MIDI_LOVELOCITY : handle->aiff.inst [i].midilovelocity = value; case AF_INST_MIDI_HIVELOCITY : handle->aiff.inst [i].midihivelocity = value; case AF_INST_NUMDBS_GAIN : handle->aiff.inst [i].numdbsgain = value; case AF_INST_SUSLOOPID : handle->aiff.inst [i].susloopid = value; case AF_INST_RELLOOPID : handle->aiff.inst [i].relloopid = value; default : return; } } /*--------------------------------------------------------------------------- | FUNCTION AFgetloopids ---------------------------------------------------------------------------*/ int AFgetloopids (AFfilehandle handle,long *loopids) { int i; if (!handle) return 0; if (loopids) for (i=0; iaiff.loops; i++) loopids [i] = handle->aiff.loop [i].id; return handle->aiff.loops; } /*--------------------------------------------------------------------------- | FUNCTION AFgetloopmode ---------------------------------------------------------------------------*/ int AFgetloopmode (AFfilehandle handle,int instid,int loopid) { int i; int found; if (!handle || instid != AF_DEFAULT_INST) return AF_LOOP_MODE_NOLOOP; i = 0; found = FALSE; while (iaiff.loops && !found) { if (handle->aiff.loop [i].id == loopid) found = TRUE; else i++; } if (!found) return AF_LOOP_MODE_NOLOOP; return handle->aiff.loop [i].mode; } /*--------------------------------------------------------------------------- | FUNCTION AFsetloopmode ---------------------------------------------------------------------------*/ void AFsetloopmode (AFfilehandle handle,int instid,int loopid,int mode) { int i; int found; if (!handle || instid != AF_DEFAULT_INST) return; i = 0; found = FALSE; while (iaiff.loops && !found) { if (handle->aiff.loop [i].id == loopid) found = TRUE; else i++; } if (!found) return; handle->aiff.loop [i].mode = mode; } /*--------------------------------------------------------------------------- | FUNCTION AFgetloopstart ---------------------------------------------------------------------------*/ int AFgetloopstart (AFfilehandle handle,int instid,int loopid) { int i; int found; if (!handle || instid != AF_DEFAULT_INST) return 0; i = 0; found = FALSE; while (iaiff.loops && !found) { if (handle->aiff.loop [i].id == loopid) found = TRUE; else i++; } if (!found) return 0; return handle->aiff.loop [i].start; } /*--------------------------------------------------------------------------- | FUNCTION AFsetloopstart ---------------------------------------------------------------------------*/ void AFsetloopstart ( AFfilehandle handle, int instid, int loopid, int markid) { int i; int found; if (!handle || instid != AF_DEFAULT_INST) return; i = 0; found = FALSE; while (iaiff.loops && !found) { if (handle->aiff.loop [i].id == loopid) found = TRUE; else i++; } if (!found) return; handle->aiff.loop [i].start = markid; } /*--------------------------------------------------------------------------- | FUNCTION AFgetloopend ---------------------------------------------------------------------------*/ int AFgetloopend (AFfilehandle handle,int instid,int loopid) { int i; int found; if (!handle || instid != AF_DEFAULT_INST) return 0; i = 0; found = FALSE; while (iaiff.loops && !found) { if (handle->aiff.loop [i].id == loopid) found = TRUE; else i++; } if (!found) return 0; return handle->aiff.loop [i].end; } /*--------------------------------------------------------------------------- | FUNCTION AFsetloopend ---------------------------------------------------------------------------*/ void AFsetloopend (AFfilehandle handle,int instid,int loopid,int markid) { int i; int found; if (!handle || instid != AF_DEFAULT_INST) return; i = 0; found = FALSE; while (iaiff.loops && !found) { if (handle->aiff.loop [i].id == loopid) found = TRUE; else i++; } if (!found) return; handle->aiff.loop [i].end = markid; } /*--------------------------------------------------------------------------- | FUNCTION AFgetmiscids ---------------------------------------------------------------------------*/ int AFgetmiscids (AFfilehandle handle,long *miscids) { int i; if (!handle) return 0; if (miscids) for (i=0; iaiff.miscs; i++) miscids [i] = handle->aiff.misc [i].id; return handle->aiff.miscs; } /*--------------------------------------------------------------------------- | FUNCTION AFgetmisctype ---------------------------------------------------------------------------*/ int AFgetmisctype (AFfilehandle handle,int miscid) { int i; int found; if (!handle) return AF_MISC_AIFF_UNRECOGNIZED; i = 0; found = FALSE; while (iaiff.miscs && !found) { if (handle->aiff.misc [i].id == miscid) found = TRUE; else i++; } if (!found) return AF_MISC_AIFF_UNRECOGNIZED; return handle->aiff.misc [i].type; } /*--------------------------------------------------------------------------- | FUNCTION AFgetmiscsize ---------------------------------------------------------------------------*/ int AFgetmiscsize (AFfilehandle handle,int miscid) { int i; int found; if (!handle) return 0; i = 0; found = FALSE; while (iaiff.miscs && !found) { if (handle->aiff.misc [i].id == miscid) found = TRUE; else i++; } if (!found) return 0; return handle->aiff.misc [i].size; } /*--------------------------------------------------------------------------- | FUNCTION AFreadmisc ---------------------------------------------------------------------------*/ int AFreadmisc (AFfilehandle handle,int miscid,void *buf,int nbytes) { int i; int j; int count; int found; if (!handle) return 0; i = 0; found = FALSE; while (iaiff.miscs && !found) { if (handle->aiff.misc [i].id == miscid) found = TRUE; else i++; } if (!found) return 0; count = 0; j = handle->aiff.misc [i].current; while (count < nbytes && j < handle->aiff.misc [i].size) { ((char *) buf) [j] = handle->aiff.misc [i].data [j]; j++; count++; handle->aiff.misc [i].current++; } return count; } /*--------------------------------------------------------------------------- | FUNCTION AFwritemisc ---------------------------------------------------------------------------*/ int AFwritemisc (AFfilehandle handle,int miscid,void *buf,int nbytes) { int i; int j; int count; int found; if (!handle) return 0; i = 0; found = FALSE; while (iaiff.miscs && !found) { if (handle->aiff.misc [i].id == miscid) found = TRUE; else i++; } if (!found) return 0; count = 0; j = handle->aiff.misc [i].current; while (count < nbytes && j < handle->aiff.misc [i].size) { handle->aiff.misc [i].data [j] = ((char *) buf) [j]; j++; count++; handle->aiff.misc [i].current++; } return count; } /*--------------------------------------------------------------------------- | FUNCTION AFseekmisc ---------------------------------------------------------------------------*/ void AFseekmisc (AFfilehandle handle,int miscid,int offset) { int i; int found; if (!handle) return; i = 0; found = FALSE; while (iaiff.miscs && !found) { if (handle->aiff.misc [i].id == miscid) found = TRUE; else i++; } if (!found) return; handle->aiff.misc [i].current = offset; if (handle->aiff.misc [i].current < 0) handle->aiff.misc [i].current = 0; if (handle->aiff.misc [i].current > handle->aiff.misc [i].size) handle->aiff.misc [i].current = handle->aiff.misc [i].size; } /*--------------------------------------------------------------------------- | FUNCTION AFreadframes ---------------------------------------------------------------------------*/ int AFreadframes ( AFfilehandle handle, int trackid, void *frames, int count) { if (!handle) return 0; // Check for type to close if (handle->aiff.sampleFormat == AF_FORMAT_AIFF) { // AIFF files are always little endian setBigEndian (FALSE); return AFreadframesAIFF (handle,trackid,frames,count); } else if (handle->aiff.sampleFormat == AF_FORMAT_WAV) { // WAV files are always big endian setBigEndian (TRUE); return AFreadframesWAV (handle,frames,count); } else if (handle->aiff.sampleFormat == AF_FORMAT_RAW) { // RAW files can be big or little setEndian (handle->aiff.rawDetails.endian); return AFreadframesRAW (handle,frames,count); } return 0; } /*--------------------------------------------------------------------------- | FUNCTION AFreadframesAIFF ---------------------------------------------------------------------------*/ int AFreadframesAIFF ( AFfilehandle handle, int trackid, void *frames, int count) { int i; int j; int frameCount; FHandle file; signed char ctemp; short stemp; int itemp; if (!handle || trackid != AF_DEFAULT_TRACK) return 0; if (handle->mode != READONLY) return 0; file = handle->file; if (!file) return 0; i = 0; frameCount = 0; while (handle->actualFrames < handle->aiff.framecount && frameCount < count && !mEof (file)) { for (j=0; jaiff.channels; j++) { if (handle->aiff.width <= 8) { if (!cRead (file,&ctemp)) return frameCount; ((signed char *) frames) [i++] = ctemp; } else if (handle->aiff.width <= 16) { if (!sRead (file,&stemp)) return frameCount; ((short *) frames) [i++] = stemp; } else if (handle->aiff.width <= 32) { if (!iRead (file,&itemp)) return frameCount; ((int *) frames) [i++] = itemp; } else { return frameCount; } } frameCount++; handle->actualFrames++; } return frameCount; } /*--------------------------------------------------------------------------- | FUNCTION AFwriteframes ---------------------------------------------------------------------------*/ int AFwriteframes ( AFfilehandle handle, int trackid, void *frames, int count) { if (!handle) return 0; // Check for type to close if (handle->aiff.sampleFormat == AF_FORMAT_AIFF) { // AIFF files are always little endian setBigEndian (FALSE); return AFwriteframesAIFF (handle,trackid,frames,count); } else if (handle->aiff.sampleFormat == AF_FORMAT_WAV) { // WAV files are always big endian setBigEndian (TRUE); return AFwriteframesWAV (handle,frames,count); } else if (handle->aiff.sampleFormat == AF_FORMAT_RAW) { // RAW files can be big or little setEndian (handle->aiff.rawDetails.endian); return AFwriteframesRAW (handle,frames,count); } return 0; } /*--------------------------------------------------------------------------- | FUNCTION AFwriteframesAIFF ---------------------------------------------------------------------------*/ int AFwriteframesAIFF ( AFfilehandle handle, int trackid, void *frames, int count) { int i; int j; int frameCount; FHandle file; signed char ctemp; short stemp; int itemp; if (!handle || trackid != AF_DEFAULT_TRACK) return 0; if (handle->mode != WRITEONLY) return 0; file = handle->file; if (!file) return 0; i = 0; frameCount = 0; while (frameCount < count && !mEof (file)) { for (j=0; jaiff.channels; j++) { if (handle->aiff.width <= 8) { ctemp = ((signed char *) frames) [i++]; if (!cWrite (file,ctemp)) return frameCount; handle->actualBytes += sizeof (ctemp); } else if (handle->aiff.width <= 16) { stemp = ((short *) frames) [i++]; if (!sWrite (file,stemp)) return frameCount; handle->actualBytes += sizeof (stemp); } else if (handle->aiff.width <= 32) { itemp = ((int *) frames) [i++]; if (!iWrite (file,itemp)) return frameCount; handle->actualBytes += sizeof (itemp); } else { return frameCount; } } frameCount++; handle->actualFrames++; } return frameCount; } /*--------------------------------------------------------------------------- | FUNCTION AFseekframe ---------------------------------------------------------------------------*/ int AFseekframe (AFfilehandle handle,int trackid,int offset) { int seeksize; FHandle file; if (!handle || trackid != AF_DEFAULT_TRACK) return 0; if (handle->mode != READONLY) return 0; file = handle->file; if (!file) return 0; if (offset < 0) offset = 0; if (offset >= handle->aiff.framecount) offset = handle->aiff.framecount; seeksize = offset - handle->actualFrames; if (handle->aiff.width <= 8) { seeksize = seeksize; } else if (handle->aiff.width <= 16) { seeksize = 2 * seeksize; } else if (handle->aiff.width <= 32) { seeksize = 4 * seeksize; } else { seeksize = 0; } seeksize *= handle->aiff.channels; handle->actualFrames = offset; if (mSeek (file,seeksize,SEEK_CUR) == -1) return -1; else return offset; } /*--------------------------------------------------------------------------- | FUNCTION AFgettrackids ---------------------------------------------------------------------------*/ int AFgettrackids (AFfilehandle handle,long *trackids) { if (!handle) return 0; /* Only return AF_DEFAULT_TRACK for now */ if (trackids) trackids[0] = AF_DEFAULT_TRACK; return 1; } /*--------------------------------------------------------------------------- | FUNCTION initialiseMiscs ---------------------------------------------------------------------------*/ void initialiseMiscs (AFfilehandle handle) { // Initialises the miscs in the order shown below int i; if (!handle) return; handle->aiff.miscs = 6; handle->aiff.misc = (miscType *) calloc (handle->aiff.miscs,sizeof (miscType)); for (i=0; iaiff.miscs; i++) { handle->aiff.misc [i].id = i + 1; if (i == 0) handle->aiff.misc [i].type = AF_MISC_AIFF_NAME; if (i == 1) handle->aiff.misc [i].type = AF_MISC_AIFF_AUTH; if (i == 2) handle->aiff.misc [i].type = AF_MISC_AIFF_COPY; if (i == 3) handle->aiff.misc [i].type = AF_MISC_AIFF_ANNO; if (i == 4) handle->aiff.misc [i].type = AF_MISC_AIFF_MIDI; if (i == 5) handle->aiff.misc [i].type = AF_MISC_AIFF_APPL; handle->aiff.misc [i].size = 0; handle->aiff.misc [i].current = 0; handle->aiff.misc [i].data = 0; } } /*--------------------------------------------------------------------------- | FUNCTION initialiseSetup ---------------------------------------------------------------------------*/ void initialiseSetup (AFfilesetup setup) { // Initialises a default setup int i; if (!setup) return; setup->sampleFormat = AF_FORMAT_AIFF; setup->rawDetails.channels = 1; setup->rawDetails.dataFormat = AF_BYTE_FORMAT; setup->rawDetails.signedData = TRUE; setup->rawDetails.endian = AF_DEF_ENDIAN_FORMAT; setup->filefmt = AF_FILE_AIFFC; setup->version = AIFCVersion1; setup->audiotrack = AF_DEFAULT_TRACK; setup->rate = 8000.0; setup->sampfmt = AF_SAMPFMT_TWOSCOMP; setup->width = 16; setup->channels = 2; setup->compression = AF_COMPRESSION_NONE; setup->aesdatapresent = 0; for (i=0; i<24; i++) setup->aesdata [i] = 0; setup->framecount = 0; setup->marks = 4; setup->mark = (markType *) calloc (4,sizeof (markType)); for (i=0; i<4; i++) { setup->mark [i].id = i + 1; setup->mark [i].name = 0; setup->mark [i].position = 0; } setup->insts = 1; setup->inst = (instType *) calloc (1,sizeof (instType)); for (i=0; i<1; i++) { setup->inst [i].id = AF_DEFAULT_INST; setup->inst [i].midibasenote = 60; setup->inst [i].midihinote = 127; setup->inst [i].midihivelocity = 127; setup->inst [i].midilonote = 0; setup->inst [i].midilovelocity = 1; setup->inst [i].numcentsdetune = 0; setup->inst [i].numdbsgain = 0; setup->inst [i].susloopid = 1; setup->inst [i].relloopid = 2; } setup->loops = 2; setup->loop = (loopType *) calloc (2,sizeof (loopType)); for (i=0; i<2; i++) { setup->loop [i].id = i + 1; setup->loop [i].mode = AF_LOOP_MODE_NOLOOP; setup->loop [i].start = (2 * i) + 1; setup->loop [i].end = (2 * i) + 2; } setup->miscs = 0; setup->misc = 0; } /*--------------------------------------------------------------------------- | FUNCTION blankSetup ---------------------------------------------------------------------------*/ void blankSetup (AFfilesetup setup) { // Initialises a completely blank setup int i; if (!setup) return; setup->sampleFormat = AF_FORMAT_AIFF; setup->rawDetails.channels = 1; setup->rawDetails.dataFormat = AF_BYTE_FORMAT; setup->rawDetails.signedData = TRUE; setup->rawDetails.endian = AF_DEF_ENDIAN_FORMAT; setup->filefmt = AF_FILE_AIFF; setup->version = AIFCVersion1; setup->audiotrack = AF_DEFAULT_TRACK; setup->rate = 8000.0; setup->sampfmt = AF_SAMPFMT_TWOSCOMP; setup->width = 16; setup->channels = 2; setup->compression = AF_COMPRESSION_NONE; setup->aesdatapresent = 0; for (i=0; i<24; i++) setup->aesdata [i] = 0; setup->framecount = 0; setup->marks = 0; setup->mark = 0; setup->insts = 0; setup->inst = 0; setup->loops = 0; setup->loop = 0; setup->miscs = 0; setup->misc = 0; } /*--------------------------------------------------------------------------- | FUNCTION copySetup ---------------------------------------------------------------------------*/ void copySetup (AFfilesetup from,AFfilesetup to) { // Copies a setup int i; if (!from || !to) return; to->sampleFormat = from->sampleFormat; to->rawDetails.channels = from->rawDetails.channels; to->rawDetails.dataFormat = from->rawDetails.dataFormat; to->rawDetails.signedData = from->rawDetails.signedData; to->rawDetails.endian = from->rawDetails.endian; to->filefmt = from->filefmt; to->version = from->version; to->audiotrack = from->audiotrack; to->rate = from->rate; to->sampfmt = from->sampfmt; to->width = from->width; to->channels = from->channels; to->compression = from->compression; to->aesdatapresent = from->aesdatapresent; for (i=0; i<24; i++) to->aesdata [i] = from->aesdata [i]; to->framecount = from->framecount; to->marks = from->marks; to->mark = (markType *) calloc (to->marks,sizeof (markType)); for (i=0; imarks; i++) { to->mark [i].id = from->mark [i].id; if (from->mark [i].name) { to->mark [i].name = (char *) calloc (strlen (from->mark [i].name) + 1,sizeof (char)); strcpy (to->mark [i].name,from->mark [i].name); } else { to->mark [i].name = 0; } to->mark [i].position = from->mark [i].position; } to->insts = from->insts; to->inst = (instType *) calloc (to->insts,sizeof (instType)); for (i=0; iinsts; i++) to->inst [i] = from->inst [i]; to->loops = from->loops; to->loop = (loopType *) calloc (to->loops,sizeof (loopType)); for (i=0; iloops; i++) to->loop [i] = from->loop [i]; to->miscs = from->miscs; to->misc = (miscType *) calloc (to->miscs,sizeof (miscType)); for (i=0; imiscs; i++) { to->misc [i].id = from->misc [i].id; to->misc [i].type = from->misc [i].type; to->misc [i].size = from->misc [i].size; to->misc [i].current = from->misc [i].current; if (from->misc [i].data) { to->misc [i].data = (char *) calloc (to->misc [i].size,sizeof (char)); memcpy (to->misc [i].data,from->misc [i].data,to->misc [i].size); } else { to->misc [i].data = 0; } } } /*--------------------------------------------------------------------------- | FUNCTION freeSetup ---------------------------------------------------------------------------*/ void freeSetup (AFfilesetup setup) { // Frees all memory from a setup int i; if (!setup) return; if (setup->mark) { for (i=0; imarks; i++) { if (setup->mark [i].name) { free (setup->mark [i].name); setup->mark [i].name = 0; } } free (setup->mark); setup->mark = 0; setup->marks = 0; } if (setup->inst) { free (setup->inst); setup->inst = 0; setup->insts = 0; } if (setup->loop) { free (setup->loop); setup->loop = 0; setup->loops = 0; } if (setup->misc) { for (i=0; imiscs; i++) { if (setup->misc [i].data) { free (setup->misc [i].data); setup->misc [i].data = 0; } } free (setup->misc); setup->misc = 0; setup->miscs = 0; } } /***************************************************************************/