/**************************************************************************** | Digital Audio Processor | ======================= | | Filename : wav.c | | Object : None | | Description : Audiofile replacement code for linux (wav files) | | (c) Richard Kent 1998 | | $Id: wav.c,v 1.1 2003/09/10 00:06:24 rk Exp $ | ****************************************************************************/ static char wav_c [] = "$Id: wav.c,v 1.1 2003/09/10 00:06:24 rk Exp $"; #include "audiofile.h" #include "wav.h" #include "macros.h" #include #include static int SaveBasicWavs = 0; void AFbasicWAV (int set) { SaveBasicWavs = set; } /*--------------------------------------------------------------------------- | FUNCTION AFreadWAV ---------------------------------------------------------------------------*/ AFfilehandle AFreadWAV (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; unsigned char uctemp; char idtemp [4]; int done = FALSE; int error = FALSE; int fmt = FALSE; int cue = FALSE; int adtl = FALSE; int dapi = FALSE; int info = FALSE; int name = FALSE; int auth = FALSE; int copy = FALSE; int anno = FALSE; int midi = FALSE; int appl = FALSE; int labl = FALSE; int data = FALSE; handle->mode = READONLY; handle->file = file; handle->actualBytes = 0; handle->actualFrames = 0; handle->ssndStart = 0; // Setup defaults in handle->aiff blankSetup (&(handle->aiff)); handle->aiff.sampleFormat = AF_FORMAT_WAV; // Read info from file into handle->aiff if (!file) return AF_NULL_FILEHANDLE; // Check RIFF chunk if (!idRead (file,id) || strncmp (id,"RIFF",4)) fail ("WAV header does not begin with magic word 'RIFF'\n") if (!uiRead (file,&uitemp)) fail ("No overall chunk size\n"); handle->actualBytes = uitemp; if (!idRead (file,id)) fail ("WAV header does not contain a form type\n") if (strncmp (id,"WAVE",4)) fail ("WAV 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,"fmt ",4)) { // fmt // message ("fmt\n"); unsigned short format; unsigned int byteRate; unsigned short blockAlign; unsigned short bitWidth; if (fmt) aiffError uiread (chunksize) if (chunksize != 16) aiffError usread (format) if (format != WAVE_FORMAT_PCM) aiffError usread (handle->aiff.channels) uiread (handle->aiff.rate) uiread (byteRate) usread (blockAlign) usread (bitWidth) if (bitWidth <= 8) handle->aiff.width = 8; else if (bitWidth <= 16) handle->aiff.width = 16; else handle->aiff.width = 32; fmt = TRUE; } else if (!strncmp (id,"data",4)) { // data // message ("data\n"); if (data) aiffError uiread (chunksize) // Now sort out framecount handle->aiff.framecount = chunksize / handle->aiff.channels; switch (handle->aiff.width) { case 8 : break; case 16 : handle->aiff.framecount /= 2; break; case 32 : handle->aiff.framecount /= 4; break; default : aiffError } // Skip past data for now handle->ssndStart = mTell (file); if (handle->ssndStart == -1) aiffError seeksize = chunksize; if (seeksize % 2) seeksize++; if (mSeek (file,seeksize,SEEK_CUR) == -1) aiffError data = TRUE; } else if (!strncmp (id,"cue ",4)) { // cue // message ("cue\n"); int position; char chunk [4]; unsigned int chunkStart; unsigned int blockStart; if (cue) aiffError uiread (chunksize) uiread (handle->aiff.marks) if (handle->aiff.marks) { handle->aiff.mark = (markType *) calloc (handle->aiff.marks,sizeof (markType)); for (i=0; iaiff.marks; i++) { uiread (handle->aiff.mark [i].id) uiread (position) idread (chunk) uiread (chunkStart) uiread (blockStart) uiread (handle->aiff.mark [i].position) handle->aiff.mark [i].name = 0; // Can only handle marks in WAV files containing a single // data chunk and within non-compressed PCM data chunks // - all other marks are set to position zero if (strncmp (chunk,"data",4) || chunkStart || blockStart) { handle->aiff.mark [i].position = 0; } } } else { handle->aiff.mark = 0; } cue = TRUE; } else if (!strncmp (id,"LIST",4)) { // LIST // message ("LIST\n"); char listType [4]; uiread (chunksize) idread (listType) if (strncmp (listType,"adtl",4) && strncmp (listType,"INFO",4)) { // Unknown list type so just skip whole chunk if (chunksize >= 4) { seeksize = chunksize - 4; // Already read in list type if (seeksize % 2) seeksize++; if (mSeek (file,seeksize,SEEK_CUR) == -1) aiffError } else { aiffError } } else { int listChunksize = chunksize; int amountRead = 4; // Already read in list type if (!strncmp (listType,"adtl",4)) adtl = TRUE; else if (!strncmp (listType,"INFO",4)) info = TRUE; while (!done && !error && amountRead < listChunksize && !mEof (file)) { if (!idRead (file,id)) { aiffError } else if (!strncmp (id,"labl",4) && !strncmp (listType,"adtl",4)) { // labl (adtl list) // message ("labl (adtl list)\n"); unsigned int markid; char *markname; int m; int found = FALSE; int stringsize; uiread (chunksize) amountRead += 8; // Space for "labl" and chunksize amountRead += chunksize; // Space for actual data if (chunksize % 2) amountRead++; // Space for padding byte uiread (markid) if (chunksize >= 4) { stringsize = chunksize - 4; // Allow for mark id markname = (char *) calloc (stringsize,sizeof (char)); if (!markname) aiffError if (!mRead (file,markname,stringsize)) aiffError markname [stringsize - 1] = 0; // Just in case if (stringsize % 2) ucread (uctemp) // We are assuming the cue chunk has already created // our marks for us - otherwise they won't be found for (m=0; maiff.marks && !found; m++) { if (handle->aiff.mark[m].id == markid) { handle->aiff.mark[m].name = markname; found = TRUE; } } if (!found) free (markname); } else { aiffError } labl = TRUE; } else if ((!strncmp (id,"INAM",4) || !strncmp (id,"IENG",4) || !strncmp (id,"ICOP",4) || !strncmp (id,"ICMT",4)) && !strncmp (listType,"INFO",4)) { // inam,ieng,icop,icmt (INFO list) // message ("inam,ieng,icop,icmt (INFO list)\n"); char *string; uiread (chunksize) amountRead += 8; // Space for chunktype and chunksize amountRead += chunksize; // Space for actual data if (chunksize % 2) amountRead++; // Space for padding byte string = (char *) calloc (chunksize,sizeof (char)); if (!string) aiffError if (!mRead (file,string,chunksize)) aiffError string [chunksize - 1] = 0; // Just in case if (chunksize % 2) ucread (uctemp) if (!strncmp (id,"INAM",4)) { // name (INFO list) // message ("name (INFO list)\n"); if (name) aiffError if (!name && !auth && !copy && !anno && !midi && !appl) initialiseMiscs (handle); handle->aiff.misc [0].size = chunksize; handle->aiff.misc [0].current = 0; handle->aiff.misc [0].data = string; name = TRUE; } else if (!strncmp (id,"IENG",4)) { // auth (INFO list) // message ("auth (INFO list)\n"); if (auth) aiffError if (!name && !auth && !copy && !anno && !midi && !appl) initialiseMiscs (handle); handle->aiff.misc [1].size = chunksize; handle->aiff.misc [1].current = 0; handle->aiff.misc [1].data = string; auth = TRUE; } else if (!strncmp (id,"ICOP",4)) { // copy (INFO list) // message ("copy (INFO list)\n"); if (copy) aiffError if (!name && !auth && !copy && !anno && !midi && !appl) initialiseMiscs (handle); handle->aiff.misc [2].size = chunksize; handle->aiff.misc [2].current = 0; handle->aiff.misc [2].data = string; copy = TRUE; } else if (!strncmp (id,"ICMT",4)) { // anno (INFO list) // message ("anno (INFO list)\n"); if (anno) aiffError if (!name && !auth && !copy && !anno && !midi && !appl) initialiseMiscs (handle); handle->aiff.misc [3].size = chunksize; handle->aiff.misc [3].current = 0; handle->aiff.misc [3].data = string; anno = TRUE; } else { free (string); } } else { // other (list) // message ("other (list)\n"); uiread (chunksize) amountRead += 8; // Space for chunktype and chunksize amountRead += chunksize; // Space for actual data if (chunksize % 2) amountRead++; // Space for padding byte // Skip past data seeksize = chunksize; if (seeksize % 2) seeksize++; if (mSeek (file,seeksize,SEEK_CUR) == -1) aiffError } } } } else if (!strncmp (id,"dapi",4)) { // dapi // message ("dapi\n"); if (dapi) aiffError uiread (chunksize) if (chunksize != 12) aiffError handle->aiff.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; 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) } } dapi = 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 (!fmt) fail ("no fmt chunk\n") if (!data) fail ("no data chunk\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 AFwriteWAV ---------------------------------------------------------------------------*/ AFfilehandle AFwriteWAV (FHandle file,AFfilesetup setup) { int i; int j; int found; aiffHandle handleAct; AFfilehandle handle = &handleAct; int chunksize; unsigned int uitemp; short stemp; unsigned short ustemp; unsigned char uctemp; char idtemp [4]; int bytes; int bitWidth; int byteWidth; unsigned int byteRate; unsigned short blockAlign; int stringsize; 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 ("RIFF") // Don't know length yet (will update later) uiwrite (0); // Reset counter as count doesn't include FORM or count itself handle->actualBytes = 0; idwrite ("WAVE") idwrite ("fmt ") chunksize = 16; uiwrite (chunksize) // Note will always save 8, 16 or 32 bit samples byteWidth = ((handle->aiff.width + 7) / 8); if (byteWidth == 3) byteWidth++; bitWidth = byteWidth * 8; byteRate = handle->aiff.channels * ((unsigned int) handle->aiff.rate) * byteWidth; blockAlign = handle->aiff.channels * byteWidth; uswrite (WAVE_FORMAT_PCM) uswrite (handle->aiff.channels) uiwrite (handle->aiff.rate) uiwrite (byteRate) uswrite (blockAlign) uswrite (bitWidth) if (handle->aiff.marks && !SaveBasicWavs) { idwrite ("cue ") chunksize = 4; // Space for number of markers for (i=0; iaiff.marks; i++) chunksize += 24; uiwrite (chunksize) uiwrite (handle->aiff.marks) for (i=0; iaiff.marks; i++) { uiwrite (handle->aiff.mark [i].id) uiwrite (i) idwrite ("data") uiwrite (0) uiwrite (0) uiwrite (handle->aiff.mark [i].position) } idwrite ("LIST") chunksize = 4; // Space for "adtl" for (i=0; iaiff.marks; i++) { chunksize += 12; // Space for "labl", chunksize, mark id if (handle->aiff.mark [i].name) stringsize = strlen (handle->aiff.mark [i].name); else stringsize = 0; chunksize += stringsize + 1; // Space for name and null if (!(stringsize % 2)) chunksize++; // Space for padding byte } uiwrite (chunksize) idwrite ("adtl") for (i=0; iaiff.marks; i++) { idwrite ("labl") chunksize = 4; // Space for mark id if (handle->aiff.mark [i].name) stringsize = strlen (handle->aiff.mark [i].name); else stringsize = 0; chunksize += stringsize + 1; // Space for name and null uiwrite (chunksize) uiwrite (handle->aiff.mark [i].id) if (stringsize) if (!mWrite (file,handle->aiff.mark [i].name,stringsize)) return AF_NULL_FILEHANDLE; handle->actualBytes += stringsize; ucwrite (0) if (!(stringsize % 2)) ucwrite (0) } } if (handle->aiff.insts && !SaveBasicWavs) { for (i=0; iaiff.insts; i++) { // This is a non-standard header - DAP instrument idwrite ("dapi") chunksize = 12; uiwrite (chunksize) // 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.miscs && !SaveBasicWavs) { idwrite ("LIST") chunksize = 4; // Space for "INFO" for (i=0; iaiff.miscs; i++) { if (handle->aiff.misc [i].type == AF_MISC_AIFF_NAME) chunksize += 4; // Space for "INAM" else if (handle->aiff.misc [i].type == AF_MISC_AIFF_AUTH) chunksize += 4; // Space for "IENG" else if (handle->aiff.misc [i].type == AF_MISC_AIFF_COPY) chunksize += 4; // Space for "ICOP" else if (handle->aiff.misc [i].type == AF_MISC_AIFF_ANNO) chunksize += 4; // Space for "ICMT" else continue; if (handle->aiff.misc [i].data) { chunksize += 4; // For chunksize chunksize += handle->aiff.misc [i].size + 1; // For string and null if (!(handle->aiff.misc [i].size % 2)) chunksize++; // Space for padding byte } else { chunksize += 6; // Space for chunksize and null ZSTR } } uiwrite (chunksize) idwrite ("INFO") for (i=0; iaiff.miscs; i++) { if (handle->aiff.misc [i].type == AF_MISC_AIFF_NAME) idwrite ("INAM") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_AUTH) idwrite ("IENG") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_COPY) idwrite ("ICOP") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_ANNO) idwrite ("ICMT") else continue; if (handle->aiff.misc [i].data) { chunksize = handle->aiff.misc [i].size + 1; uiwrite (chunksize) if (!mWrite (file,handle->aiff.misc [i].data,handle->aiff.misc [i].size)) return AF_NULL_FILEHANDLE; handle->actualBytes += handle->aiff.misc [i].size; ucwrite (0) if (!(handle->aiff.misc [i].size % 2)) ucwrite (0) } else { // Write a zero length ZSTR chunksize = 1; uiwrite (chunksize) ucwrite (0) ucwrite (0) } } } // Write sample data chunk header and reset frame counter idwrite ("data") // Don't know length yet uiwrite (0) mFlush (file); handle = (AFfilehandle) calloc (1,sizeof (aiffHandle)); *handle = handleAct; return handle; } /*--------------------------------------------------------------------------- | FUNCTION AFclosefileWAV ---------------------------------------------------------------------------*/ int AFclosefileWAV (AFfilehandle handle) { int i; int j; int found; int chunksize; int itemp; unsigned int uitemp; short stemp; unsigned short ustemp; unsigned char uctemp; char idtemp [4]; FHandle file; int bitWidth; int byteWidth; unsigned int byteRate; unsigned short blockAlign; int stringsize; 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 ("RIFF") // Update length iupdate (handle->actualBytes); idupdate ("WAVE") idupdate ("fmt ") chunksize = 16; uiupdate (chunksize) // Note will always save 8, 16 or 32 bit samples byteWidth = ((handle->aiff.width + 7) / 8); if (byteWidth == 3) byteWidth++; bitWidth = byteWidth * 8; byteRate = handle->aiff.channels * ((unsigned int) handle->aiff.rate) * byteWidth; blockAlign = handle->aiff.channels * byteWidth; usupdate (WAVE_FORMAT_PCM) usupdate (handle->aiff.channels) uiupdate (handle->aiff.rate) uiupdate (byteRate) usupdate (blockAlign) usupdate (bitWidth) if (handle->aiff.marks && !SaveBasicWavs) { idupdate ("cue ") chunksize = 4; // Space for number of markers; for (i=0; iaiff.marks; i++) chunksize += 24; uiupdate (chunksize) uiupdate (handle->aiff.marks) for (i=0; iaiff.marks; i++) { uiupdate (handle->aiff.mark [i].id) uiupdate (i) idupdate ("data") uiupdate (0) uiupdate (0) uiupdate (handle->aiff.mark [i].position) } idupdate ("LIST") chunksize = 4; // Space for "adtl" for (i=0; iaiff.marks; i++) { chunksize += 12; // Space for "labl", chunksize, mark id if (handle->aiff.mark [i].name) stringsize = strlen (handle->aiff.mark [i].name); else stringsize = 0; chunksize += stringsize + 1; // Space for name and null if (!(stringsize % 2)) chunksize++; // Space for padding byte } uiupdate (chunksize) idupdate ("adtl") for (i=0; iaiff.marks; i++) { idupdate ("labl") chunksize = 4; // Space for mark id if (handle->aiff.mark [i].name) stringsize = strlen (handle->aiff.mark [i].name); else stringsize = 0; chunksize += stringsize + 1; // Space for name and null uiupdate (chunksize) uiupdate (handle->aiff.mark [i].id) if (stringsize) if (!mWrite (file,handle->aiff.mark [i].name,stringsize)) return AF_NULL_FILEHANDLE; handle->actualBytes += stringsize; ucupdate (0) if (!(stringsize % 2)) ucupdate(0) } } if (handle->aiff.insts && !SaveBasicWavs) { for (i=0; iaiff.insts; i++) { // This is a non-standard header - DAP instrument idupdate ("dapi") chunksize = 12; uiupdate (chunksize) // 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.miscs && !SaveBasicWavs) { idupdate ("LIST") chunksize = 4; // Space for "INFO" for (i=0; iaiff.miscs; i++) { if (handle->aiff.misc [i].type == AF_MISC_AIFF_NAME) chunksize += 4; // Space for "INAM" else if (handle->aiff.misc [i].type == AF_MISC_AIFF_AUTH) chunksize += 4; // Space for "IENG" else if (handle->aiff.misc [i].type == AF_MISC_AIFF_COPY) chunksize += 4; // Space for "ICOP" else if (handle->aiff.misc [i].type == AF_MISC_AIFF_ANNO) chunksize += 4; // Space for "ICMT" else continue; if (handle->aiff.misc [i].data) { chunksize += 4; // For chunksize chunksize += handle->aiff.misc [i].size + 1; // For string and null if (!(handle->aiff.misc [i].size % 2)) chunksize++; // Space for padding byte } else { chunksize += 6; // Space for chunksize and null ZSTR } } uiupdate (chunksize) idupdate ("INFO") for (i=0; iaiff.miscs; i++) { if (handle->aiff.misc [i].type == AF_MISC_AIFF_NAME) idupdate ("INAM") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_AUTH) idupdate ("IENG") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_COPY) idupdate ("ICOP") else if (handle->aiff.misc [i].type == AF_MISC_AIFF_ANNO) idupdate ("ICMT") else continue; if (handle->aiff.misc [i].data) { chunksize = handle->aiff.misc [i].size + 1; uiupdate (chunksize) if (!mWrite (file,handle->aiff.misc [i].data,handle->aiff.misc [i].size)) return AF_NULL_FILEHANDLE; handle->actualBytes += handle->aiff.misc [i].size; ucupdate (0) if (!(handle->aiff.misc [i].size % 2)) ucupdate (0) } else { // Write a zero length ZSTR chunksize = 1; uiupdate (chunksize) ucupdate (0) ucupdate (0) } } } // Update sample data chunk header and reset frame counter idupdate ("data") // Update chunk size chunksize = handle->aiff.framecount * handle->aiff.channels; byteWidth = ((handle->aiff.width + 7) / 8); if (byteWidth == 3) byteWidth++; chunksize *= byteWidth; uiupdate (chunksize) if (mClose (handle->file) == -1) return -1; free (handle); return 0; } return -1; } /*--------------------------------------------------------------------------- | FUNCTION AFreadframesWAV ---------------------------------------------------------------------------*/ int AFreadframesWAV (AFfilehandle handle,void *frames,int count) { int i; int j; int frameCount; FHandle file; unsigned char uctemp; short stemp; int itemp; if (!handle) 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 (!ucRead (file,&uctemp)) return frameCount; ((signed char *) frames) [i++] = uctemp - MAX7; } 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 AFwriteframesWAV ---------------------------------------------------------------------------*/ int AFwriteframesWAV (AFfilehandle handle,void *frames,int count) { int i; int j; int frameCount; FHandle file; unsigned char uctemp; short stemp; int itemp; if (!handle) 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) { uctemp = ((signed char *) frames) [i++] + MAX7; if (!ucWrite (file,uctemp)) return frameCount; handle->actualBytes += sizeof (uctemp); } 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; } /***************************************************************************/