status CAFFile::readInit(AFfilesetup setup) { m_fh->seek(8, File::SeekFromBeginning); if (!allocateTrack()) return AF_FAIL; off_t currentOffset = m_fh->tell(); off_t fileLength = m_fh->length(); while (currentOffset < fileLength) { Tag chunkType; int64_t chunkLength; if (!readTag(&chunkType) || !readS64(&chunkLength)) return AF_FAIL; currentOffset += 12; if (chunkType == "data" && chunkLength == -1) chunkLength = fileLength - currentOffset; else if (chunkLength < 0) _af_error(AF_BAD_HEADER, "invalid chunk length %jd for chunk type %s\n", static_cast<intmax_t>(chunkLength), chunkType.name().c_str()); if (chunkType == "desc") { if (parseDescription(chunkType, chunkLength) == AF_FAIL) return AF_FAIL; } else if (chunkType == "data") { if (parseData(chunkType, chunkLength) == AF_FAIL) return AF_FAIL; } currentOffset = m_fh->seek(currentOffset + chunkLength, File::SeekFromBeginning); } return AF_SUCCEED; }
status WAVEFile::readInit(AFfilesetup setup) { Tag type, formtype; uint32_t size; uint32_t index = 0; bool hasFormat = false; bool hasData = false; bool hasCue = false; bool hasList = false; bool hasPlayList = false; bool hasFrameCount = false; bool hasINST = false; Track *track = allocateTrack(); fh->seek(0, File::SeekFromBeginning); readTag(&type); readU32(&size); readTag(&formtype); assert(type == "RIFF"); assert(formtype == "WAVE"); #ifdef DEBUG printf("size: %d\n", size); #endif /* Include the offset of the form type. */ index += 4; while (index < size) { Tag chunkid; uint32_t chunksize = 0; status result; #ifdef DEBUG printf("index: %d\n", index); #endif readTag(&chunkid); readU32(&chunksize); #ifdef DEBUG printf("%s size: %d\n", chunkid.name().c_str(), chunksize); #endif if (chunkid == "fmt ") { result = parseFormat(chunkid, chunksize); if (result == AF_FAIL) return AF_FAIL; hasFormat = true; } else if (chunkid == "data") { /* The format chunk must precede the data chunk. */ if (!hasFormat) { _af_error(AF_BAD_HEADER, "missing format chunk in WAVE file"); return AF_FAIL; } result = parseData(chunkid, chunksize); if (result == AF_FAIL) return AF_FAIL; hasData = true; } else if (chunkid == "inst") { result = parseInstrument(chunkid, chunksize); if (result == AF_FAIL) return AF_FAIL; } else if (chunkid == "fact") { hasFrameCount = true; result = parseFrameCount(chunkid, chunksize); if (result == AF_FAIL) return AF_FAIL; } else if (chunkid == "cue ") { hasCue = true; result = parseCues(chunkid, chunksize); if (result == AF_FAIL) return AF_FAIL; } else if (chunkid == "LIST" || chunkid == "list") { hasList = true; result = parseList(chunkid, chunksize); if (result == AF_FAIL) return AF_FAIL; } else if (chunkid == "INST") { hasINST = true; result = parseInstrument(chunkid, chunksize); if (result == AF_FAIL) return AF_FAIL; } else if (chunkid == "plst") { hasPlayList = true; result = parsePlayList(chunkid, chunksize); if (result == AF_FAIL) return AF_FAIL; } index += chunksize + 8; /* All chunks must be aligned on an even number of bytes */ if ((index % 2) != 0) index++; fh->seek(index + 8, File::SeekFromBeginning); } /* The format chunk and the data chunk are required. */ if (!hasFormat || !hasData) { return AF_FAIL; } /* At this point we know that the file has a format chunk and a data chunk, so we can assume that track->f and track->data_size have been initialized. */ if (!hasFrameCount) { track->totalfframes = track->data_size / (int) _af_format_frame_size(&track->f, false); } if (track->f.compressionType != AF_COMPRESSION_NONE && (track->f.compressionType == AF_COMPRESSION_G711_ULAW || track->f.compressionType == AF_COMPRESSION_G711_ALAW)) { track->totalfframes = track->data_size / track->f.channelCount; } /* A return value of AF_SUCCEED indicates successful parsing. */ return AF_SUCCEED; }
status IFFFile::readInit(AFfilesetup setup) { m_fh->seek(0, File::SeekFromBeginning); Tag type; uint32_t size; Tag formtype; readTag(&type); readU32(&size); readTag(&formtype); if (type != "FORM" || formtype != "8SVX") return AF_FAIL; /* IFF/8SVX files have only one track. */ Track *track = allocateTrack(); if (!track) return AF_FAIL; /* Set the index to include the form type ('8SVX' in this case). */ size_t index = 4; while (index < size) { Tag chunkid; uint32_t chunksize = 0; status result = AF_SUCCEED; readTag(&chunkid); readU32(&chunksize); if (chunkid == "VHDR") { result = parseVHDR(chunkid, chunksize); } else if (chunkid == "BODY") { result = parseBODY(chunkid, chunksize); } else if (chunkid == "NAME" || chunkid == "AUTH" || chunkid == "(c) " || chunkid == "ANNO") { parseMiscellaneous(chunkid, chunksize); } if (result == AF_FAIL) return AF_FAIL; /* Increment the index by the size of the chunk plus the size of the chunk header. */ index += chunksize + 8; /* All chunks must be aligned on an even number of bytes. */ if ((index % 2) != 0) index++; /* Set the seek position to the beginning of the next chunk. */ m_fh->seek(index + 8, File::SeekFromBeginning); } /* The file has been successfully parsed. */ return AF_SUCCEED; }
status SampleVisionFile::readInit(AFfilesetup) { m_fh->seek(0, File::SeekFromBeginning); char magic[kSMPMagicLength]; if (m_fh->read(magic, kSMPMagicLength) != (ssize_t) kSMPMagicLength) return AF_FAIL; if (strncmp(magic, kSMPMagic, kSMPMagicLength) != 0) return AF_FAIL; char version[kSMPVersionLength]; if (m_fh->read(version, kSMPVersionLength) != (ssize_t) kSMPVersionLength) return AF_FAIL; if (strncmp(version, kSMPVersion, kSMPVersionLength) != 0) return AF_FAIL; Track *track = allocateTrack(); char name[kSMPNameLength + 1]; m_fh->read(name, kSMPNameLength); name[kSMPNameLength] = '\0'; trimTrailingSpaces(name); if (strlen(name) > 0) addMiscellaneous(AF_MISC_NAME, name); char comment[kSMPCommentLength + 1]; m_fh->read(comment, kSMPCommentLength); comment[kSMPCommentLength] = '\0'; trimTrailingSpaces(comment); if (strlen(comment) > 0) addMiscellaneous(AF_MISC_COMMENT, comment); uint32_t frameCount; readU32(&frameCount); track->totalfframes = frameCount; track->fpos_first_frame = m_fh->tell(); track->data_size = 2 * frameCount; m_fh->seek(track->data_size, File::SeekFromCurrent); uint16_t reserved; readU16(&reserved); parseLoops(); parseMarkers(); uint8_t midiNote; uint32_t sampleRate; uint32_t smpteOffset; uint32_t cycleLength; readU8(&midiNote); readU32(&sampleRate); readU32(&smpteOffset); readU32(&cycleLength); track->f.byteOrder = AF_BYTEORDER_LITTLEENDIAN; track->f.sampleRate = sampleRate; track->f.channelCount = 1; track->f.compressionType = AF_COMPRESSION_NONE; track->f.framesPerPacket = 1; _af_set_sample_format(&track->f, AF_SAMPFMT_TWOSCOMP, 16); track->f.computeBytesPerPacketPCM(); return AF_SUCCEED; }
status NeXTFile::readInit(AFfilesetup setup) { uint32_t id, offset, length, encoding, sampleRate, channelCount; fh->seek(0, File::SeekFromBeginning); fh->read(&id, 4); assert(!memcmp(&id, ".snd", 4)); readU32(&offset); readU32(&length); readU32(&encoding); readU32(&sampleRate); readU32(&channelCount); #ifdef DEBUG printf("id, offset, length, encoding, sampleRate, channelCount:\n" " %d %d %d %d %d %d\n", id, offset, length, encoding, sampleRate, channelCount); #endif Track *track = allocateTrack(); if (!track) return AF_FAIL; track->f.byteOrder = AF_BYTEORDER_BIGENDIAN; /* Override the compression type later if necessary. */ track->f.compressionType = AF_COMPRESSION_NONE; track->fpos_first_frame = offset; off_t lengthAvailable = fh->length() - offset; if (length == _AU_LENGTH_UNSPECIFIED || static_cast<off_t>(length) > lengthAvailable) length = lengthAvailable; track->data_size = length; switch (encoding) { case _AU_FORMAT_MULAW_8: track->f.sampleWidth = 16; track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; track->f.compressionType = AF_COMPRESSION_G711_ULAW; break; case _AU_FORMAT_ALAW_8: track->f.sampleWidth = 16; track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; track->f.compressionType = AF_COMPRESSION_G711_ALAW; break; case _AU_FORMAT_LINEAR_8: track->f.sampleWidth = 8; track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; break; case _AU_FORMAT_LINEAR_16: track->f.sampleWidth = 16; track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; break; case _AU_FORMAT_LINEAR_24: track->f.sampleWidth = 24; track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; break; case _AU_FORMAT_LINEAR_32: track->f.sampleWidth = 32; track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; break; case _AU_FORMAT_FLOAT: track->f.sampleWidth = 32; track->f.sampleFormat = AF_SAMPFMT_FLOAT; break; case _AU_FORMAT_DOUBLE: track->f.sampleWidth = 64; track->f.sampleFormat = AF_SAMPFMT_DOUBLE; break; default: /* This encoding method is not recognized. */ _af_error(AF_BAD_SAMPFMT, "bad sample format"); return AF_FAIL; } _af_set_sample_format(&track->f, track->f.sampleFormat, track->f.sampleWidth); track->f.sampleRate = sampleRate; track->f.channelCount = channelCount; int frameSize = _af_format_frame_size(&track->f, false); track->totalfframes = length / frameSize; #ifdef DEBUG printf("_af_next_read_init\n"); _af_print_filehandle(file); #endif /* The file has been parsed successfully. */ return AF_SUCCEED; }
status AVRFile::readInit(AFfilesetup setup) { uint32_t magic; char name[8]; uint16_t mono, resolution, sign, loop, midi; uint32_t rate, size, loopStart, loopEnd; char reserved[26]; char user[64]; m_fh->seek(0, File::SeekFromBeginning); if (m_fh->read(&magic, 4) != 4) { _af_error(AF_BAD_READ, "could not read AVR file header"); return AF_FAIL; } if (memcmp(&magic, "2BIT", 4) != 0) { _af_error(AF_BAD_FILEFMT, "file is not AVR format"); return AF_FAIL; } /* Read name. */ m_fh->read(name, 8); readU16(&mono); readU16(&resolution); readU16(&sign); readU16(&loop); readU16(&midi); readU32(&rate); readU32(&size); readU32(&loopStart); readU32(&loopEnd); m_fh->read(reserved, 26); m_fh->read(user, 64); Track *track = allocateTrack(); if (!track) return AF_FAIL; /* Use only low-order three bytes of sample rate. */ track->f.sampleRate = rate & 0xffffff; if (sign == 0) track->f.sampleFormat = AF_SAMPFMT_UNSIGNED; else if (sign == 0xffff) track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; else { _af_error(AF_BAD_SAMPFMT, "bad sample format in AVR file"); return AF_FAIL; } if (resolution != 8 && resolution != 16) { _af_error(AF_BAD_WIDTH, "bad sample width %d in AVR file", resolution); return AF_FAIL; } track->f.sampleWidth = resolution; track->f.byteOrder = AF_BYTEORDER_BIGENDIAN; if (mono == 0) track->f.channelCount = 1; else if (mono == 0xffff) track->f.channelCount = 2; else { _af_error(AF_BAD_CHANNELS, "invalid number of channels in AVR file"); return AF_FAIL; } track->f.compressionType = AF_COMPRESSION_NONE; track->f.framesPerPacket = 1; track->f.computeBytesPerPacketPCM(); _af_set_sample_format(&track->f, track->f.sampleFormat, track->f.sampleWidth); track->fpos_first_frame = m_fh->tell(); track->totalfframes = size; track->data_size = track->totalfframes * track->f.bytesPerFrame(false); track->nextfframe = 0; track->fpos_next_frame = track->fpos_first_frame; /* The file has been parsed successfully. */ return AF_SUCCEED; }
status NISTFile::readInit(AFfilesetup setup) { char header[NIST_SPHERE_HEADER_LENGTH + 1]; int intval; char strval[NIST_SPHERE_MAX_FIELD_LENGTH]; int sample_n_bytes; m_fh->seek(0, File::SeekFromBeginning); if (m_fh->read(header, NIST_SPHERE_HEADER_LENGTH) != NIST_SPHERE_HEADER_LENGTH) { _af_error(AF_BAD_READ, "Could not read NIST SPHERE file header"); return AF_FAIL; } header[NIST_SPHERE_HEADER_LENGTH] = '\0'; if (memcmp(header, "NIST_1A\n 1024\n", 16) != 0) { _af_error(AF_BAD_FILEFMT, "Bad NIST SPHERE file header"); return AF_FAIL; } Track *track = allocateTrack(); if (!track) return AF_FAIL; // Read channel count. if (nist_header_read_int(header, "channel_count", &intval)) { if (intval < 1) { _af_error(AF_BAD_CHANNELS, "invalid number of channels %d", intval); return AF_FAIL; } track->f.channelCount = intval; } else { _af_error(AF_BAD_HEADER, "number of channels not specified"); return AF_FAIL; } // Read number of bytes per sample. if (!nist_header_read_int(header, "sample_n_bytes", &sample_n_bytes)) { _af_error(AF_BAD_HEADER, "bytes per sample not specified"); return AF_FAIL; } track->f.framesPerPacket = 1; /* Since some older NIST SPHERE files lack a sample_coding field, if sample_n_bytes is 1, assume mu-law; otherwise assume linear PCM. */ track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP; if (sample_n_bytes == 1) { track->f.compressionType = AF_COMPRESSION_G711_ULAW; track->f.sampleWidth = 16; track->f.bytesPerPacket = track->f.channelCount; } else { track->f.compressionType = AF_COMPRESSION_NONE; track->f.sampleWidth = sample_n_bytes * 8; track->f.computeBytesPerPacketPCM(); } if (nist_header_read_string(header, "sample_coding", &intval, strval)) { if (strcmp(strval, "pcm") == 0) ; else if (strcmp(strval, "ulaw") == 0 || strcmp(strval, "mu-law") == 0) { track->f.compressionType = AF_COMPRESSION_G711_ULAW; track->f.sampleWidth = 16; } else if (strcmp(strval, "alaw") == 0) { track->f.compressionType = AF_COMPRESSION_G711_ALAW; track->f.sampleWidth = 16; } else { _af_error(AF_BAD_SAMPFMT, "unrecognized NIST SPHERE sample format %s", strval); return AF_FAIL; } } // Read string representing byte order. if (nist_header_read_string(header, "sample_byte_format", &intval, strval)) { if (intval > 1) { if (strncmp(strval, "01", 2) == 0) track->f.byteOrder = AF_BYTEORDER_LITTLEENDIAN; else track->f.byteOrder = AF_BYTEORDER_BIGENDIAN; } else track->f.byteOrder = _AF_BYTEORDER_NATIVE; } else { /* Fail if this field is not present and sample width is more than one byte. */ if (track->f.compressionType == AF_COMPRESSION_NONE && track->f.sampleWidth > 8) { _af_error(AF_BAD_HEADER, "sample byte order not specified"); return AF_FAIL; } } // Read significant bits per sample. if (nist_header_read_int(header, "sample_sig_bits", &intval)) { if (intval < 1 || intval > 32) { _af_error(AF_BAD_WIDTH, "invalid sample width %d bits\n", intval); return AF_FAIL; } /* Use specified significant bits value as the sample width for uncompressed data as long as the number of bytes per sample remains unchanged. */ if (track->f.compressionType == AF_COMPRESSION_NONE && (intval + 7) / 8 == sample_n_bytes) { track->f.sampleWidth = intval; } } // Read sample rate. if (nist_header_read_int(header, "sample_rate", &intval)) { if (intval <= 0) { _af_error(AF_BAD_RATE, "invalid sample rate %d Hz\n", intval); return AF_FAIL; } track->f.sampleRate = intval; } else { _af_error(AF_BAD_HEADER, "sample rate not specified"); return AF_FAIL; } // Read sample count. if (nist_header_read_int(header, "sample_count", &intval)) { track->totalfframes = intval; } else { _af_error(AF_BAD_HEADER, "number of samples not specified"); return AF_FAIL; } if (_af_set_sample_format(&track->f, track->f.sampleFormat, track->f.sampleWidth) == AF_FAIL) { return AF_FAIL; } track->fpos_first_frame = NIST_SPHERE_HEADER_LENGTH; track->data_size = m_fh->length() - NIST_SPHERE_HEADER_LENGTH; track->nextfframe = 0; track->fpos_next_frame = track->fpos_first_frame; return AF_SUCCEED; }
status VOCFile::readInit(AFfilesetup) { m_fh->seek(20, File::SeekFromBeginning); uint16_t dataOffset, version, checksum; readU16(&dataOffset); readU16(&version); readU16(&checksum); Track *track = allocateTrack(); bool hasExtendedInfo = false; bool foundSoundData = false; off_t position = m_fh->tell(); off_t fileLength = m_fh->length(); while (position < fileLength) { uint32_t blockHeader; if (!readU32(&blockHeader)) break; uint8_t blockType = blockHeader & 0xff; uint32_t blockSize = blockHeader >> 8; if (blockType == kVOCSoundData) { if (foundSoundData) { _af_error(AF_BAD_HEADER, "VOC file contains multiple sound data blocks"); return AF_FAIL; } foundSoundData = true; uint8_t frequencyDivisor, codec; readU8(&frequencyDivisor); readU8(&codec); if (!hasExtendedInfo) { track->f.channelCount = 1; track->f.sampleRate = 1000000 / (256 - frequencyDivisor); } track->f.compressionType = AF_COMPRESSION_NONE; track->f.byteOrder = AF_BYTEORDER_LITTLEENDIAN; track->f.framesPerPacket = 1; if (codec == kVOCFormatU8) { _af_set_sample_format(&track->f, AF_SAMPFMT_UNSIGNED, 8); track->f.computeBytesPerPacketPCM(); } else if (codec == kVOCFormatCreativeADPCM4_8 || codec == kVOCFormatCreativeADPCM3_8 || codec == kVOCFormatCreativeADPCM2_8) { _af_error(AF_BAD_NOT_IMPLEMENTED, "Creative ADPCM compression is not currently suppported"); return AF_FAIL; } else { _af_error(AF_BAD_CODEC_TYPE, "VOC file contains unrecognized codec type %d", codec); return AF_FAIL; } track->fpos_first_frame = m_fh->tell(); track->data_size = m_fh->length() - 1 - track->fpos_first_frame; track->computeTotalFileFrames(); } else if (blockType == kVOCExtendedInfo) { if (foundSoundData) { _af_error(AF_BAD_HEADER, "VOC extended information found after sound data"); return AF_FAIL; } hasExtendedInfo = true; uint16_t frequencyDivisor; uint8_t bitsPerSample; uint8_t isStereo; readU16(&frequencyDivisor); readU8(&bitsPerSample); readU8(&isStereo); track->f.sampleWidth = bitsPerSample; track->f.channelCount = isStereo ? 2 : 1; uint32_t frequencyDividend = 256000000 / (isStereo ? 2 : 1); track->f.sampleRate = frequencyDividend / (65536 - frequencyDivisor); } else if (blockType == kVOCSoundDataNew) { if (foundSoundData) { _af_error(AF_BAD_HEADER, "VOC file contains multiple sound data blocks"); return AF_FAIL; } foundSoundData = true; uint32_t sampleRate; uint8_t bitsPerSample, channels; uint16_t format; uint32_t pad; readU32(&sampleRate); readU8(&bitsPerSample); readU8(&channels); readU16(&format); readU32(&pad); if (!channels) { _af_error(AF_BAD_CHANNELS, "invalid file with 0 channels"); return AF_FAIL; } track->fpos_first_frame = m_fh->tell(); track->data_size = blockSize - 12; track->f.compressionType = AF_COMPRESSION_NONE; track->f.byteOrder = AF_BYTEORDER_LITTLEENDIAN; track->f.sampleRate = sampleRate; track->f.channelCount = channels; track->f.framesPerPacket = 1; if (format == kVOCFormatU8) { _af_set_sample_format(&track->f, AF_SAMPFMT_UNSIGNED, 8); track->f.computeBytesPerPacketPCM(); } else if (format == kVOCFormatS16) { _af_set_sample_format(&track->f, AF_SAMPFMT_TWOSCOMP, 16); track->f.computeBytesPerPacketPCM(); } else if (format == kVOCFormatAlaw) { track->f.compressionType = AF_COMPRESSION_G711_ALAW; track->f.byteOrder = _AF_BYTEORDER_NATIVE; track->f.bytesPerPacket = track->f.channelCount; _af_set_sample_format(&track->f, AF_SAMPFMT_TWOSCOMP, 16); } else if (format == kVOCFormatUlaw) { track->f.compressionType = AF_COMPRESSION_G711_ULAW; track->f.byteOrder = _AF_BYTEORDER_NATIVE; track->f.bytesPerPacket = track->f.channelCount; _af_set_sample_format(&track->f, AF_SAMPFMT_TWOSCOMP, 16); } else if (format == kVOCFormatCreativeADPCM4_8 || format == kVOCFormatCreativeADPCM3_8 || format == kVOCFormatCreativeADPCM2_8 || format == kVOCFormatCreativeADPCM4_16) { _af_error(AF_BAD_NOT_IMPLEMENTED, "Creative ADPCM compression is not currently supported"); return AF_FAIL; } else { _af_error(AF_BAD_CODEC_TYPE, "VOC file contains unrecognized codec type %d", format); return AF_FAIL; } track->computeTotalFileFrames(); } position += 4 + blockSize; m_fh->seek(position, File::SeekFromBeginning); } return AF_SUCCEED; }