int RiffFile::open(const char* path) { // Open the file mpFile = fopen(path, "rb"); if(!mpFile) { return 1; // error } RiffChunkHeader root_chunk; // Read the header info for the root chunk. if (fread(&root_chunk, sizeof(UInt32), 3, mpFile) != 3) { return 1; // error } root_chunk.chunkSize -= sizeof(UInt32); // root chunk has an extra format code in header. // Save the location of the root data segment. root_chunk.dataStart = ftell(mpFile); if(root_chunk.chunkId != STR2FOURCC("RIFF") || root_chunk.dataStart < 0) { return 1; // error } mChunkStack.push_back(root_chunk); return 0; // success }
int WaveFile::open(const char *path) { int status = RiffFile::open(path); if(status != 0) return status; char s[5]; FOURCC2STR(formatCode(), s); printf("type = %s\n", s); if(formatCode() != STR2FOURCC("WAVE")) { return 1; // error } // Jump into the "fmt " chunk if(push(STR2FOURCC("fmt "))) { memset(&mHeader, 0, sizeof(mHeader)); UInt32 fmtSize = chunkSize(); if(RiffFile::readData(&mHeader, fmtSize) != fmtSize) { return 1; // error } assert(mHeader.formatTag == 1); // only uncompressed files are supported // Some writers put a bad block align and/or avgBytesPerSecond value. // Let's recalculate it. mHeader.bytesPerFrame = mHeader.bitsPerSample / 8 * mHeader.numChannels; mHeader.averageBytesPerSecond = mHeader.bytesPerFrame * mHeader.samplesPerSecond; } // Jump out of the "fmt " chunk pop(); // Jump into the "data" chunk if(!push(STR2FOURCC("data"))) { return 1; // error, couldn't find the data chunk } return 0; // success }
bool RiffFile::push(UInt32 chunkId) { long start_pos = ftell(mpFile); RiffChunkHeader parent_chunk = mChunkStack.back(); // Seek to start of current chunk, and iterate over children looking for desired chunk id. fseek(mpFile, parent_chunk.dataStart, SEEK_SET); RiffChunkHeader child_chunk;// = (RiffChunkHeader *)malloc(sizeof(RiffChunkHeader)); child_chunk.formatCode = 0; long parent_end = parent_chunk.dataStart + parent_chunk.chunkSize; while(!feof(mpFile) && ftell(mpFile) < parent_end) { // Read the full header of this child. if(fread(&child_chunk, sizeof(UInt32), 2, mpFile) != 2) break; // something went wrong. bail. if(child_chunk.chunkId == STR2FOURCC("RIFF") || child_chunk.chunkId == STR2FOURCC("LIST")) { if(fread(&child_chunk.formatCode, sizeof(UInt32), 1, mpFile) != 1) break; child_chunk.chunkSize -= sizeof(UInt32); } child_chunk.dataStart = ftell(mpFile); // If this child is the one we're looking for, push it and return. if(child_chunk.chunkId == chunkId) { mChunkStack.push_back(child_chunk); fseek(mpFile, mChunkStack.back().dataStart, SEEK_SET); return true; } // Find the start of our next sibling. long next_sibling_start = child_chunk.dataStart + child_chunk.chunkSize; next_sibling_start += next_sibling_start % 2; // word align fseek(mpFile, next_sibling_start, SEEK_SET); } clearerr(mpFile); fseek(mpFile, start_pos, SEEK_SET); return false; }