void MFSound_DeinitWASAPI() { gpEnumerator->Release(); gpNotification->Release(); gDevices.Deinit(); gCaptureDevices.Deinit(); }
static void DestroyDevice(MFDevice *pDevice) { AudioDevice *pDev = (AudioDevice*)pDevice->pInternal; if(pDev->pDevice) alcCloseDevice(pDev->pDevice); gDevices.Free(pDev); }
MFInitStatus MFHeap_InitModule() { MFCALLSTACK; MFDebug_Assert(MFThread_GetMutexSizePlatformSpecific() <= sizeof(gMutexBuffer), "Mutex buffer too small!"); MFThread_InitMutexPlatformSpecific((MFMutex)gMutexBuffer, "MFHeap alloc mutex"); gAllocMutex = (MFMutex)gMutexBuffer; // any heap tracking allocations should be made in the debug space MFHeap *pOld = MFHeap_SetActiveHeap(MFHeap_GetDebugHeap()); #if defined(_USE_TRACKING_HASH_TABLE) // set up the memory tracking hash table // note: this is slightly complicated due to the chicken and egg nature // of making the first allocation for the pool its self ;) static const int numAllocHeaders = 1024; // uint32 bytes = (sizeof(MFHeap_AllocItem) + sizeof(void**)) * numAllocHeaders; // void *pPoolMemory = MFHeap_Alloc(bytes); // gAllocHeaderPool.Init(sizeof(MFHeap_AllocItem), numAllocHeaders, 1024, pPoolMemory, bytes); gAllocHeaderPool.Init(sizeof(MFHeap_AllocItem), numAllocHeaders, 1024); MFZeroMemory(gpAllocTable, sizeof(gpAllocTable)); // artificially add an entry for the pool its self... MFHeap_AllocItem *pHeader = (MFHeap_AllocItem*)gAllocHeaderPool.Alloc(); pHeader->header.pHeap = &gExternalHeap; pHeader->header.size = bytes; pHeader->header.pFile = __FILE__; pHeader->header.line = (uint16)__LINE__; pHeader->header.alignment = 4; pHeader->pMemory = pPoolMemory; pHeader->pNext = NULL; gpAllocTable[MFUtil_HashPointer(pPoolMemory) % MFHeap_AllocTableLength] = pHeader; #endif #if defined(_USE_ALLOC_TRACKER) gAllocList.Init(sizeof(void*), 1024, 1024); gPoolInitialised = true; #endif // restore the active heap MFHeap_SetActiveHeap(pOld); // init the heap MFHeap_InitModulePlatformSpecific(); return MFAIC_Succeeded; }
MF_API void MFString_Dump() { MFString temp = MFString_GetStats(); MFDebug_Log(1, "\n-------------------------------------------------------------------------------------------------------"); MFDebug_Log(1, temp.CStr()); // dump all strings... MFDebug_Log(1, ""); int numStrings = stringPool.GetNumAllocated(); for(int a=0; a<numStrings; ++a) { MFStringData *pString = (MFStringData*)stringPool.GetItem(a); MFDebug_Log(1, MFStr("%d refs, " MFFMT_SIZE_T "b: \"%s\"", pString->refCount, pString->allocated, pString->pMemory)); } }
MF_API MFStringData *MFStringData_Alloc() { MFStringData *pData = (MFStringData*)stringPool.Alloc(); pData->refCount = 1; pData->pMemory = NULL; pData->allocated = pData->bytes = 0; return pData; }
void MFString_DeinitModule() { if(--gModuleInitCount == 0) { stringPool.Deinit(); stringHeap.Deinit(); } }
MF_API MFString MFString_GetStats() { size_t overhead = stringPool.GetTotalMemory() + stringPool.GetOverheadMemory() + stringHeap.GetOverheadMemory(); size_t waste = 0, averageSize = 0; // calculate waste int numStrings = stringPool.GetNumAllocated(); for(int a=0; a<numStrings; ++a) { MFStringData *pString = (MFStringData*)stringPool.GetItem(a); size_t allocated = pString->allocated; if(allocated) { size_t bytes = pString->bytes+1; averageSize += bytes; waste += allocated - bytes; } } if(numStrings) averageSize /= numStrings; MFString desc; desc.Reserve(1024); desc = MFStr("String heap memory: " MFFMT_SIZE_T " allocated/" MFFMT_SIZE_T " reserved + " MFFMT_SIZE_T " overhead Waste: " MFFMT_SIZE_T " Average length: " MFFMT_SIZE_T "\n\tPool: %d/%d", stringHeap.GetAllocatedMemory(), stringHeap.GetTotalMemory(), overhead, waste, averageSize, stringPool.GetNumAllocated(), stringPool.GetNumReserved()); int numGroups = stringHeap.GetNumPools(); for(int a=0; a<numGroups; ++a) { MFObjectPool *pPool = stringHeap.GetPool(a); desc += MFStr("\n\t\t" MFFMT_SIZE_T " byte: %d/%d", pPool->GetObjectSize(), pPool->GetNumAllocated(), pPool->GetNumReserved()); } return desc; }
void MFHeap_DeinitModule() { MFCALLSTACK; MFHeap_DeinitModulePlatformSpecific(); #if defined(_USE_ALLOC_TRACKER) gPoolInitialised = false; gAllocList.Deinit(); #endif #if defined(_USE_TRACKING_HASH_TABLE) // todo: list all unfreed allocations? //... gAllocHeaderPool.Deinit(); MFZeroMemory(gpAllocTable, sizeof(gpAllocTable)); #endif // TODO: gAllocMutex is not allocated by MFHeap... separate the 'deinit' from the 'destroy' // MFThread_DestroyMutex(gAllocMutex); }
MF_API bool MFHeap_ValidateHeap() { #if defined(_USE_ALLOC_TRACKER) MFThread_LockMutex(gAllocMutex); if(gPoolInitialised) { int numAllocated = gAllocList.GetNumAllocated(); for(int a=0; a<numAllocated; ++a) { void *pMem = *(void**)gAllocList.GetItem(a); if(!MFHeap_ValidateMemory(pMem)) { MFDebug_Assert(false, "Corrupt memory allocation!"); return false; } } } MFThread_ReleaseMutex(gAllocMutex); #endif return true; }
static MFDevice *NewDevice(LPCWSTR pwstrDeviceId) { MFDevice *pDev = NULL; IMMDevice *pDevice; gpEnumerator->GetDevice(pwstrDeviceId, &pDevice); if(pDevice) { // TODO: don't know if it's a capture device or not! if(1) { pDev = MFDevice_AllocDevice(MFDT_AudioRender, NULL); pDev->pInternal = gDevices.AllocAndZero(); GetDeviceInfo(pDevice, pDev); } else { pDev = MFDevice_AllocDevice(MFDT_AudioCapture, NULL); pDev->pInternal = gCaptureDevices.AllocAndZero(); GetDeviceInfo(pDevice, pDev); } pDevice->Release(); } return pDev; }
MFInitStatus MFString_InitModule(int moduleId, bool bPerformInitialisation) { if(!bPerformInitialisation) return MFIS_Succeeded; if(gModuleInitCount == 0) { ++gModuleInitCount; stringHeap.Init(gStringGroups, sizeof(gStringGroups) / sizeof(gStringGroups[0])); stringPool.Init(sizeof(MFStringData), 128, 128); } return MFIS_Succeeded; }
MF_API void MFHeap_Free(void *pMem) { MFCALLSTACK; if(!pMem) { MFDebug_Warn(3, "Attemptd to Free 'NULL' pointer."); return; } MFAllocHeader *pHeader = &((MFAllocHeader*)pMem)[-1]; MFDebug_Assert(MFHeap_ValidateMemory(pMem), MFStr("Memory corruption detected!!\n%s(%d)", pHeader->pFile, pHeader->line)); MFThread_LockMutex(gAllocMutex); MFHeap *pHeap = pHeader->pHeap; if(pHeap->heapType != MFHT_Debug) { #if defined(_USE_TRACKING_HASH_TABLE) int hash = MFUtil_HashPointer(pMem) % MFHeap_AllocTableLength; MFHeap_AllocItem *pT = gpAllocTable[hash]; if(pT) { if(pT->pMemory == pMem) { gpAllocTable[hash] = pT->pNext; gAllocHeaderPool.Free(pT); } else { while(pT->pNext && pT->pNext->pMemory != pMem) pT = pT->pNext; if(pT->pNext) { MFHeap_AllocItem *pTN = pT->pNext; pT->pNext = pTN->pNext; gAllocHeaderPool.Free(pTN); } } } #endif #if defined(_USE_ALLOC_TRACKER) if(gPoolInitialised) { int numAllocs = gAllocList.GetNumAllocated(); for(int a=0; a<numAllocs; ++a) { void **ppAlloc = (void**)gAllocList.GetItem(a); if(*ppAlloc == pMem) { gAllocList.Free(ppAlloc); break; } } } #endif } #if !defined(_RETAIL) int pad = 0; while(pad < (int)sizeof(MFAllocHeader)) pad += heapAlignment; size_t extra = pad + sizeof(MFAllocHeader) + MFHeap_MungwallBytes; pHeap->totalAllocated -= pHeader->size + extra; pHeap->totalWaste -= extra; --pHeap->allocCount; // MFDebug_Log(2, MFStr("Free: %08X, %d bytes - %s:(%d)", pMem, pHeader->size, pHeader->pFile, (int)pHeader->line)); #endif MFHeap *pAllocHeap = pHeader->pHeap; MFCopyMemory((char*)pMem + pHeader->size, "freefreefreefree", MFHeap_MungwallBytes); MFCopyMemory((char*)pMem - 8, "freefreefreefree", MFHeap_MungwallBytes); MFMemSet(pMem, 0xFE, pHeader->size); pAllocHeap->pCallbacks->pFree((char*)pMem - pHeader->alignment, pAllocHeap->pHeapData); MFThread_ReleaseMutex(gAllocMutex); }
MF_API void *MFHeap_AllocInternal(size_t bytes, MFHeap *pHeap) { MFCALLSTACK; MFHeap *pAllocHeap = pOverrideHeap ? pOverrideHeap : (pHeap ? pHeap : pActiveHeap); int pad = 0; while(pad < (int)sizeof(MFAllocHeader)) pad += heapAlignment; size_t allocExtra = pad + sizeof(MFAllocHeader) + MFHeap_MungwallBytes; size_t allocBytes = bytes + allocExtra; MFThread_LockMutex(gAllocMutex); char *pMemory = (char*)pAllocHeap->pCallbacks->pMalloc(allocBytes, pAllocHeap->pHeapData); MFDebug_Assert(pMemory, "Failed to allocate memory!"); if(pMemory) { int alignment = (int)(MFALIGN(pMemory + sizeof(MFAllocHeader), heapAlignment) - (uintp)pMemory); pMemory += alignment; MFAllocHeader *pHeader = &((MFAllocHeader*)pMemory)[-1]; pHeader->alignment = (uint16)alignment; pHeader->pHeap = pAllocHeap; pHeader->size = (uint32)bytes; pHeader->pFile = gpMFHeap_TrackerFile; pHeader->line = (uint16)gMFHeap_TrackerLine; #if defined(USE_PRE_MUNGWALL) MFCopyMemory(pHeader->llawgnum, gLlawgnum, MFHeap_MungwallBytes); #endif if(pAllocHeap->heapType != MFHT_Debug) { #if defined(_USE_TRACKING_HASH_TABLE) MFHeap_AllocItem *pAlloc = (MFHeap_AllocItem*)gAllocHeaderPool.Alloc(); pAlloc->header.alignment = (uint16)alignment; pAlloc->header.pHeap = pAllocHeap; pAlloc->header.size = (uint32)bytes; pAlloc->header.pFile = gpMFHeap_TrackerFile; pAlloc->header.line = (uint16)gMFHeap_TrackerLine; pAlloc->pMemory = pMemory; int hash = MFUtil_HashPointer(pMemory) % MFHeap_AllocTableLength; pAlloc->pNext = gpAllocTable[hash]; gpAllocTable[hash] = pAlloc; #endif #if defined(_USE_ALLOC_TRACKER) if(gPoolInitialised) *(void**)gAllocList.Alloc() = pMemory; #endif } #if !defined(_RETAIL) MFCopyMemory(pMemory + bytes, gMungwall, MFHeap_MungwallBytes); pAllocHeap->totalAllocated += allocBytes; pAllocHeap->totalWaste += allocExtra; ++pAllocHeap->allocCount; // MFDebug_Log(2, MFStr("Alloc: %08X(%08X), %d bytes - %s:(%d)", pMemory, pMemory - pHeader->alignment, bytes, gpMFHeap_TrackerFile, gMFHeap_TrackerLine)); #endif } MFThread_ReleaseMutex(gAllocMutex); return (void*)pMemory; }
void MFSound_InitModulePlatformSpecific(int *pSoundDataSize, int *pVoiceDataSize) { MFCALLSTACK; gDevices.Init(sizeof(AudioDevice), 8, 8); ALCint minor, major; alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &major); alcGetIntegerv(NULL, ALC_MINOR_VERSION, 1, &minor); gAPIVersion = major*100 + minor; bool bCanEnumerate, bHasCapture; if(gAPIVersion >= 101) { bCanEnumerate = true; bHasCapture = true; } else { bCanEnumerate = alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") == AL_TRUE; bHasCapture = alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE") == AL_TRUE; } if(bCanEnumerate) { const char *pDevices = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER); const char *pDefault = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); while(pDevices && *pDevices) { bool bIsDefault = !MFString_Compare(pDevices, pDefault); MFDebug_Log(2, MFStr("OpenAL: found output device '%s'%s", pDevices, bIsDefault ? " (default)" : "")); MFDevice *pDevice = MFDevice_AllocDevice(MFDT_AudioRender, &DestroyDevice); pDevice->pInternal = gDevices.AllocAndZero(); pDevice->state = MFDevState_Ready; AudioDevice &device = *(AudioDevice*)pDevice->pInternal; MFString_CopyN(pDevice->strings[MFDS_ID], pDevices, sizeof(pDevice->strings[MFDS_ID])-1); pDevice->strings[MFDS_ID][sizeof(pDevice->strings[MFDS_ID])-1] = 0; device.pDevice = NULL; if(bIsDefault) MFDevice_SetDefaultDevice(MFDT_AudioRender, MFDDT_All, pDevice); pDevices += MFString_Length(pDevices) + 1; } if(!MFDevice_GetDefaultDevice(MFDT_AudioRender, MFDDT_Default)) { MFDebug_Warn(2, "OpenAL: No default output device?"); // HACK: set it to the first one... MFDevice *pDevice = MFDevice_GetDeviceByIndex(MFDT_AudioRender, 0); MFDevice_SetDefaultDevice(MFDT_AudioRender, MFDDT_All, pDevice); } if(bHasCapture) { pDevices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); pDefault = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER); while(pDevices && *pDevices) { bool bIsDefault = !MFString_Compare(pDevices, pDefault); MFDebug_Log(2, MFStr("OpenAL: found capture device '%s'%s", pDevices, bIsDefault ? " (default)" : "")); MFDevice *pDevice = MFDevice_AllocDevice(MFDT_AudioCapture, &DestroyDevice); pDevice->pInternal = gDevices.AllocAndZero(); pDevice->state = MFDevState_Ready; AudioDevice &device = *(AudioDevice*)pDevice->pInternal; MFString_CopyN(pDevice->strings[MFDS_ID], pDevices, sizeof(pDevice->strings[MFDS_ID])-1); pDevice->strings[MFDS_ID][sizeof(pDevice->strings[MFDS_ID])-1] = 0; device.pDevice = NULL; if(bIsDefault) MFDevice_SetDefaultDevice(MFDT_AudioCapture, MFDDT_All, pDevice); pDevices += MFString_Length(pDevices) + 1; } if(!MFDevice_GetDefaultDevice(MFDT_AudioCapture, MFDDT_Default)) MFDebug_Warn(2, "OpenAL: No default capture device?"); } } // create a context Context *pContext = CreateContext(MFDevice_GetDefaultDevice(MFDT_AudioRender, MFDDT_Default)); MakeCurrent(pContext); // we need to return the size of the internal structures so the platform independant // code can make the correct allocations.. *pSoundDataSize = sizeof(MFSoundDataInternal); *pVoiceDataSize = sizeof(MFVoiceDataInternal); }
void MFSound_InitWASAPI() { gDevices.Init(sizeof(MFAudioDevice), 8, 8); gCaptureDevices.Init(sizeof(MFAudioCaptureDevice), 8, 8); HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&gpEnumerator); if(FAILED(hr)) { MFDebug_Assert(false, "Couldn't create multimedia device enumerator!"); return; } // enumerate audio devices... gpNotification = new MFAudioDeviceNotification; gpEnumerator->RegisterEndpointNotificationCallback(gpNotification); // enumerate render devices IMMDeviceCollection *pDevices; gpEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE | DEVICE_STATE_UNPLUGGED, &pDevices); if(pDevices) { UINT count; pDevices->GetCount(&count); for(UINT i=0; i<count; ++i) { IMMDevice *pDevice; pDevices->Item(i, &pDevice); MFDevice *pDev = MFDevice_AllocDevice(MFDT_AudioRender, NULL); pDev->pInternal = gDevices.AllocAndZero(); MFAudioDevice &device = *(MFAudioDevice*)pDev->pInternal; GetDeviceInfo(pDevice, pDev); pDevice->Release(); MFDebug_Log(0, MFStr("Found audio device: %s, %s - state: %d (%s)", pDev->strings[MFDS_DeviceName], pDev->strings[MFDS_Manufacturer], device.state, pDev->strings[MFDS_ID])); } pDevices->Release(); } // enumerate capture devices gpEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE | DEVICE_STATE_UNPLUGGED, &pDevices); if(pDevices) { UINT count; pDevices->GetCount(&count); for(UINT i=0; i<count; ++i) { IMMDevice *pDevice; pDevices->Item(i, &pDevice); MFDevice *pDev = MFDevice_AllocDevice(MFDT_AudioCapture, NULL); pDev->pInternal = gCaptureDevices.AllocAndZero(); MFAudioCaptureDevice &device = *(MFAudioCaptureDevice*)pDev->pInternal; GetDeviceInfo(pDevice, pDev); pDevice->Release(); MFDebug_Log(0, MFStr("Found audio capture device: %s, %s - state: %d (%s)", pDev->strings[MFDS_DeviceName], pDev->strings[MFDS_Manufacturer], device.state, pDev->strings[MFDS_ID])); } pDevices->Release(); } // set defaults (this is some awkward windows code!) for(int i=0; i<2; ++i) { for(int j=0; j<3; ++j) { IMMDevice *pDevice; gpEnumerator->GetDefaultAudioEndpoint(gDirection[i], gRole[j], &pDevice); if(pDevice) { wchar_t *pDefaultId; pDevice->GetId(&pDefaultId); char temp[128]; MFString_CopyUTF16ToUTF8(temp, pDefaultId); MFDevice *pDev = MFDevice_GetDeviceById(temp); MFDevice_SetDefaultDevice(gDt[i], gDef[j], pDev); CoTaskMemFree(pDefaultId); pDevice->Release(); } } } }
MF_API void MFStringData_Destroy(MFStringData *pStringData) { if(pStringData->allocated) stringHeap.Free(pStringData->pMemory); stringPool.Free(pStringData); }