int PreCacheFrameOffsets(MFMADDecoder *pDecoder) { MP3Header header; unsigned char headerBuffer[10]; int sampleRate = 0; uint32 filePos = MFFile_Tell(pDecoder->pFile); while(MFFile_Read(pDecoder->pFile, headerBuffer, 4)) { int validHeader = ReadMP3Header(&header, headerBuffer); sampleRate = header.samplerate; if(validHeader != 1) { if(pDecoder->frameCount >= pDecoder->numFrameOffsetsAllocated) { pDecoder->numFrameOffsetsAllocated *= 2; pDecoder->pFrameOffsets = (uint32*)MFHeap_Realloc(pDecoder->pFrameOffsets, sizeof(uint32) * pDecoder->numFrameOffsetsAllocated); } pDecoder->pFrameOffsets[pDecoder->frameOffsetCount++] = filePos; ++pDecoder->frameCount; MFFile_Seek(pDecoder->pFile, header.frameSize-4, MFSeek_Current); } else { // check if we have some other header.. ID3? if(!MFString_CaseCmpN((char*)headerBuffer, "TAG", 3)) { // read ID3 v1? ... // skip past it for now... MFFile_Seek(pDecoder->pFile, 128-4, MFSeek_Current); } else if(!MFString_CaseCmpN((char*)headerBuffer, "ID3", 3)) { // ID3 v2... MFFile_Read(pDecoder->pFile, headerBuffer + 4, 6); uint32 size = GetSynchSafeInt(headerBuffer + 6); // skip ID3 v2 data MFFile_Seek(pDecoder->pFile, size, MFSeek_Current); } else { // lost sync? :/ return 0; } } filePos = MFFile_Tell(pDecoder->pFile); } return sampleRate; }
long ztell_file_func(voidpf opaque, voidpf stream) { return MFFile_Tell((MFFile*)stream); }
MF_API long MFFile_StdTell(void* fileHandle) { return (long)MFFile_Tell((MFFile*)fileHandle); }
void CreateWAVStream(MFAudioStream *pStream, const char *pFilename) { MFCALLSTACK; // open wav file MFFile* hFile = MFFileSystem_Open(pFilename); if(!hFile) return; // attempt to cache the vorbis stream MFOpenDataCachedFile cachedOpen; cachedOpen.cbSize = sizeof(MFOpenDataCachedFile); cachedOpen.openFlags = MFOF_Read | MFOF_Binary | MFOF_Cached_CleanupBaseFile; cachedOpen.maxCacheSize = 256*1024; // 256k cache for wav stream should be heaps!! cachedOpen.pBaseFile = hFile; MFFile *pCachedFile = MFFile_Open(MFFileSystem_GetInternalFileSystemHandle(MFFSH_CachedFileSystem), &cachedOpen); if(pCachedFile) hFile = pCachedFile; RIFFHeader header; MFFile_Read(hFile, &header, sizeof(header)); if(header.RIFF != MFMAKEFOURCC('R', 'I', 'F', 'F') || header.WAVE != MFMAKEFOURCC('W', 'A', 'V', 'E')) return; // not a .wav file... // if everything's good, and it appears to be a valid wav file MFWAVStream *pWS = (MFWAVStream*)MFHeap_AllocAndZero(sizeof(MFWAVStream)); pStream->pStreamData = pWS; pWS->pStream = hFile; size_t read; size_t fptr = sizeof(header); do { MFFile_Seek(hFile, fptr, MFSeek_Begin); WAVChunk dataChunk; MFZeroMemory(&dataChunk, sizeof(dataChunk)); read = MFFile_Read(hFile, &dataChunk, sizeof(dataChunk)); fptr += sizeof(dataChunk) + dataChunk.size; if(dataChunk.id == MFMAKEFOURCC('f', 'm', 't', ' ')) { read = MFFile_Read(hFile, &pWS->format, dataChunk.size); if(pWS->format.cbSize) read = (size_t)MFFile_Seek(hFile, pWS->format.cbSize, MFSeek_Current); } else if(dataChunk.id == MFMAKEFOURCC('d', 'a', 't', 'a')) { pWS->dataOffset = (size_t)MFFile_Tell(hFile); pWS->dataSize = dataChunk.size; } } while(read); // return to the start of the audio data MFFile_Seek(pWS->pStream, (int)pWS->dataOffset, MFSeek_Begin); // calculate the track length pWS->sampleSize = (pWS->format.nChannels * pWS->format.wBitsPerSample) >> 3; pStream->trackLength = (float)(pWS->dataSize / pWS->sampleSize) / (float)pWS->format.nSamplesPerSec; // fill out the stream info pStream->streamInfo.sampleRate = pWS->format.nSamplesPerSec; pStream->streamInfo.channels = pWS->format.nChannels; pStream->streamInfo.bitsPerSample = pWS->format.wBitsPerSample; pStream->streamInfo.bufferLength = pWS->format.nSamplesPerSec; }