MF_API void MFIntSound_CreateRuntimeData(MFIntSound *pSound, void **ppOutput, size_t *pSize, MFPlatform platform) { *ppOutput = NULL; MFAudioStream *pStream = (MFAudioStream*)pSound->pInternal; // decode audio into buffer size_t sampleSize = (pSound->soundTemplate.bitsPerSample * pSound->soundTemplate.numChannels) >> 3; size_t bytesAllocated = 44100 * sampleSize; size_t bytes = 0; char *pAudioData = (char*)MFHeap_Alloc(bytesAllocated); size_t read; do { // read samples from stream read = MFSound_ReadStreamSamples(pStream, pAudioData + bytes, bytesAllocated - bytes); bytes += read; // if we fill the buffer, increase it's size if(bytes == bytesAllocated) { bytesAllocated *= 4; pAudioData = (char*)MFHeap_Realloc(pAudioData, bytesAllocated); } } while(read); // calculate the number of samples from the bytes read int numSamples = (int)(bytes / sampleSize); // construct MFSoundTemplate size_t templateBytes = sizeof(MFSoundTemplate) + sizeof(char*)*pSound->soundTemplate.numStreams + sampleSize*numSamples; MFSoundTemplate *pTemplate = (MFSoundTemplate*)MFHeap_Alloc(templateBytes); MFCopyMemory(pTemplate, &pSound->soundTemplate, sizeof(MFSoundTemplate)); pTemplate->numSamples = numSamples; pTemplate->ppStreams = (char**)&pTemplate[1]; pTemplate->ppStreams[0] = (char*)&pTemplate->ppStreams[1]; // copy sample data MFCopyMemory(pTemplate->ppStreams[0], pAudioData, sampleSize * numSamples); // free decode buffer MFHeap_Free(pAudioData); // fix down pointers for(int a=0; a<pTemplate->numStreams; a++) MFFixUp(pTemplate->ppStreams[a], pTemplate, false); MFFixUp(pTemplate->ppStreams, pTemplate, false); // return template data *ppOutput = pTemplate; if(pSize) *pSize = templateBytes; }
void MFAnimation_FixUp(MFAnimationTemplate *pTemplate, bool load) { if(load) { MFFixUp(pTemplate->pBones, pTemplate, 1); MFFixUp(pTemplate->pAnimName, pTemplate, 1); } for(uint32 a=0; a<pTemplate->numBones; a++) { MFFixUp(pTemplate->pBones[a].pBoneName, pTemplate, load); MFFixUp(pTemplate->pBones[a].pTime, pTemplate, load); MFFixUp(pTemplate->pBones[a].pFrames, pTemplate, load); } if(!load) { MFFixUp(pTemplate->pBones, pTemplate, 0); MFFixUp(pTemplate->pAnimName, pTemplate, 0); } }
void MFMesh_FixUpMeshChunkGeneric(MFMeshChunk *pMeshChunk, void *pBase, bool load) { MFCALLSTACK; MFDebug_Assert(pMeshChunk->type == MFMCT_Generic, "Not a Generic type meshchunk!!"); MFMeshChunk_Generic *pMC = (MFMeshChunk_Generic*)pMeshChunk; MFFixUp(pMC->pMaterial, pBase, load); MFFixUp(pMC->pIndexData, pBase, load); MFFixUp(pMC->pBatchIndices, pBase, load); if(load) { MFFixUp(pMC->pVertexFormat, pBase, 1); MFFixUp(pMC->pVertexFormat->pStreams, pBase, 1); MFFixUp(pMC->ppVertexStreams, pBase, 1); } for(int b=0; b<pMC->pVertexFormat->numVertexStreams; ++b) { if(pMC->pVertexFormat->pStreams[b].pStreamName) MFFixUp(pMC->pVertexFormat->pStreams[b].pStreamName, pBase, load); MFFixUp(pMC->pVertexFormat->pStreams[b].pElements, pBase, load); MFFixUp(pMC->ppVertexStreams[b], pBase, load); } if(!load) { MFFixUp(pMC->pVertexFormat->pStreams, pBase, 0); MFFixUp(pMC->pVertexFormat, pBase, 0); MFFixUp(pMC->ppVertexStreams, pBase, 0); } }
int main(int argc, char *argv[]) { MFPlatform platform = FP_Unknown; MFWaveFormat targetFormat = MFWF_PCM_s16; char fileName[256] = ""; char outFile[256] = ""; int a; // process command line for(a=1; a<argc; a++) { if(argv[a][0] == '-' || argv[a][0] == '/') { for(int b=0; b<FP_Max; b++) { if(!MFString_CaseCmp(&argv[a][1], MFSystem_GetPlatformString(b))) { platform = (MFPlatform)b; break; } } if(!MFString_CaseCmp(&argv[a][1], "v") || !MFString_CaseCmp(&argv[a][1], "version")) { // print version return 0; } } else { if(!fileName[0]) MFString_Copy(fileName, argv[a]); else if(!outFile[0]) MFString_Copy(outFile, argv[a]); } } if(platform == FP_Unknown) { LOGERROR("No platform specified...\n"); return 1; } if(!fileName[0]) { LOGERROR("No file specified...\n"); return 1; } if(!outFile[0]) { // generate output filename MFString_Copy(outFile, fileName); for(int i=MFString_Length(outFile); --i; ) { if(outFile[i] == '.') { outFile[i] = 0; break; } } MFString_Cat(outFile, ".snd"); } // load image char *pBuffer; FILE *pFile = fopen(fileName, "rb"); if(!pFile) { LOGERROR("Couldnt open source file '%s' for reading.", fileName); return 1; } fseek(pFile, 0, SEEK_END); int bytes = ftell(pFile) + 1; fseek(pFile, 0, SEEK_SET); pBuffer = (char*)malloc(bytes); fread(pBuffer, bytes, 1, pFile); fclose(pFile); FILE *pOutFile = fopen(outFile, "wb"); if(!pOutFile) { LOGERROR("Couldnt open output file '%s' for writing.", outFile); return 2; } // parse the sound file... WAVHeader *pHeader = (WAVHeader*)pBuffer; if(pHeader->RIFF != MFMAKEFOURCC('R', 'I', 'F', 'F') || pHeader->WAVE != MFMAKEFOURCC('W', 'A', 'V', 'E')) { LOGERROR("Source file '%s' is not a wave file.", fileName); return 1; } WAVChunk *pChunk = (WAVChunk*)&pHeader[1]; WAVFormatChunk *pFormat = NULL; WAVDataChunk *pData = NULL; while((char*)pChunk - pBuffer < bytes && bytes - ((char*)pChunk - pBuffer) >= sizeof(WAVChunk)) { if(pChunk->id == MFMAKEFOURCC('f', 'm', 't', ' ')) { pFormat = (WAVFormatChunk*)pChunk; } else if(pChunk->id == MFMAKEFOURCC('d', 'a', 't', 'a')) { pData = (WAVDataChunk*)pChunk; } pChunk = (WAVChunk*)((char*)pChunk + sizeof(WAVChunk) + ((pChunk->size+1) & ~1)); } if(!pFormat || !pData) { LOGERROR("WAVE file '%s' has no format or data chunks.", fileName); return 2; } // we only output 1 stream for now.. int numStreams = 1; int numSamples = ((pData->size*8) / ((pFormat->wBitsPerSample + 7) & ~7)) / pFormat->nChannels; int fileSize = sizeof(MFSoundTemplate) + sizeof(char*)*numStreams + bytesPerSample[targetFormat]*pFormat->nChannels*numSamples*numStreams; char *pSndFile = (char*)MFHeap_Alloc(fileSize); MFSoundTemplate *pTemplate = (MFSoundTemplate*)pSndFile; pTemplate->ppStreams = (char **)&pTemplate[1]; char *pWaveData = (char*)&pTemplate->ppStreams[numStreams]; for(int a=0; a<numStreams; a++) { pTemplate->ppStreams[a] = pWaveData; pWaveData += bytesPerSample[targetFormat]*pFormat->nChannels*numSamples; } pTemplate->magic = MFMAKEFOURCC('S', 'N', 'D', '1'); pTemplate->flags = 0; pTemplate->format = targetFormat; pTemplate->numSamples = numSamples; pTemplate->numStreams = numStreams; pTemplate->numChannels = pFormat->nChannels; pTemplate->bitsPerSample = bytesPerSample[targetFormat]*8; pTemplate->sampleRate = pFormat->nSamplesPerSec; // write wave data into file if(pTemplate->bitsPerSample == pFormat->wBitsPerSample) { for(int a=0; a<pTemplate->numStreams; a++) MFCopyMemory(pTemplate->ppStreams[a], pData->data, bytesPerSample[targetFormat]*pTemplate->numChannels*pTemplate->numSamples); } else { // do a format conversion LOGERROR("Format conversion not written."); return 3; } // fix up template for(int a=0; a<numStreams; a++) MFFixUp(pTemplate->ppStreams[a], pTemplate, false); MFFixUp(pTemplate->ppStreams, pTemplate, false); // write to disk fwrite(pSndFile, fileSize, 1, pOutFile); fclose(pOutFile); printf("> %s\n", outFile); return 0; }
void MFModel_FixUp(MFModelTemplate *pTemplate, bool load) { int a, b, c; if(load) { MFFixUp(pTemplate->pDataChunks, pTemplate, 1); MFFixUp(pTemplate->pName, pTemplate, 1); } for(a=0; a<pTemplate->numDataChunks; a++) { if(load) MFFixUp(pTemplate->pDataChunks[a].pData, pTemplate, 1); switch(pTemplate->pDataChunks[a].chunkType) { case MFChunkType_SubObjects: { MFModelSubObject *pSubobjects = (MFModelSubObject*)pTemplate->pDataChunks[a].pData; for(b=0; b<pTemplate->pDataChunks[a].count; b++) { if(load) { MFFixUp(pSubobjects[b].pMeshChunks, pTemplate, 1); MFFixUp(pSubobjects[b].pSubObjectName, pTemplate, 1); // MFFixUp(pSubobjects[b].pMaterial, pTemplate, 1); } for(c=0; c<pSubobjects[b].numMeshChunks; c++) { MFModel_FixUpMeshChunk(MFModel_GetMeshChunkInternal(pTemplate, b, c), pTemplate, load); } if(!load) { MFFixUp(pSubobjects[b].pSubObjectName, pTemplate, 0); // MFFixUp(pSubobjects[b].pMaterial, pTemplate, 0); MFFixUp(pSubobjects[b].pMeshChunks, pTemplate, 0); } } break; } case MFChunkType_Bones: { MFModelBone *pBones = (MFModelBone*)pTemplate->pDataChunks[a].pData; for(b=0; b<pTemplate->pDataChunks[a].count; b++) { MFFixUp(pBones[b].pBoneName, pTemplate, load); MFFixUp(pBones[b].pParentName, pTemplate, load); MFFixUp(pBones[b].pChildren, pTemplate, load); } break; } case MFChunkType_Collision: { MFCollisionTemplate *pCollisionChunk = (MFCollisionTemplate*)pTemplate->pDataChunks[a].pData; for(b=0; b<pTemplate->pDataChunks[a].count; b++) { MFFixUp(pCollisionChunk[b].pName, pTemplate, load); if(load) MFFixUp(pCollisionChunk[b].pCollisionTemplateData, pTemplate, 1); if(pCollisionChunk[b].type == MFCT_Mesh) { MFCollisionMesh *pMesh = (MFCollisionMesh*)pCollisionChunk[b].pCollisionTemplateData; MFFixUp(pMesh->pTriangles, pTemplate, load); } if(!load) MFFixUp(pCollisionChunk[b].pCollisionTemplateData, pTemplate, 0); } break; } case MFChunkType_Tags: { MFModelTag *pTags = (MFModelTag*)pTemplate->pDataChunks[a].pData; for(b=0; b<pTemplate->pDataChunks[a].count; b++) { MFFixUp(pTags[b].pTagName, pTemplate, load); } break; } default: break; } if(!load) MFFixUp(pTemplate->pDataChunks[a].pData, pTemplate, 0); } if(!load) { MFFixUp(pTemplate->pDataChunks, pTemplate, 0); MFFixUp(pTemplate->pName, pTemplate, 0); } }