Example #1
0
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;
}
Example #2
0
// read/write a file to a filesystem
MF_API char* MFFileSystem_Load(const char *pFilename, size_t *pBytesRead, size_t extraBytes)
{
	char *pBuffer = NULL;

	MFFile *hFile = MFFileSystem_Open(pFilename, MFOF_Read|MFOF_Binary);
	if(hFile)
	{
		uint64 size = MFFile_GetSize(hFile);

		if(size > 0)
		{
#if defined(MF_32BIT)
			if(size >= 1LL << 32)
			{
				MFDebug_Warn(1, MFStr("File is larger than the available address space!", pFilename));
				return NULL;
			}
#endif

			pBuffer = (char*)MFHeap_Alloc((size_t)size + extraBytes);

			size_t bytesRead = MFFile_Read(hFile, pBuffer, (size_t)size);

			if(extraBytes > 0)
				pBuffer[size] = 0;

			if(pBytesRead)
				*pBytesRead = bytesRead;
		}

		MFFile_Close(hFile);
	}

	return pBuffer;
}
Example #3
0
int F3DFile::ReadOBJ(const char *pFilename)
{
	pModel = this;

	MFFile *pFile = MFFileSystem_Open(pFilename, MFOF_Read);
	if(!pFile)
	{
		MFDebug_Warn(2, MFStr("Failed to open OBJ file %s", pFilename));
		return 1;
	}

	uint64 size = MFFile_Seek(pFile, 0, MFSeek_End);
	MFFile_Seek(pFile, 0, MFSeek_Begin);

	char *pMem = (char*)MFHeap_Alloc((size_t)size+1);
	MFFile_Read(pFile, pMem, size);
	pMem[size] = 0;

	MFFile_Close(pFile);

	ParseOBJFile(pMem);
	MFHeap_Free(pMem);

	return 0;
}
Example #4
0
size_t GetWAVSamples(MFAudioStream *pStream, void *pBuffer, size_t bytes)
{
	MFWAVStream *pWS = (MFWAVStream*)pStream->pStreamData;
	size_t read = MFFile_Read(pWS->pStream, pBuffer, MFMin(bytes, pWS->dataSize - pWS->sampleOffset));
	pWS->sampleOffset += read;
	return read;
}
uLong zread_file_func(voidpf opaque, voidpf stream, void* buf, uLong size)
{
	return MFFile_Read((MFFile*)stream, buf, size, false);
}
MF_API MFAnimation* MFAnimation_Create(const char *pFilename, MFModel *pModel)
{
	MFAnimationTemplate *pTemplate = MFAnimation_FindTemplate(pFilename);

	if(!pTemplate)
	{
		size_t size = 0;
		pTemplate = (MFAnimationTemplate*)MFModelInternal_PendingAnimationTemplate(&size);

		if(!pTemplate)
		{
			MFFile *hFile = MFFileSystem_Open(MFStr("%s.anm", pFilename), MFOF_Read|MFOF_Binary);

			if(hFile)
			{
				size = (size_t)MFFile_GetSize(hFile);

				if(size > 0)
				{
					char *pTemplateData;

					// allocate memory and load file
					pTemplateData = (char*)MFHeap_Alloc(size + MFString_Length(pFilename) + 1);
					MFFile_Read(hFile, pTemplateData, size);

					pTemplate = (MFAnimationTemplate*)pTemplateData;

					// check ID string
					MFDebug_Assert(pTemplate->hash == MFMAKEFOURCC('A', 'N', 'M', '2'), "Incorrect MFAnimation version.");
				}

				MFFile_Close(hFile);
			}
		}

		if(!pTemplate)
			return NULL;

		pFilename = MFString_Copy((char*)pTemplate + size, pFilename);

		MFAnimation_FixUp(pTemplate, true);
		MFResource_AddResource(pTemplate, MFRT_AnimationTemplate, MFUtil_HashString(pFilename) ^ 0xA010A010, pFilename);
	}

	// get the model bone chunk
	MFModelDataChunk *pBoneChunk = MFModel_GetDataChunk(pModel->pTemplate, MFChunkType_Bones);
	MFDebug_Assert(pBoneChunk, "Cant apply animation to a model with no skeleton!");

	// create and init instance
	MFAnimation *pAnimation;
	size_t bytes = MFALIGN16(sizeof(MFAnimation)) + sizeof(MFMatrix)*pBoneChunk->count + sizeof(int)*pBoneChunk->count + sizeof(MFAnimationCurrentFrame)*pBoneChunk->count;
	pAnimation = (MFAnimation*)MFHeap_Alloc(bytes);
	pAnimation->pModel = pModel;
	pAnimation->pTemplate = pTemplate;

	// add animation to model animation list
	pModel->pAnimation = pAnimation;

	// get bones pointer from model (for convenience)
	pAnimation->pBones = (MFModelBone*)pBoneChunk->pData;
	pAnimation->numBones = pBoneChunk->count;

	// set matrices to identity
	pAnimation->pMatrices = (MFMatrix*)MFALIGN16(&pAnimation[1]);
	for(int a=0; a<pBoneChunk->count; a++)
	{
		pAnimation->pMatrices[a] = MFMatrix::identity;
	}

	MFStateConstant_AnimationMatrices animMats;
	animMats.pMatrices = pAnimation->pMatrices;
	animMats.numMatrices = pAnimation->numBones;
	MFStateBlock_SetAnimMatrices(pModel->pEntityState, animMats);

	// build bone to animation stream mapping
	pAnimation->pBoneMap = (int*)MFALIGN16(&pAnimation->pMatrices[pBoneChunk->count]);
	for(int a=0; a<pBoneChunk->count; a++)
	{
		const char *pBoneName = MFModel_GetBoneName(pModel, a);

		// find bone in animation
		pAnimation->pBoneMap[a] = -1;
		for(uint32 b=0; b<pTemplate->numBones; b++)
		{
			if(!MFString_CaseCmp(pBoneName, pTemplate->pBones[b].pBoneName))
			{
				pAnimation->pBoneMap[a] = b;
				break;
			}
		}
	}

	pAnimation->pCustomMatrices = NULL;
	pAnimation->blendLayer.frameTime = pAnimation->pTemplate->startTime;

	pAnimation->blendLayer.pCurFrames = (MFAnimationCurrentFrame*)&pAnimation->pBoneMap[pBoneChunk->count];
	MFZeroMemory(pAnimation->blendLayer.pCurFrames, sizeof(MFAnimationCurrentFrame)*pBoneChunk->count);

	return pAnimation;
}
Example #7
0
// stdio signiture functions (these can be used as a callback to many libs and API's)
MF_API size_t MFFile_StdRead(void *pBuffer, size_t size, size_t count, void* fileHandle)
{
	return MFFile_Read((MFFile*)fileHandle, pBuffer, size*count, false);
}
Example #8
0
MF_API MFModel* MFModel_Create(const char *pFilename)
{
	const char* pOriginalFilename = pFilename;

	// see if it's already loaded
	MFModelPool::Iterator it = gModelBank.Get(pOriginalFilename);
	MFModelTemplate *pTemplate = it ? *it : NULL;

	if(!pTemplate)
	{
		char *pTemplateData = NULL;

		MFFile *hFile = MFFileSystem_Open(MFStr("%s.mdl", pFilename), MFOF_Read|MFOF_Binary);
		if(hFile)
		{
			int64 size = MFFile_GetSize(hFile);

			if(size > 0)
			{
				// allocate memory and load file
				pTemplateData = (char*)MFHeap_Alloc((size_t)size + MFString_Length(pFilename) + 1);
				MFFile_Read(hFile, pTemplateData, (size_t)size);
				MFFile_Close(hFile);

				MFString_Copy(&pTemplateData[size], pFilename);
				pFilename = &pTemplateData[size];
			}
		}
		else
		{
#if defined(ALLOW_LOAD_FROM_SOURCE_DATA)
			// try to load from source data
			const char * const pExt[] = { ".f3d", ".dae", ".x", ".ase", ".obj", ".md2", ".md3", ".me2", NULL };
			const char * const *ppExt = pExt;
			MFIntModel *pIM = NULL;
			while(!pIM && *ppExt)
			{
				MFString tempFilename = MFString::Format("%s%s", pFilename, *ppExt);
				pIM = MFIntModel_CreateFromFile(tempFilename.CStr());
				if(pIM)
				{
					pFilename = MFString_Copy((char*)MFHeap_Alloc(tempFilename.NumBytes()+1), tempFilename.CStr());
					break;
				}
				++ppExt;
			}

			if(pIM)
			{
				MFIntModel_Optimise(pIM);

				size_t size;
				MFIntModel_CreateRuntimeData(pIM, (void**)&pTemplateData, &size, MFSystem_GetCurrentPlatform());

				MFFile *pFile = MFFileSystem_Open(MFStr("cache:%s.mdl", pOriginalFilename), MFOF_Write | MFOF_Binary);
				if(pFile)
				{
					MFFile_Write(pFile, pTemplateData, size, false);
					MFFile_Close(pFile);
				}

				MFIntModel_Destroy(pIM);
			}
#endif
		}

		if(!pTemplateData)
			return NULL;

		// check ID string
		MFDebug_Assert(*(uint32*)pTemplateData == MFMAKEFOURCC('M', 'D', 'L', '2'), "Incorrect MFModel version.");

		// store filename for later reference
		pTemplate = (MFModelTemplate*)pTemplateData;
		pTemplate->pFilename = pFilename;

		gModelBank.Add(pOriginalFilename, pTemplate);

		MFModel_FixUp(pTemplate, true);

		MFModelDataChunk *pChunk = MFModel_GetDataChunk(pTemplate, MFChunkType_SubObjects);

		if(pChunk)
		{
			MFModelSubObject *pSubobjects = (MFModelSubObject*)pChunk->pData;

			for(int a=0; a<pChunk->count; a++)
			{
//				pSubobjects[a].pMaterial = MFMaterial_Create((char*)pSubobjects[a].pMaterial);

				for(int b=0; b<pSubobjects[a].numMeshChunks; b++)
				{
					MFModel_CreateMeshChunk(MFModel_GetMeshChunkInternal(pTemplate, a, b));
				}
			}
		}
	}

	MFModel *pModel;
	pModel = (MFModel*)MFHeap_Alloc(sizeof(MFModel));

	pModel->worldMatrix = MFMatrix::identity;
	pModel->modelColour = MFVector::one;
	pModel->pTemplate = pTemplate;
	pModel->pAnimation = NULL;

	++pTemplate->refCount;

	return pModel;
}
Example #9
0
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;
}