status _af_wave_update (AFfilehandle file) { _Track *track; track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); if (track->fpos_first_frame != 0) { size_t dataLength, fileLength; /* We call _af_format_frame_size to calculate the frame size of normal PCM data or compressed data. */ dataLength = track->totalfframes * _af_format_frame_size(&track->f, AF_FALSE); dataLength = HOST_TO_LENDIAN_INT32(dataLength); af_fseek(file->fh, track->fpos_first_frame - 4, SEEK_SET); af_fwrite(&dataLength, 4, 1, file->fh); fileLength = af_flength(file->fh); fileLength -= 8; fileLength = HOST_TO_LENDIAN_INT32(fileLength); af_fseek(file->fh, 4, SEEK_SET); af_fwrite(&fileLength, 4, 1, file->fh); } return AF_SUCCEED; }
static status next_write_header (AFfilehandle file) { _Track *track; int frameSize; uint32_t offset, length, encoding, sampleRate, channelCount; track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); frameSize = _af_format_frame_size(&track->f, false); offset = track->fpos_first_frame; length = track->totalfframes * frameSize; encoding = nextencodingtype(&track->f); sampleRate = track->f.sampleRate; channelCount = track->f.channelCount; if (af_fseek(file->fh, 0, SEEK_SET) != 0) _af_error(AF_BAD_LSEEK, "bad seek"); af_fwrite(".snd", 4, 1, file->fh); af_write_uint32_be(&offset, file->fh); af_write_uint32_be(&length, file->fh); af_write_uint32_be(&encoding, file->fh); af_write_uint32_be(&sampleRate, file->fh); af_write_uint32_be(&channelCount, file->fh); return AF_SUCCEED; }
static status WriteFrameCount (AFfilehandle file) { _Track *track = NULL; _WAVEInfo *waveinfo = NULL; u_int32_t factSize = 4; u_int32_t totalFrameCount; assert(file != NULL); track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); waveinfo = (_WAVEInfo *) file->formatSpecific; /* We only write the fact chunk for compressed audio. */ if (track->f.compressionType == AF_COMPRESSION_NONE) return AF_SUCCEED; /* If the offset for the fact chunk hasn't been set yet, set it to the file's current position. */ if (waveinfo->factOffset == 0) waveinfo->factOffset = af_ftell(file->fh); else af_fseek(file->fh, waveinfo->factOffset, SEEK_SET); af_fwrite("fact", 4, 1, file->fh); factSize = HOST_TO_LENDIAN_INT32(factSize); af_fwrite(&factSize, 4, 1, file->fh); totalFrameCount = HOST_TO_LENDIAN_INT32(track->totalfframes); af_fwrite(&totalFrameCount, 4, 1, file->fh); return AF_SUCCEED; }
static status WriteFrameCount (AFfilehandle file) { _Track *track = NULL; _WAVEInfo *waveinfo = NULL; uint32_t factSize = 4; uint32_t totalFrameCount; assert(file != NULL); track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); waveinfo = (_WAVEInfo *) file->formatSpecific; /* Omit the fact chunk only for uncompressed integer audio formats. */ if (track->f.compressionType == AF_COMPRESSION_NONE && (track->f.sampleFormat == AF_SAMPFMT_TWOSCOMP || track->f.sampleFormat == AF_SAMPFMT_UNSIGNED)) return AF_SUCCEED; /* If the offset for the fact chunk hasn't been set yet, set it to the file's current position. */ if (waveinfo->factOffset == 0) waveinfo->factOffset = af_ftell(file->fh); else af_fseek(file->fh, waveinfo->factOffset, SEEK_SET); af_fwrite("fact", 4, 1, file->fh); af_write_uint32_le(&factSize, file->fh); totalFrameCount = track->totalfframes; af_write_uint32_le(&totalFrameCount, file->fh); return AF_SUCCEED; }
int afSetTrackPCMMapping (AFfilehandle file, int trackid, double slope, double intercept, double minClip, double maxClip) { _Track *track; if (!_af_filehandle_ok(file)) return -1; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; /* NOTE: this is highly unusual: we don't ordinarily change track.f after the file is opened. PCM mapping is the exception because this information is not encoded in sound files' headers using today's formats, so the user will probably want to set this information on a regular basis. The defaults may or may not be what the user wants. */ track->f.pcm.slope = slope; track->f.pcm.intercept = intercept; track->f.pcm.minClip = minClip; track->f.pcm.maxClip = maxClip; track->ms.modulesdirty = AF_TRUE; return 0; }
/* Parse voice header chunk. */ static status ParseVHDR (AFfilehandle file, AFvirtualfile *fh, uint32_t type, size_t size) { _Track *track; uint32_t oneShotSamples, repeatSamples, samplesPerRepeat; uint16_t sampleRate; uint8_t octaves, compression; uint32_t volume; assert(!memcmp(&type, "VHDR", 4)); track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); af_read_uint32_be(&oneShotSamples, fh); af_read_uint32_be(&repeatSamples, fh); af_read_uint32_be(&samplesPerRepeat, fh); af_read_uint16_be(&sampleRate, fh); af_read_uint8(&octaves, fh); af_read_uint8(&compression, fh); af_read_uint32_be(&volume, fh); track->f.sampleWidth = 8; track->f.sampleRate = sampleRate; track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; track->f.compressionType = AF_COMPRESSION_NONE; track->f.byteOrder = AF_BYTEORDER_BIGENDIAN; track->f.channelCount = 1; _af_set_sample_format(&track->f, track->f.sampleFormat, track->f.sampleWidth); return AF_SUCCEED; }
static status next_write_header (AFfilehandle file) { _Track *track; int frameSize; u_int32_t offset, length, encoding, sampleRate, channelCount; track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); frameSize = _af_format_frame_size(&track->f, AF_FALSE); if (track->f.compressionType == AF_COMPRESSION_G711_ULAW || track->f.compressionType == AF_COMPRESSION_G711_ALAW) frameSize = frameSize / 2; offset = HOST_TO_BENDIAN_INT32(track->fpos_first_frame); length = HOST_TO_BENDIAN_INT32(track->totalfframes * frameSize); encoding = HOST_TO_BENDIAN_INT32(nextencodingtype(&track->f)); sampleRate = HOST_TO_BENDIAN_INT32(track->f.sampleRate); channelCount = HOST_TO_BENDIAN_INT32(track->f.channelCount); if (af_fseek(file->fh, 0, SEEK_SET) != 0) _af_error(AF_BAD_LSEEK, "bad seek"); af_fwrite(".snd", 4, 1, file->fh); af_fwrite(&offset, 4, 1, file->fh); af_fwrite(&length, 4, 1, file->fh); af_fwrite(&encoding, 4, 1, file->fh); af_fwrite(&sampleRate, 4, 1, file->fh); af_fwrite(&channelCount, 4, 1, file->fh); return AF_SUCCEED; }
/* Parse marker chunks, which contain the positions and names of loop markers. */ static status ParseMARK (AFfilehandle file, AFvirtualfile *fh, u_int32_t type, size_t size) { _Track *track; int i; u_int16_t numMarkers; assert(!memcmp(&type, "MARK", 4)); track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); af_fread(&numMarkers, sizeof (u_int16_t), 1, fh); numMarkers = BENDIAN_TO_HOST_INT16(numMarkers); track->markerCount = numMarkers; if (numMarkers) track->markers = _af_marker_new(numMarkers); for (i=0; i<numMarkers; i++) { u_int16_t markerID = 0; u_int32_t markerPosition = 0; u_int8_t sizeByte = 0; char *markerName = NULL; af_fread(&markerID, sizeof (u_int16_t), 1, fh); markerID = BENDIAN_TO_HOST_INT16(markerID); af_fread(&markerPosition, sizeof (u_int32_t), 1, fh); markerPosition = BENDIAN_TO_HOST_INT32(markerPosition); af_fread(&sizeByte, sizeof (unsigned char), 1, fh); markerName = _af_malloc(sizeByte + 1); af_fread(markerName, sizeof (unsigned char), sizeByte, fh); markerName[sizeByte] = '\0'; #ifdef DEBUG printf("marker id: %d, position: %d, name: %s\n", markerID, markerPosition, markerName); printf("size byte: %d\n", sizeByte); #endif /* If sizeByte is even, then 1+sizeByte (the length of the string) is odd. Skip an extra byte to make it even. */ if ((sizeByte % 2) == 0) af_fseek(fh, 1, SEEK_CUR); track->markers[i].id = markerID; track->markers[i].position = markerPosition; track->markers[i].name = markerName; track->markers[i].comment = _af_strdup(""); } return AF_SUCCEED; }
int afGetCompression (AFfilehandle file, int trackid) { _Track *track; if (!_af_filehandle_ok(file)) return -1; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; return track->f.compressionType; }
status _af_wave_update (AFfilehandle file) { _Track *track; _WAVEInfo *wave = (_WAVEInfo *) file->formatSpecific; track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); if (track->fpos_first_frame != 0) { u_int32_t dataLength, fileLength; /* Update the frame count chunk if present. */ WriteFrameCount(file); /* Update the length of the data chunk. */ af_fseek(file->fh, wave->dataSizeOffset, SEEK_SET); /* We call _af_format_frame_size to calculate the frame size of normal PCM data or compressed data. */ dataLength = (u_int32_t) track->totalfframes * _af_format_frame_size(&track->f, AF_FALSE); dataLength = HOST_TO_LENDIAN_INT32(dataLength); af_fwrite(&dataLength, 4, 1, file->fh); /* Update the length of the RIFF chunk. */ fileLength = (u_int32_t) af_flength(file->fh); fileLength -= 8; fileLength = HOST_TO_LENDIAN_INT32(fileLength); af_fseek(file->fh, 4, SEEK_SET); af_fwrite(&fileLength, 4, 1, file->fh); } /* Write the actual data that was set after initializing the miscellaneous IDs. The size of the data will be unchanged. */ WriteMiscellaneous(file); /* Write the new positions; the size of the data will be unchanged. */ WriteCues(file); return AF_SUCCEED; }
/* What is with these return values? */ int afGetAESChannelData (AFfilehandle file, int trackid, unsigned char buf[24]) { _Track *track; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; if (track->hasAESData == AF_FALSE) { if (buf) memset(buf, 0, 24); return 0; } if (buf) memcpy(buf, track->aesData, 24); return 1; }
static status ParseBODY (AFfilehandle file, AFvirtualfile *fh, uint32_t type, size_t size) { _Track *track; track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); /* IFF/8SVX files have only one audio channel with one byte per sample, so the number of frames is equal to the number of bytes. */ track->totalfframes = size; track->data_size = size; /* Sound data follows. */ track->fpos_first_frame = af_ftell(fh); return AF_SUCCEED; }
void afGetVirtualPCMMapping (AFfilehandle file, int trackid, double *slope, double *intercept, double *minClip, double *maxClip) { _Track *track; if (!_af_filehandle_ok(file)) return; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return; if (slope) *slope = track->v.pcm.slope; if (intercept) *intercept = track->v.pcm.intercept; if (minClip) *minClip = track->v.pcm.minClip; if (maxClip) *maxClip = track->v.pcm.maxClip; }
int afSetVirtualPCMMapping (AFfilehandle file, int trackid, double slope, double intercept, double minClip, double maxClip) { _Track *track; if (!_af_filehandle_ok(file)) return -1; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; track->v.pcm.slope = slope; track->v.pcm.intercept = intercept; track->v.pcm.minClip = minClip; track->v.pcm.maxClip = maxClip; track->ms.modulesdirty = AF_TRUE; return 0; }
void afSetAESChannelData (AFfilehandle file, int trackid, unsigned char buf[24]) { _Track *track; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return; if (!_af_filehandle_can_write(file)) return; if (track->hasAESData) { memcpy(track->aesData, buf, 24); } else { _af_error(AF_BAD_NOAESDATA, "unable to store AES channel status data for track %d", trackid); } }
static status WriteData (AFfilehandle file) { _Track *track; uint32_t chunkSize; _WAVEInfo *waveinfo; assert(file); waveinfo = file->formatSpecific; track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); af_fwrite("data", 4, 1, file->fh); waveinfo->dataSizeOffset = af_ftell(file->fh); chunkSize = (int) _af_format_frame_size(&track->f, false) * track->totalfframes; af_write_uint32_le(&chunkSize, file->fh); track->fpos_first_frame = af_ftell(file->fh); return AF_SUCCEED; }
status _af_avr_update (AFfilehandle file) { _Track *track; uint32_t size, loopStart, loopEnd; track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); /* Seek to the position of the size field. */ af_fseek(file->fh, 26, SEEK_SET); size = track->totalfframes; /* For the case of no loops, loopStart = 0 and loopEnd = size. */ loopStart = 0; loopEnd = size; af_write_uint32_be(&size, file->fh); af_write_uint32_be(&loopStart, file->fh); af_write_uint32_be(&loopEnd, file->fh); return AF_SUCCEED; }
static status WriteData (AFfilehandle file) { _Track *track; u_int32_t frameSize, chunkSize; _WAVEInfo *waveinfo; assert(file); waveinfo = file->formatSpecific; track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); af_fwrite("data", 4, 1, file->fh); waveinfo->dataSizeOffset = af_ftell(file->fh); frameSize = _af_format_frame_size(&track->f, AF_FALSE); chunkSize = frameSize * track->totalfframes; chunkSize = HOST_TO_LENDIAN_INT32(chunkSize); af_fwrite(&chunkSize, 4, 1, file->fh); track->fpos_first_frame = af_ftell(file->fh); return AF_SUCCEED; }
/* Parse AES recording data. */ static status ParseAESD (AFfilehandle file, AFvirtualfile *fh, u_int32_t type, size_t size) { _Track *track; unsigned char aesChannelStatusData[24]; assert(!memcmp(&type, "AESD", 4)); assert(size == 24); track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); track->hasAESData = AF_TRUE; /* Try to read 24 bytes of AES nonaudio data from the file. Fail if the file disappoints. */ if (af_fread(aesChannelStatusData, 1, 24, fh) != 24) return AF_FAIL; memcpy(track->aesData, aesChannelStatusData, 24); return AF_SUCCEED; }
/* Parse the stored sound chunk, which usually contains little more than the sound data. */ static status ParseSSND (AFfilehandle file, AFvirtualfile *fh, u_int32_t type, size_t size) { _Track *track; u_int32_t offset, blockSize; assert(!memcmp(&type, "SSND", 4)); track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); af_fread(&offset, sizeof (u_int32_t), 1, fh); offset = BENDIAN_TO_HOST_INT32(offset); af_fread(&blockSize, sizeof (u_int32_t), 1, fh); blockSize = BENDIAN_TO_HOST_INT32(blockSize); /* This seems like a reasonable way to calculate the number of bytes in an SSND chunk. */ track->data_size = size - 8 - offset; #ifdef DEBUG printf("offset: %d\n", offset); printf("block size: %d\n", blockSize); #endif track->fpos_first_frame = af_ftell(fh) + offset; #ifdef DEBUG printf("data start: %d\n", track->fpos_first_frame); #endif /* Sound data follows. */ return AF_SUCCEED; }
status _af_next_write_init (AFfilesetup setup, AFfilehandle filehandle) { _Track *track; if (_af_filesetup_make_handle(setup, filehandle) == AF_FAIL) return AF_FAIL; filehandle->formatSpecific = NULL; if (filehandle->miscellaneousCount > 0) { _af_error(AF_BAD_NUMMISC, "NeXT format supports no miscellaneous chunks"); return AF_FAIL; } next_write_header(filehandle); track = _af_filehandle_get_track(filehandle, AF_DEFAULT_TRACK); track->fpos_first_frame = 28; track->f.byteOrder = AF_BYTEORDER_BIGENDIAN; return AF_SUCCEED; }
static status WriteFormat (AFfilehandle file) { _Track *track = NULL; uint16_t formatTag, channelCount; uint32_t sampleRate, averageBytesPerSecond; uint16_t blockAlign; uint32_t chunkSize; uint16_t bitsPerSample; assert(file != NULL); track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); af_fwrite("fmt ", 4, 1, file->fh); switch (track->f.compressionType) { case AF_COMPRESSION_NONE: chunkSize = 16; if (track->f.sampleFormat == AF_SAMPFMT_FLOAT || track->f.sampleFormat == AF_SAMPFMT_DOUBLE) { formatTag = WAVE_FORMAT_IEEE_FLOAT; } else if (track->f.sampleFormat == AF_SAMPFMT_TWOSCOMP || track->f.sampleFormat == AF_SAMPFMT_UNSIGNED) { formatTag = WAVE_FORMAT_PCM; } else { _af_error(AF_BAD_COMPTYPE, "bad sample format"); return AF_FAIL; } blockAlign = _af_format_frame_size(&track->f, false); bitsPerSample = 8 * _af_format_sample_size(&track->f, false); break; /* G.711 compression uses eight bits per sample. */ case AF_COMPRESSION_G711_ULAW: chunkSize = 18; formatTag = IBM_FORMAT_MULAW; blockAlign = track->f.channelCount; bitsPerSample = 8; break; case AF_COMPRESSION_G711_ALAW: chunkSize = 18; formatTag = IBM_FORMAT_ALAW; blockAlign = track->f.channelCount; bitsPerSample = 8; break; default: _af_error(AF_BAD_COMPTYPE, "bad compression type"); return AF_FAIL; } af_write_uint32_le(&chunkSize, file->fh); af_write_uint16_le(&formatTag, file->fh); channelCount = track->f.channelCount; af_write_uint16_le(&channelCount, file->fh); sampleRate = track->f.sampleRate; af_write_uint32_le(&sampleRate, file->fh); averageBytesPerSecond = track->f.sampleRate * _af_format_frame_size(&track->f, false); af_write_uint32_le(&averageBytesPerSecond, file->fh); blockAlign = _af_format_frame_size(&track->f, false); af_write_uint16_le(&blockAlign, file->fh); af_write_uint16_le(&bitsPerSample, file->fh); if (track->f.compressionType == AF_COMPRESSION_G711_ULAW || track->f.compressionType == AF_COMPRESSION_G711_ALAW) { uint16_t zero = 0; af_write_uint16_le(&zero, file->fh); } return AF_SUCCEED; }
/* Parse common data chunks, which contain information regarding the sampling rate, the number of sample frames, and the number of sound channels. */ static status ParseCOMM (AFfilehandle file, AFvirtualfile *fh, u_int32_t type, size_t size) { _Track *track; u_int16_t numChannels; u_int32_t numSampleFrames; u_int16_t sampleSize; unsigned char sampleRate[10]; assert(!memcmp(&type, "COMM", 4)); track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); af_fread(&numChannels, sizeof (u_int16_t), 1, fh); track->f.channelCount = BENDIAN_TO_HOST_INT16(numChannels); af_fread(&numSampleFrames, sizeof (u_int32_t), 1, fh); track->totalfframes = BENDIAN_TO_HOST_INT32(numSampleFrames); af_fread(&sampleSize, sizeof (u_int16_t), 1, fh); track->f.sampleWidth = BENDIAN_TO_HOST_INT16(sampleSize); af_fread(sampleRate, 10, 1, fh); track->f.sampleRate = _af_convert_from_ieee_extended(sampleRate); track->f.compressionType = AF_COMPRESSION_NONE; track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; track->f.byteOrder = AF_BYTEORDER_BIGENDIAN; if (file->fileFormat == AF_FILE_AIFFC) { u_int8_t compressionID[4]; /* Pascal strings are at most 255 bytes long. */ unsigned char compressionName[256]; unsigned char compressionNameLength; af_fread(compressionID, 4, 1, fh); /* Read the Pascal-style string containing the name. */ af_fread(&compressionNameLength, 1, 1, fh); af_fread(compressionName, compressionNameLength, 1, fh); compressionName[compressionNameLength] = '\0'; if (!memcmp(compressionID, "NONE", 4)) track->f.compressionType = AF_COMPRESSION_NONE; else if (!memcmp(compressionID, "ACE2", 4) || !memcmp(compressionID, "ACE8", 4) || !memcmp(compressionID, "MAC3", 4) || !memcmp(compressionID, "MAC6", 4)) { _af_error(AF_BAD_NOT_IMPLEMENTED, "AIFF-C format does not support Apple's proprietary %s compression format", compressionName); return AF_FAIL; } else if (!memcmp(compressionID, "ulaw", 4) || !memcmp(compressionID, "ULAW", 4)) { track->f.compressionType = AF_COMPRESSION_G711_ULAW; } else if (!memcmp(compressionID, "alaw", 4) || !memcmp(compressionID, "ALAW", 4)) { track->f.compressionType = AF_COMPRESSION_G711_ALAW; } else if (!memcmp(compressionID, "fl32", 4) || !memcmp(compressionID, "FL32", 4)) { track->f.sampleFormat = AF_SAMPFMT_FLOAT; track->f.sampleWidth = 32; track->f.compressionType = AF_COMPRESSION_NONE; } else if (!memcmp(compressionID, "fl64", 4) || !memcmp(compressionID, "FL64", 4)) { track->f.sampleFormat = AF_SAMPFMT_DOUBLE; track->f.sampleWidth = 64; track->f.compressionType = AF_COMPRESSION_NONE; } else if (!memcmp(compressionID, "sowt", 4)) { track->f.compressionType = AF_COMPRESSION_NONE; track->f.byteOrder = AF_BYTEORDER_LITTLEENDIAN; } else { _af_error(AF_BAD_NOT_IMPLEMENTED, "AIFF-C compression type '%c%c%c%c' not currently supported", compressionID[0], compressionID[1], compressionID[2], compressionID[3]); return AF_FAIL; } } _af_set_sample_format(&track->f, track->f.sampleFormat, track->f.sampleWidth); return AF_SUCCEED; }
status _af_avr_write_init (AFfilesetup setup, AFfilehandle filehandle) { _Track *track; char name[8]; uint16_t mono, resolution, sign, loop, midi; uint32_t rate, size, loopStart, loopEnd; char reserved[26]; char user[64]; if (_af_filesetup_make_handle(setup, filehandle) == AF_FAIL) return AF_FAIL; filehandle->formatSpecific = NULL; track = _af_filehandle_get_track(filehandle, AF_DEFAULT_TRACK); if (af_fseek(filehandle->fh, 0, SEEK_SET) != 0) { _af_error(AF_BAD_LSEEK, "bad seek"); return AF_FAIL; } af_fwrite("2BIT", 4, 1, filehandle->fh); memset(name, 0, 8); if (filehandle->fileName != NULL) strncpy(name, af_basename(filehandle->fileName), 8); af_fwrite(name, 8, 1, filehandle->fh); if (track->f.channelCount == 1) mono = 0x0; else mono = 0xffff; af_write_uint16_be(&mono, filehandle->fh); resolution = track->f.sampleWidth; af_write_uint16_be(&resolution, filehandle->fh); if (track->f.sampleFormat == AF_SAMPFMT_UNSIGNED) sign = 0x0; else sign = 0xffff; af_write_uint16_be(&sign, filehandle->fh); /* We do not currently support loops. */ loop = 0; af_write_uint16_be(&loop, filehandle->fh); midi = 0xffff; af_write_uint16_be(&midi, filehandle->fh); rate = track->f.sampleRate; /* Set the high-order byte of rate to 0xff. */ rate |= 0xff000000; size = track->totalfframes; loopStart = 0; loopEnd = size; af_write_uint32_be(&rate, filehandle->fh); af_write_uint32_be(&size, filehandle->fh); af_write_uint32_be(&loopStart, filehandle->fh); af_write_uint32_be(&loopEnd, filehandle->fh); memset(reserved, 0, 26); af_fwrite(reserved, 26, 1, filehandle->fh); memset(user, 0, 64); af_fwrite(user, 64, 1, filehandle->fh); if (track->fpos_first_frame == 0) track->fpos_first_frame = af_ftell(filehandle->fh); return AF_SUCCEED; }
static status WriteFormat (AFfilehandle file) { _Track *track = NULL; u_int16_t formatTag, channelCount; u_int32_t sampleRate, averageBytesPerSecond; u_int16_t blockAlign; u_int32_t chunkSize; u_int16_t bitsPerSample; _WAVEInfo *waveinfo = NULL; assert(file != NULL); track = _af_filehandle_get_track(file, AF_DEFAULT_TRACK); waveinfo = (_WAVEInfo *) file->formatSpecific; af_fwrite("fmt ", 4, 1, file->fh); switch (track->f.compressionType) { case AF_COMPRESSION_NONE: chunkSize = 16; formatTag = WAVE_FORMAT_PCM; blockAlign = _af_format_frame_size(&track->f, AF_FALSE); bitsPerSample = 8 * _af_format_sample_size(&track->f, AF_FALSE); break; case AF_COMPRESSION_G711_ULAW: chunkSize = 18; formatTag = IBM_FORMAT_MULAW; blockAlign = _af_format_frame_size(&track->f, AF_FALSE); bitsPerSample = 8 * _af_format_sample_size(&track->f, AF_FALSE); break; case AF_COMPRESSION_G711_ALAW: chunkSize = 18; formatTag = IBM_FORMAT_ALAW; blockAlign = _af_format_frame_size(&track->f, AF_FALSE); bitsPerSample = 8 * _af_format_sample_size(&track->f, AF_FALSE); break; default: _af_error(AF_BAD_COMPTYPE, "bad compression type"); return AF_FAIL; } chunkSize = HOST_TO_LENDIAN_INT32(chunkSize); af_fwrite(&chunkSize, 4, 1, file->fh); formatTag = HOST_TO_LENDIAN_INT16(formatTag); af_fwrite(&formatTag, 2, 1, file->fh); formatTag = LENDIAN_TO_HOST_INT16(formatTag); channelCount = track->f.channelCount; channelCount = HOST_TO_LENDIAN_INT16(channelCount); af_fwrite(&channelCount, 2, 1, file->fh); sampleRate = track->f.sampleRate; sampleRate = HOST_TO_LENDIAN_INT32(sampleRate); af_fwrite(&sampleRate, 4, 1, file->fh); averageBytesPerSecond = track->f.sampleRate * _af_format_frame_size(&track->f, AF_FALSE); averageBytesPerSecond = HOST_TO_LENDIAN_INT32(averageBytesPerSecond); af_fwrite(&averageBytesPerSecond, 4, 1, file->fh); blockAlign = _af_format_frame_size(&track->f, AF_FALSE); blockAlign = HOST_TO_LENDIAN_INT16(blockAlign); af_fwrite(&blockAlign, 2, 1, file->fh); bitsPerSample = HOST_TO_LENDIAN_INT16(bitsPerSample); af_fwrite(&bitsPerSample, 2, 1, file->fh); /* If the data is compressed we have additional format-specific information to write as well as the 'fact' (frame count) chunk. */ if (track->f.compressionType != AF_COMPRESSION_NONE) { u_int32_t factSize = 4; u_int32_t totalFrameCount = 0; if (track->f.compressionType == AF_COMPRESSION_G711_ULAW || track->f.compressionType == AF_COMPRESSION_G711_ALAW) { u_int16_t zero = 0; af_fwrite(&zero, 2, 1, file->fh); } af_fwrite("fact", 4, 1, file->fh); factSize = HOST_TO_LENDIAN_INT32(factSize); af_fwrite(&factSize, 4, 1, file->fh); waveinfo->fileSizeOffset = af_ftell(file->fh); totalFrameCount = HOST_TO_LENDIAN_INT32(totalFrameCount); af_fwrite(&totalFrameCount, 4, 1, file->fh); } return AF_SUCCEED; }
int afReadFrames (AFfilehandle file, int trackid, void *samples, int nvframeswanted) { _Track *track; _AFmoduleinst *firstmod; _AFchunk *userc; AFframecount nvframesleft, nvframes2read; int bytes_per_vframe; AFframecount vframe; if (!_af_filehandle_ok(file)) return -1; if (!_af_filehandle_can_read(file)) return -1; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; if (track->ms.modulesdirty) { if (_AFsetupmodules(file, track) != AF_SUCCEED) return -1; } /*if (file->seekok) {*/ if (af_fseek(file->fh, track->fpos_next_frame, SEEK_SET) < 0) { _af_error(AF_BAD_LSEEK, "unable to position read pointer at next frame"); return -1; } /* } */ if (track->totalvframes == -1) nvframes2read = nvframeswanted; else { nvframesleft = track->totalvframes - track->nextvframe; nvframes2read = (nvframeswanted > nvframesleft) ? nvframesleft : nvframeswanted; } bytes_per_vframe = _af_format_frame_size(&track->v, AF_TRUE); firstmod = &track->ms.module[track->ms.nmodules-1]; userc = &track->ms.chunk[track->ms.nmodules]; track->filemodhappy = AF_TRUE; vframe = 0; if (!track->ms.mustuseatomicnvframes) { assert(track->frames2ignore == 0); userc->buf = samples; userc->nframes = nvframes2read; (*firstmod->mod->run_pull)(firstmod); if (track->filemodhappy) vframe += userc->nframes; } else { bool eof = AF_FALSE; if (track->frames2ignore != 0) { userc->nframes = track->frames2ignore; userc->buf = _af_malloc(track->frames2ignore * bytes_per_vframe); if (userc->buf == AF_NULL) return 0; (*firstmod->mod->run_pull)(firstmod); /* Have we hit EOF? */ if (userc->nframes < track->frames2ignore) eof = AF_TRUE; track->frames2ignore = 0; free(userc->buf); userc->buf = NULL; } /* Now start reading useful frames, until EOF or premature EOF. */ while (track->filemodhappy && !eof && vframe < nvframes2read) { AFframecount nvframes2pull; userc->buf = (char *) samples + bytes_per_vframe * vframe; if (vframe <= nvframes2read - _AF_ATOMIC_NVFRAMES) nvframes2pull = _AF_ATOMIC_NVFRAMES; else nvframes2pull = nvframes2read - vframe; userc->nframes = nvframes2pull; (*firstmod->mod->run_pull)(firstmod); if (track->filemodhappy) { vframe += userc->nframes; if (userc->nframes < nvframes2pull) eof = AF_TRUE; } } } track->nextvframe += vframe; return vframe; }
int afWriteFrames (AFfilehandle file, int trackid, const void *samples, int nvframes2write) { _AFmoduleinst *firstmod; _AFchunk *userc; _Track *track; int bytes_per_vframe; AFframecount vframe; if (!_af_filehandle_ok(file)) return -1; if (!_af_filehandle_can_write(file)) return -1; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; if (track->ms.modulesdirty) { if (_AFsetupmodules(file, track) != AF_SUCCEED) return -1; } /*if (file->seekok) {*/ if (af_fseek(file->fh, track->fpos_next_frame, SEEK_SET) < 0) { _af_error(AF_BAD_LSEEK, "unable to position write pointer at next frame"); return -1; } /* } */ bytes_per_vframe = _af_format_frame_size(&track->v, AF_TRUE); firstmod = &track->ms.module[0]; userc = &track->ms.chunk[0]; track->filemodhappy = AF_TRUE; vframe = 0; #ifdef UNLIMITED_CHUNK_NVFRAMES /* OPTIMIZATION: see the comment at the very end of arrangemodules() in modules.c for an explanation of this: */ if (!trk->ms.mustuseatomicnvframes) { userc->buf = (char *)buf; userc->nframes = nvframes2write; (*firstmod->mod->run_push)(firstmod); /* Count this chunk if there was no i/o error. */ if (trk->filemodhappy) vframe += userc->nframes; } else #else /* Optimization must be off. */ assert(track->ms.mustuseatomicnvframes); #endif { while (vframe < nvframes2write) { userc->buf = (char *) samples + bytes_per_vframe * vframe; if (vframe <= nvframes2write - _AF_ATOMIC_NVFRAMES) userc->nframes = _AF_ATOMIC_NVFRAMES; else userc->nframes = nvframes2write - vframe; (*firstmod->mod->run_push)(firstmod); if (track->filemodhappy == AF_FALSE) break; vframe += userc->nframes; } } track->nextvframe += vframe; track->totalvframes += vframe; return vframe; }