bool FVoiceCaptureWindows::Init(int32 SampleRate, int32 NumChannels)
{
	if (SampleRate < 8000 || SampleRate > 48000)
	{
		UE_LOG(LogVoiceCapture, Warning, TEXT("Voice capture doesn't support %d hz"), SampleRate);
		return false;
	}

	if (NumChannels < 0 || NumChannels > 2)
	{
		UE_LOG(LogVoiceCapture, Warning, TEXT("Voice capture only supports 1 or 2 channels"));
		return false;
	}

	FVoiceCaptureDeviceWindows* VoiceDev = FVoiceCaptureDeviceWindows::Get();
	if (!VoiceDev)
	{
		UE_LOG(LogVoiceCapture, Warning, TEXT("No voice capture interface."));
		return false;
	}

	// DSDEVID_DefaultCapture WAVEINCAPS 
	HRESULT hr = DirectSoundCaptureCreate8(&DSDEVID_DefaultVoiceCapture, &CV->VoiceCaptureDev, NULL);
	if (FAILED(hr))
	{
		//DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION, DSERR_OUTOFMEMORY
		UE_LOG(LogVoiceCapture, Warning, TEXT("Failed to create capture device 0x%08x"), hr);
		return false;
	}

	// Device capabilities
	CV->VoiceCaptureDevCaps.dwSize = sizeof(DSCCAPS);
	hr = CV->VoiceCaptureDev->GetCaps(&CV->VoiceCaptureDevCaps);
	if (FAILED(hr))
	{
		UE_LOG(LogVoiceCapture, Warning, TEXT("Failed to get mic device caps 0x%08x"), hr);
		return false;
	}

	// Wave format setup
	CV->WavFormat.wFormatTag = WAVE_FORMAT_PCM;
	CV->WavFormat.nChannels = NumChannels;
	CV->WavFormat.wBitsPerSample = 16;
	CV->WavFormat.nSamplesPerSec = SampleRate;
	CV->WavFormat.nBlockAlign = (CV->WavFormat.nChannels * CV->WavFormat.wBitsPerSample) / 8;
	CV->WavFormat.nAvgBytesPerSec = CV->WavFormat.nBlockAlign * CV->WavFormat.nSamplesPerSec;
	CV->WavFormat.cbSize = 0;

	// Buffer setup
	CV->VoiceCaptureBufferDesc.dwSize = sizeof(DSCBUFFERDESC);
	CV->VoiceCaptureBufferDesc.dwFlags = 0;
	CV->VoiceCaptureBufferDesc.dwBufferBytes = CV->WavFormat.nAvgBytesPerSec / 2; // .5 sec buffer
	CV->VoiceCaptureBufferDesc.dwReserved = 0;
	CV->VoiceCaptureBufferDesc.lpwfxFormat = &CV->WavFormat;
	CV->VoiceCaptureBufferDesc.dwFXCount = 0;
	CV->VoiceCaptureBufferDesc.lpDSCFXDesc = NULL;

	LPDIRECTSOUNDCAPTUREBUFFER VoiceBuffer = NULL;

	hr = CV->VoiceCaptureDev->CreateCaptureBuffer(&CV->VoiceCaptureBufferDesc, &VoiceBuffer, NULL);
	if (FAILED(hr))
	{
		UE_LOG(LogVoiceCapture, Warning, TEXT("Failed to create voice capture buffer 0x%08x"), hr);
		return false;
	}

	hr = VoiceBuffer->QueryInterface(IID_IDirectSoundCaptureBuffer8, (LPVOID*)&CV->VoiceCaptureBuffer8);
	VoiceBuffer->Release(); 
	VoiceBuffer = NULL;
	if (FAILED(hr))
	{
		UE_LOG(LogVoiceCapture, Warning, TEXT("Failed to create voice capture buffer 0x%08x"), hr);
		return false;
	}

	CV->VoiceCaptureBufferCaps8.dwSize = sizeof(DSCBCAPS);
	hr = CV->VoiceCaptureBuffer8->GetCaps(&CV->VoiceCaptureBufferCaps8);
	if (FAILED(hr))
	{
		UE_LOG(LogVoiceCapture, Warning, TEXT("Failed to get voice buffer caps 0x%08x"), hr);
		return false;
	}

	// TEST ------------------------
	if (0)
	{
		DWORD SizeWritten8 = 0;
		CV->VoiceCaptureBuffer8->GetFormat(NULL, sizeof(WAVEFORMATEX), &SizeWritten8);

		LPWAVEFORMATEX BufferFormat8 = (WAVEFORMATEX*)FMemory::Malloc(SizeWritten8);
		CV->VoiceCaptureBuffer8->GetFormat(BufferFormat8, SizeWritten8, &SizeWritten8);
		FMemory::Free(BufferFormat8);
	}
	// TEST ------------------------

	if (!CreateNotifications(CV->VoiceCaptureBufferCaps8.dwBufferBytes))
	{
		UE_LOG(LogVoiceCapture, Warning, TEXT("Failed to create voice buffer notifications"));
		return false;
	}

	VoiceCaptureState = EVoiceCaptureState::NotCapturing;
	return true;
}
bool FVoiceCaptureWindows::Init(int32 SampleRate, int32 NumChannels)
{
	if (SampleRate < 8000 || SampleRate > 48000)
	{
		UE_LOG(LogVoice, Warning, TEXT("Voice capture doesn't support %d hz"), SampleRate);
		return false;
	}

	if (NumChannels < 0 || NumChannels > 2)
	{
		UE_LOG(LogVoice, Warning, TEXT("Voice capture only supports 1 or 2 channels"));
		return false;
	}

	// @todo move this to voice module (only init/deinit once ever)
	if (FAILED(DirectSoundCreate8(NULL, &DirectSound, NULL)))
	{
		UE_LOG(LogVoice, Warning, TEXT("Failed to init DirectSound"));
		return false;
	}

	if (FAILED(DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)CaptureDeviceCallback, this)))
	{
		UE_LOG(LogVoice, Warning, TEXT("Failed to enumerate devices"));
		return false;
	}

	// DSDEVID_DefaultCapture WAVEINCAPS 
	if (FAILED(DirectSoundCaptureCreate8(&DSDEVID_DefaultVoiceCapture, &VoiceCaptureDev, NULL)))
	{
		UE_LOG(LogVoice, Warning, TEXT("Failed to create capture device"));
		return false;
	}

	// Device capabilities
	VoiceCaptureDevCaps.dwSize = sizeof(DSCCAPS);
	if (FAILED(VoiceCaptureDev->GetCaps(&VoiceCaptureDevCaps)))
	{
		UE_LOG(LogVoice, Warning, TEXT("Failed to get mic device caps"));
		return false;
	}

	// Wave format setup
	WavFormat.wFormatTag = WAVE_FORMAT_PCM;
	WavFormat.nChannels = NumChannels;
	WavFormat.wBitsPerSample = 16;
	WavFormat.nSamplesPerSec = SampleRate;
	WavFormat.nBlockAlign = (WavFormat.nChannels * WavFormat.wBitsPerSample) / 8;
	WavFormat.nAvgBytesPerSec = WavFormat.nBlockAlign * WavFormat.nSamplesPerSec;
	WavFormat.cbSize = 0;

	// Buffer setup
	VoiceCaptureBufferDesc.dwSize = sizeof(DSCBUFFERDESC);
	VoiceCaptureBufferDesc.dwFlags = 0;
	VoiceCaptureBufferDesc.dwBufferBytes = WavFormat.nAvgBytesPerSec / 2; // .5 sec buffer
	VoiceCaptureBufferDesc.dwReserved = 0;
	VoiceCaptureBufferDesc.lpwfxFormat = &WavFormat;
	VoiceCaptureBufferDesc.dwFXCount = 0;
	VoiceCaptureBufferDesc.lpDSCFXDesc = NULL;

	LPDIRECTSOUNDCAPTUREBUFFER VoiceBuffer = NULL;
	if (FAILED(VoiceCaptureDev->CreateCaptureBuffer(&VoiceCaptureBufferDesc, &VoiceBuffer, NULL)))
	{
		UE_LOG(LogVoice, Warning, TEXT("Failed to create voice capture buffer"));
		return false;
	}

	HRESULT BufferCreateHR = VoiceBuffer->QueryInterface(IID_IDirectSoundCaptureBuffer8, (LPVOID*)&VoiceCaptureBuffer8);
	VoiceBuffer->Release(); 
	VoiceBuffer = NULL;
	if (FAILED(BufferCreateHR))
	{
		UE_LOG(LogVoice, Warning, TEXT("Failed to create voice capture buffer"));
		return false;
	}

	VoiceCaptureBufferCaps8.dwSize = sizeof(DSCBCAPS);
	if (FAILED(VoiceCaptureBuffer8->GetCaps(&VoiceCaptureBufferCaps8)))
	{
		UE_LOG(LogVoice, Warning, TEXT("Failed to get voice buffer caps"));
		return false;
	}

	// TEST ------------------------
	if (0)
	{
		DWORD SizeWritten8 = 0;
		VoiceCaptureBuffer8->GetFormat(NULL, sizeof(WAVEFORMATEX), &SizeWritten8);

		LPWAVEFORMATEX BufferFormat8 = (WAVEFORMATEX*)FMemory::Malloc(SizeWritten8);
		VoiceCaptureBuffer8->GetFormat(BufferFormat8, SizeWritten8, &SizeWritten8);
		FMemory::Free(BufferFormat8);
	}
	// TEST ------------------------

	if (!CreateNotifications(VoiceCaptureBufferCaps8.dwBufferBytes))
	{
		UE_LOG(LogVoice, Warning, TEXT("Failed to create voice buffer notifications"));
		return false;
	}

	VoiceCaptureState = EVoiceCaptureState::NotCapturing;
	return true;
}