void nuiAudioDevice_DS_ProcessingTh::Process(uint pos)
{
  NGL_LOG(_T("nuiAudioDevice_DS_ProcessingTh"), NGL_LOG_DEBUG, _T("Process Thread received Event %d\n"), pos);

  int16* pBuf1=NULL;
  int16* pBuf2=NULL;
  DWORD size1=0;
  DWORD size2=0;
  DWORD bufferBytes = mBufferSize * mInputNbChannels * sizeof(int16);

  if (!mpRingBuffer->GetWritable())
    return;

  //
  // lock the input buffer if any,
  // and read data from it to the local buffer
  //
  if (  mpDSInputBuffer 
    && mpDSInputBuffer->Lock(pos * bufferBytes /* offset */, bufferBytes /*size*/, (LPVOID*)&pBuf1, &size1, (LPVOID*)&pBuf2, &size2, 0)
    )
  {
    if (!pBuf1 || !size1)
    {
      //NGL_LOG(_T("nuiAudioDevice_DS_ProcessingTh"), NGL_LOG_ERROR, _T("Process error : could not lock any part of the input buffer\n"));
      NGL_ASSERT(0);
      return;
    }

    // check that we got the right size
    NGL_ASSERT((size1+size2) == bufferBytes);


    // copy input data into local buffer
    memcpy(mpLocalBuf, pBuf1, size1);
    if (pBuf2)
      memcpy(mpLocalBuf+size1, pBuf2, size2);

    // convert int16 buffer to float buffer
    for (uint32 ch=0; ch < mInputNbChannels; ch++)
    {
      nuiAudioConvert_INint16ToDEfloat(mpLocalBuf, const_cast<float*>(mFloatInputBuf[ch]), ch, mInputNbChannels, mBufferSize); 
    }
  }


  // call user audio process function
  mpProcessFunction(mFloatInputBuf, mFloatOutputBuf, mBufferSize);

  // copy output buffer contents to ringbuffer
  uint32 nbWrite = WriteToRingBuf(mFloatOutputBuf, mBufferSize, mOutputNbChannels);

  // release DS input buffer
  if (mpDSInputBuffer)
    mpDSInputBuffer->Unlock(pBuf1, size1, pBuf2, size2);
}
Esempio n. 2
0
static void capture_free (void)
{
	if (lpDSB2r) {
		lpDSB2r->Stop ();
		lpDSB2r->Release ();
		write_log (_T("SAMPLER: Parallel port sampler freed\n"));
	}
	lpDSB2r = NULL;
	if (lpDS2r)
		lpDS2r->Release ();
	lpDS2r = NULL;
	xfree (samplebuffer);
	samplebuffer = NULL;
}
Esempio n. 3
0
HRESULT CreateCaptureBuffer(LPDIRECTSOUNDCAPTURE8 pDSC, 
		LPDIRECTSOUNDCAPTUREBUFFER8* ppDSCB8)
{
	HRESULT hr;
	DSCBUFFERDESC               dscbd;
	LPDIRECTSOUNDCAPTUREBUFFER  pDSCB;
	WAVEFORMATEX                wfx =
	{WAVE_FORMAT_PCM, 1, 11025, 11025*2, 4, 16, 0 };
	// wFormatTag, nChannels, nSamplesPerSec, mAvgBytesPerSec,
	// nBlockAlign, wBitsPerSample, cbSize

	wfx.wFormatTag = WAVE_FORMAT_PCM;
	wfx.nChannels = 1;
	wfx.nSamplesPerSec = 11025;
	wfx.wBitsPerSample = 16;
	wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8;
	wfx.cbSize = 0;

	if ((NULL == pDSC) || (NULL == ppDSCB8)) 
		return E_INVALIDARG;
	dscbd.dwSize = sizeof(DSCBUFFERDESC);
	dscbd.dwFlags = 0;
	dscbd.dwBufferBytes = SAMPLES_BUFFER_SIZE * sizeof(short);
	dscbd.dwReserved = 0;
	dscbd.lpwfxFormat = &wfx;
	dscbd.dwFXCount = 0;
	dscbd.lpDSCFXDesc = NULL;

	hr = pDSC->CreateCaptureBuffer(&dscbd, &pDSCB, NULL);

	if (SUCCEEDED(hr))
	{
		hr = pDSCB->QueryInterface(IID_IDirectSoundCaptureBuffer8, (LPVOID*)ppDSCB8);
		pDSCB->Release();  
	}
	else
	{
		fprintf(stderr, "%4.4u %s : 0x%8.8x\n", __LINE__, __FILE__, hr);
	}
	return hr;
}
Esempio n. 4
0
static int capture_init (void)
{
	HRESULT hr;
	DSCBUFFERDESC sound_buffer_rec;
	WAVEFORMATEX wavfmt;
	TCHAR *name;
	int samplerate = 44100;

	if (currprefs.sampler_freq)
		samplerate = currprefs.sampler_freq;

	name = record_devices[currprefs.win32_samplersoundcard]->name;

	wavfmt.wFormatTag = WAVE_FORMAT_PCM;
	wavfmt.nChannels = 2;
	wavfmt.nSamplesPerSec = samplerate;
	wavfmt.wBitsPerSample = 16;
	wavfmt.nBlockAlign = wavfmt.wBitsPerSample / 8 * wavfmt.nChannels;
	wavfmt.nAvgBytesPerSec = wavfmt.nBlockAlign * wavfmt.nSamplesPerSec;
	wavfmt.cbSize = 0;

	clockspersample = sampler_evtime / samplerate;
	sampleframes = (samplerate + 49) / 50;
	recordbufferframes = 16384;
	if (currprefs.sampler_buffer)
		recordbufferframes = currprefs.sampler_buffer;

	hr = DirectSoundCaptureCreate (&record_devices[currprefs.win32_samplersoundcard]->guid, &lpDS2r, NULL);
	if (FAILED (hr)) {
		write_log (_T("SAMPLER: DirectSoundCaptureCreate('%s') failure: %s\n"), name, DXError (hr));
		return 0;
	}
	memset (&sound_buffer_rec, 0, sizeof (DSCBUFFERDESC));
	sound_buffer_rec.dwSize = sizeof (DSCBUFFERDESC);
	sound_buffer_rec.dwBufferBytes = recordbufferframes * SAMPLESIZE;
	sound_buffer_rec.lpwfxFormat = &wavfmt;
	sound_buffer_rec.dwFlags = 0 ;

	hr = lpDS2r->CreateCaptureBuffer (&sound_buffer_rec, &lpDSB2r, NULL);
	if (FAILED (hr)) {
		write_log (_T("SAMPLER: CreateCaptureSoundBuffer('%s') failure: %s\n"), name, DXError(hr));
		return 0;
	}

	hr = lpDSB2r->Start (DSCBSTART_LOOPING);
	if (FAILED (hr)) {
		write_log (_T("SAMPLER: DirectSoundCaptureBuffer_Start('%s') failed: %s\n"), name, DXError (hr));
		return 0;
	}
	samplebuffer = xcalloc (uae_u8, sampleframes * SAMPLESIZE);
	write_log (_T("SAMPLER: Parallel port sampler initialized, CPS=%f, '%s'\n"), clockspersample, name);
	return 1;
}
void VoiceRecord_DSound::Term()
{
	if(m_pCaptureBuffer)
		m_pCaptureBuffer->Release();

	if(m_pCapture)
		m_pCapture->Release();

	if(m_hWrapEvent)
		DeleteObject(m_hWrapEvent);

	if(m_hInstDS)
	{
		FreeLibrary(m_hInstDS);
		m_hInstDS = NULL;
	}

	Clear();
}
bool nuiAudioDevice_DirectSound::Close()
{
  if (mpOutputBuffer)
  {
    mpOutputBuffer->Stop();
  }

  if (mpInputBuffer)
  {
    mpInputBuffer->Stop();
  }

  if (mpProcessingTh)
  {
    mpProcessingTh->Stop();
    mpProcessingTh->Join();
    delete mpProcessingTh;
    mpProcessingTh = NULL;
  }
  if (mpOutputTh)
  {
    mpOutputTh->Stop();
    mpOutputTh->Join();
    delete mpOutputTh;
    mpOutputTh = NULL;
  }



  if (mpOutputBuffer)
  {
    mpOutputBuffer->Release();
    mpOutputBuffer=NULL;
  }

  if (mpInputBuffer)
  {
    mpInputBuffer->Release();
    mpInputBuffer=NULL;
  }

  delete mpRingBuffer;
  mpRingBuffer = NULL;


  if (mNotifInputEvent[0])
  {
    CloseHandle(mNotifInputEvent[0]);
    mNotifInputEvent[0] = NULL;
  }
  if (mNotifInputEvent[1])
  {
    CloseHandle(mNotifInputEvent[1]);
    mNotifInputEvent[1] = NULL;
  }

  if (mNotifOutputEvent[0])
  {
    CloseHandle(mNotifOutputEvent[0]);
    mNotifOutputEvent[0] = NULL;
  }
  if (mNotifOutputEvent[1])
  {
    CloseHandle(mNotifOutputEvent[1]);
    mNotifOutputEvent[1] = NULL;
  }

  return false;
}
bool nuiAudioDevice_DirectSound::Open(std::vector<uint32>& rInputChannels, std::vector<uint32>& rOutputChannels, double SampleRate, uint32 BufferSize, nuiAudioProcessFn pProcessFunction)
{
  if (!mpDirectSound)
    return false;
  
  HRESULT hr = S_OK;
  mAudioProcessFn = pProcessFunction;

  mBufferSize = BufferSize;

  hr = mpDirectSound->SetCooperativeLevel(GetDesktopWindow(), DSSCL_EXCLUSIVE);

  mHasInput = (rInputChannels.size() > 0) && (mInputChannels.size() > 0);
  mHasOutput = (rOutputChannels.size() > 0) && (mOutputChannels.size() > 0);


  mpInputBuffer = NULL;
  mpOutputBuffer = NULL;

  if (!mHasInput && !mHasOutput)
    return false;

  // init ringbuffer
  mpRingBuffer = new nglRingBuffer(BufferSize*4, sizeof(float), rOutputChannels.size());
  mpRingBuffer->AdvanceWriteIndex(BufferSize);

  // init input buffers
  if (mHasInput)
  {
    {
      mActiveInputChannels = rInputChannels;
    }

    WAVEFORMATEX IFormat;
    IFormat.wFormatTag = WAVE_FORMAT_PCM;
    IFormat.nChannels = (WORD)mInputChannels.size();
    IFormat.nSamplesPerSec = ToNearest(SampleRate);
    IFormat.wBitsPerSample = 16;
    IFormat.nAvgBytesPerSec = IFormat.nChannels * IFormat.nSamplesPerSec * (IFormat.wBitsPerSample / 8);
    IFormat.nBlockAlign = IFormat.nChannels * (IFormat.wBitsPerSample / 8);
    IFormat.cbSize = 0;

    DSCBUFFERDESC IBufferDesc;
    memset(&IBufferDesc, 0, sizeof(IBufferDesc));
    IBufferDesc.dwSize = sizeof(DSCBUFFERDESC);
    IBufferDesc.dwFlags = DSCBCAPS_WAVEMAPPED;
    IBufferDesc.dwBufferBytes = (IFormat.wBitsPerSample / 8) * IFormat.nChannels * BufferSize * 2;
    IBufferDesc.dwReserved = 0;
    IBufferDesc.lpwfxFormat = &IFormat;
    IBufferDesc.dwFXCount = 0;
    IBufferDesc.lpDSCFXDesc = NULL;

    NGL_ASSERT(mpDirectSoundCapture);
    hr = mpDirectSoundCapture->CreateCaptureBuffer(&IBufferDesc, &mpInputBuffer, NULL);
  }


  // init output buffers
  if (mHasOutput)
  {
    {
      mActiveOutputChannels = rOutputChannels;
    }

    WAVEFORMATEX OFormat;
    OFormat.wFormatTag = WAVE_FORMAT_PCM;
    OFormat.nChannels = (WORD)mOutputChannels.size();
    OFormat.nSamplesPerSec = ToNearest(SampleRate);
    OFormat.wBitsPerSample = 16;
    OFormat.nAvgBytesPerSec = OFormat.nChannels * OFormat.nSamplesPerSec * (OFormat.wBitsPerSample / 8);
    OFormat.nBlockAlign = OFormat.nChannels * OFormat.wBitsPerSample / 8;
    OFormat.cbSize = 0;

    DSBUFFERDESC  OBufferDesc;
    memset(&OBufferDesc, 0, sizeof(OBufferDesc));
    OBufferDesc.dwSize = sizeof(OBufferDesc);
    OBufferDesc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY;
    OBufferDesc.dwBufferBytes = (OFormat.wBitsPerSample / 8) * OFormat.nChannels * BufferSize * 2;
    OBufferDesc.dwReserved = 0;
    OBufferDesc.lpwfxFormat = &OFormat;

    hr = mpDirectSound->CreateSoundBuffer(&OBufferDesc, &mpOutputBuffer, NULL);
  }


  // create event for notifications
  mNotifInputEvent[0] = CreateEvent(NULL, FALSE, FALSE, _T("NUI_DSoundInputEvent0"));
  mNotifInputEvent[1] = CreateEvent(NULL, FALSE, FALSE, _T("NUI_DSoundInputEvent1"));
  mNotifOutputEvent[0] = CreateEvent(NULL, FALSE, FALSE, _T("NUI_DSoundOutputEvent0"));
  mNotifOutputEvent[1] = CreateEvent(NULL, FALSE, FALSE, _T("NUI_DSoundOutputEvent1"));




  // set the notification for the input buffer
  if (mHasInput)
  {
    // Setup the notification positions
    ZeroMemory( &mInputPosNotify, sizeof(DSBPOSITIONNOTIFY) * 2);
    mInputPosNotify[0].dwOffset = BufferSize * sizeof(int16) * mInputChannels.size() - 1;
    mInputPosNotify[0].hEventNotify = mNotifInputEvent[0];             
    mInputPosNotify[1].dwOffset = BufferSize * sizeof(int16) * mInputChannels.size() * 2 - 1;
    mInputPosNotify[1].hEventNotify = mNotifInputEvent[1];           

    LPDIRECTSOUNDNOTIFY pInputNotify = NULL;
    if( FAILED( hr = mpInputBuffer->QueryInterface( IID_IDirectSoundNotify, (VOID**)&pInputNotify ) ) )
    {
      NGL_LOG(_T("nuiAudioDevice_DirectSound"), NGL_LOG_ERROR, _T("Open ERROR : failed in querying interface for input notifications.\n"));
      return false;
    }


    // Tell DirectSound when to notify us. the notification will come in the from 
    // of signaled events that are handled in WinMain()
    if( FAILED( hr = pInputNotify->SetNotificationPositions( 2, mInputPosNotify ) ) )
    {
      NGL_LOG(_T("nuiAudioDevice_DirectSound"), NGL_LOG_ERROR, _T("Open ERROR : failed in setting notifications for input\n"));
      return false;
    }

    pInputNotify->Release();
  }



  // set the notification events for the output buffer
  if (mHasOutput)
  {
    // Setup the notification positions
    ZeroMemory( &mOutputPosNotify, sizeof(DSBPOSITIONNOTIFY) * 2);
    mOutputPosNotify[0].dwOffset = BufferSize * sizeof(int16) * mOutputChannels.size() - 1;
    mOutputPosNotify[0].hEventNotify = mNotifOutputEvent[0];             
    mOutputPosNotify[1].dwOffset = BufferSize * sizeof(int16) * mOutputChannels.size() * 2 - 1;
    mOutputPosNotify[1].hEventNotify = mNotifOutputEvent[1];    

    LPDIRECTSOUNDNOTIFY pOutputNotify = NULL;
    if( FAILED( hr = mpOutputBuffer->QueryInterface( IID_IDirectSoundNotify, (VOID**)&pOutputNotify ) ) )
    {
      NGL_LOG(_T("nuiAudioDevice_DirectSound"), NGL_LOG_ERROR, _T("Open ERROR : failed in querying interface for output notifications.\n"));
      return false;
    }

    // Tell DirectSound when to notify us. the notification will come in the from 
    // of signaled events that are handled in WinMain()
    if( FAILED( hr = pOutputNotify->SetNotificationPositions( 2, mOutputPosNotify ) ) )
    {
      NGL_LOG(_T("nuiAudioDevice_DirectSound"), NGL_LOG_ERROR, _T("Open ERROR : failed in setting notifications for output\n"));
      return false;
    }

    pOutputNotify->Release();
  }


  // start input processing thread
  mpProcessingTh = new nuiAudioDevice_DS_ProcessingTh(this, mNotifInputEvent[0], mNotifInputEvent[1], mAudioProcessFn);
  mpProcessingTh->Start();



  // start output thread
  if (mHasOutput)
  {
    mpOutputTh = new nuiAudioDevice_DS_OutputTh(this, mNotifInputEvent[0], mNotifInputEvent[1], mNotifOutputEvent[0], mNotifOutputEvent[1]);
    mpOutputTh->Start();
    hr = mpOutputBuffer->Play(0,0,DSCBSTART_LOOPING);
    if (FAILED(hr))
      NGL_LOG(_T("nuiAudioDevice_DirectSound"), NGL_LOG_ERROR, _T("OutputBuffer->Play ERROR!\n"));
  }

  // start input capture
  if (mHasInput)
  {
    hr = mpInputBuffer->Start(DSCBSTART_LOOPING);
    if (FAILED(hr))
      NGL_LOG(_T("nuiAudioDevice_DirectSound"), NGL_LOG_ERROR, _T("InputBuffer->Start ERROR!\n"));    
  }





  return true;
}
Esempio n. 8
0
void DXAudioInput::run() {
	LPDIRECTSOUNDCAPTURE8      pDSCapture;
	LPDIRECTSOUNDCAPTUREBUFFER pDSCaptureBuffer;
	LPDIRECTSOUNDNOTIFY8       pDSNotify;

	DWORD dwBufferSize;
	bool bOk;
	DWORD dwReadyBytes = 0;
	DWORD dwLastReadPos = 0;
	DWORD dwReadPosition;
	DWORD dwCapturePosition;

	LPVOID aptr1, aptr2;
	DWORD nbytes1, nbytes2;

	HRESULT       hr;
	WAVEFORMATEX  wfx;
	DSCBUFFERDESC dscbd;

	pDSCapture = NULL;
	pDSCaptureBuffer = NULL;
	pDSNotify = NULL;

	bOk = false;

	bool failed = false;
	float safety = 2.0f;
	bool didsleep = false;
	bool firstsleep = false;

	Timer t;

	ZeroMemory(&wfx, sizeof(wfx));
	wfx.wFormatTag = WAVE_FORMAT_PCM;

	ZeroMemory(&dscbd, sizeof(dscbd));
	dscbd.dwSize = sizeof(dscbd);

	dscbd.dwBufferBytes = dwBufferSize = iFrameSize * sizeof(short) * NBUFFBLOCKS;
	dscbd.lpwfxFormat = &wfx;

	wfx.nChannels = 1;
	wfx.nSamplesPerSec = iSampleRate;
	wfx.nBlockAlign = 2;
	wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
	wfx.wBitsPerSample = 16;

	// Create IDirectSoundCapture using the preferred capture device
	if (! g.s.qbaDXInput.isEmpty()) {
		LPGUID lpguid = reinterpret_cast<LPGUID>(g.s.qbaDXInput.data());
		if (FAILED(hr = DirectSoundCaptureCreate8(lpguid, &pDSCapture, NULL))) {
			failed = true;
		}
	}

	if (! pDSCapture && FAILED(hr = DirectSoundCaptureCreate8(&DSDEVID_DefaultVoiceCapture, &pDSCapture, NULL)))
		qWarning("DXAudioInput: DirectSoundCaptureCreate failed: hr=0x%08lx", hr);
	else if (FAILED(hr = pDSCapture->CreateCaptureBuffer(&dscbd, &pDSCaptureBuffer, NULL)))
		qWarning("DXAudioInput: CreateCaptureBuffer failed: hr=0x%08lx", hr);
	else if (FAILED(hr = pDSCaptureBuffer->QueryInterface(IID_IDirectSoundNotify, reinterpret_cast<void **>(&pDSNotify))))
		qWarning("DXAudioInput: QueryInterface (Notify) failed: hr=0x%08lx", hr);
	else
		bOk = true;



	if (failed)
		g.mw->msgBox(tr("Opening chosen DirectSound Input failed. Default device will be used."));

	qWarning("DXAudioInput: Initialized");

	if (! bOk)
		goto cleanup;

	if (FAILED(hr = pDSCaptureBuffer->Start(DSCBSTART_LOOPING))) {
		qWarning("DXAudioInput: Start failed: hr=0x%08lx", hr);
	} else {
		while (bRunning) {
			firstsleep = true;
			didsleep = false;

			do {
				if (FAILED(hr = pDSCaptureBuffer->GetCurrentPosition(&dwCapturePosition, &dwReadPosition))) {
					qWarning("DXAudioInput: GetCurrentPosition failed: hr=0x%08lx", hr);
					bRunning = false;
					break;
				}
				if (dwReadPosition < dwLastReadPos)
					dwReadyBytes = (dwBufferSize - dwLastReadPos) + dwReadPosition;
				else
					dwReadyBytes = dwReadPosition - dwLastReadPos;

				if (static_cast<int>(dwReadyBytes) < sizeof(short) * iFrameSize) {
					double msecleft = 20.0 - (dwReadyBytes * 20.0) / (sizeof(short) * iFrameSize);

					if (didsleep)
						safety *= 1.1f;
					else if (firstsleep)
						safety *= 0.998f;

					int msec = static_cast<int>(msecleft + (firstsleep ? safety : 0.0));

					msleep(msec);

					didsleep = true;
					firstsleep = false;
				}
			} while (static_cast<int>(dwReadyBytes) < sizeof(short) * iFrameSize);

			// Desynchonized?
			if (dwReadyBytes > (dwBufferSize / 2)) {
				qWarning("DXAudioInput: Lost synchronization");
				dwLastReadPos = dwReadPosition;
			} else if (bRunning) {
				if (FAILED(hr = pDSCaptureBuffer->Lock(dwLastReadPos, sizeof(short) * iFrameSize, &aptr1, &nbytes1, &aptr2, &nbytes2, 0))) {
					qWarning("DXAudioInput: Lock from %ld (%d bytes) failed: hr=0x%08lx",dwLastReadPos, sizeof(short) * iFrameSize, hr);
					bRunning = false;
					break;
				}

				if (aptr1 && nbytes1)
					CopyMemory(psMic, aptr1, nbytes1);

				if (aptr2 && nbytes2)
					CopyMemory(psMic+nbytes1/2, aptr2, nbytes2);

				if (FAILED(hr = pDSCaptureBuffer->Unlock(aptr1, nbytes1, aptr2, nbytes2))) {
					qWarning("DXAudioInput: Unlock failed: hr=0x%08lx", hr);
					bRunning = false;
					break;
				}

				dwLastReadPos = (dwLastReadPos + sizeof(short) * iFrameSize) % dwBufferSize;

				encodeAudioFrame();
			}
		}
		if (! FAILED(hr))
			pDSCaptureBuffer->Stop();
	}
	if (FAILED(hr)) {
		g.mw->msgBox(tr("Lost DirectSound input device."));
	}

cleanup:
	if (! bOk) {
		g.mw->msgBox(tr("Opening chosen DirectSound Input device failed. No microphone capture will be done."));
	}
	if (pDSNotify)
		pDSNotify->Release();
	if (pDSCaptureBuffer)
		pDSCaptureBuffer->Release();
	if (pDSCapture)
		pDSCapture->Release();
}
bool DSoundVoiceAdapter::SetupOutgoingBuffer()
{
	HRESULT hr;

	//
	//
	// Create the buffer for outgoing sound
	//
	//
	if (FAILED(hr=DirectSoundCaptureCreate8(NULL, &dsC, NULL)))
	{
		DXTRACE_ERR_MSGBOX(L"DirectSoundCaptureCreate8", hr);
		return false;
	}

	// Set up WAV format structure. 
	WAVEFORMATEX wfx; 
	memset(&wfx, 0, sizeof(WAVEFORMATEX)); 
	wfx.wFormatTag = WAVE_FORMAT_PCM; 
	wfx.nChannels = 1; 
	wfx.nSamplesPerSec = rakVoice->GetSampleRate(); 
	wfx.nBlockAlign = 2; 
	wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; 
	wfx.wBitsPerSample = 16; 
	// Set up DSCBUFFERDESC structure. 
	DSCBUFFERDESC dscbd;
	memset(&dscbd, 0, sizeof(DSCBUFFERDESC));
	dscbd.dwSize = sizeof(DSCBUFFERDESC);
	dscbd.dwFlags = 0;
	dscbd.dwBufferBytes = rakVoice->GetBufferSizeBytes()*FRAMES_IN_SOUND; 
	dscbd.dwReserved = 0;
	dscbd.lpwfxFormat = &wfx;
	dscbd.dwFXCount = 0;
	dscbd.lpDSCFXDesc = NULL;
	// Create capture buffer.
	LPDIRECTSOUNDCAPTUREBUFFER pDscb = NULL;
	if (FAILED(hr = dsC->CreateCaptureBuffer(&dscbd, &pDscb, NULL)))
	{
		DXTRACE_ERR_MSGBOX(L"IDirectSoundCapture8::CreateCaptureBuffer, when creating buffer for outgoing sound )", hr);
		return false;
	}
	hr = pDscb->QueryInterface(IID_IDirectSoundCaptureBuffer8, (LPVOID*) &dsbOutgoing);
	pDscb->Release();
	if (FAILED(hr))
	{
		DXTRACE_ERR_MSGBOX(L"IDirectSoundBuffer::QueryInterface, when getting IDirectSoundCaptureBuffer8 interface for outgoing sound", hr);
		return false;
	}
	//
	// Setup the notification events
	//
	for (int i=0; i<FRAMES_IN_SOUND; i++)
	{
		outgoingBufferNotifications[i].dwOffset = i*rakVoice->GetBufferSizeBytes();
		if ((outgoingBufferNotifications[i].hEventNotify = CreateEventEx(0, 0, CREATE_EVENT_MANUAL_RESET, 0))==NULL)
		{
			DXTRACE_ERR_MSGBOX(L"CreateEvent", GetLastError());
			return false;
		}
	}
	IDirectSoundNotify8 *dsbNotify=0;
	if (FAILED(hr=dsbOutgoing->QueryInterface(IID_IDirectSoundNotify8, (LPVOID*) &dsbNotify)))
	{
		DXTRACE_ERR_MSGBOX(L"IDirectSoundCaptureBuffer8::QueryInterface, when getting IDirectSoundNotify8 interface for outgoing sound", hr);
		return false;
	}
	hr = dsbNotify->SetNotificationPositions(FRAMES_IN_SOUND, outgoingBufferNotifications);
	dsbNotify->Release();
	if (FAILED(hr))
	{
		DXTRACE_ERR_MSGBOX(L"IDirectSoundNotify8::SetNotificationPositions, when setting notifications for outgoing sound", hr);
		return false;
	}

	if (FAILED(hr = dsbOutgoing->Start(DSCBSTART_LOOPING)))
	{
		DXTRACE_ERR_MSGBOX(L"IDirectSoundCaptureBuffer8::Start, when starting outgoing sound buffer", hr);
		return false;
	}

	return true;
}
Esempio n. 10
0
bool SoundRecoder::createBuffer(LPGUID guid)
{
	//デバイスの作成
	HMODULE library = LoadLibraryA("dsound.dll");
	if(!library)
		return false;

	HRESULT (WINAPI *DirectSoundCaptureCreate8)(LPCGUID,LPDIRECTSOUNDCAPTURE8*,LPUNKNOWN) =
		(HRESULT (WINAPI *)(LPCGUID,LPDIRECTSOUNDCAPTURE8*,LPUNKNOWN))
		GetProcAddress(library,"DirectSoundCaptureCreate8");

	DirectSoundCaptureCreate8(guid,&m_soundCapture,NULL);

	FreeLibrary(library);

	//デバイスが作成できなかったら終了
	if(!m_soundCapture)
		return false;

	if(m_soundCaptureBuffer)
	{
		m_soundCaptureBuffer->Release();
		m_soundCaptureBuffer = NULL;
	}
	DSCBUFFERDESC dscbd;
	WAVEFORMATEX wfx = 
	{
		WAVE_FORMAT_PCM,
		m_bufferChannel,
		m_bufferRate,
		m_bufferRate*m_bufferChannel*m_bufferBit/8,
		m_bufferChannel*m_bufferBit/8,
		m_bufferBit, 0
	};

	m_bufferSize =  wfx.nAvgBytesPerSec*m_bufferMSec/1000;

	dscbd.dwSize = sizeof(DSCBUFFERDESC);
	dscbd.dwFlags = 0;
	dscbd.dwBufferBytes = m_bufferSize;
	dscbd.dwReserved = 0;
	dscbd.lpwfxFormat = &wfx;
	dscbd.dwFXCount = 0;
	dscbd.lpDSCFXDesc = NULL;
	
	m_latency = m_bufferSize / m_notifyCount;


	LPDIRECTSOUNDCAPTUREBUFFER soundBuffer = NULL;
	m_soundCapture->CreateCaptureBuffer(&dscbd, &soundBuffer, NULL);
	if(!soundBuffer)
		return false;
	soundBuffer->QueryInterface(IID_IDirectSoundCaptureBuffer8,(LPVOID*)&m_soundCaptureBuffer);
	soundBuffer->Release();

	if(!m_soundCaptureBuffer)
		return false;

	INT i;
	for(i=0;i<m_notifyCount;i++)
	{
		m_positionNotify[i].dwOffset = (dscbd.dwBufferBytes /m_notifyCount)*i ;
	}

	LPDIRECTSOUNDNOTIFY8 dsNotify;
	m_soundCaptureBuffer->QueryInterface(IID_IDirectSoundNotify, (LPVOID*)&dsNotify);
	dsNotify->SetNotificationPositions(m_notifyCount, m_positionNotify);
	dsNotify->Release();

	return true;
}
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;
}
int VoiceRecord_DSound::GetRecordedData(short *pOut, int nSamplesInt)
{
	if(!m_pCaptureBuffer)
	{
		assert(false);
		return 0;
	}

	DWORD dwStatus;
	HRESULT hr = m_pCaptureBuffer->GetStatus(&dwStatus);
	if(FAILED(hr) || !(dwStatus & DSCBSTATUS_CAPTURING))
		return 0;
	
	Idle();	// Update wrapping..

	DWORD nSamplesWanted = (DWORD)nSamplesInt;

	DWORD dwCapturePos, dwReadPos;
	hr = m_pCaptureBuffer->GetCurrentPosition(&dwCapturePos, &dwReadPos);
	if(FAILED(hr))
		return 0;

	dwCapturePos += m_WrapOffset;
	dwReadPos += m_WrapOffset;

	// Read the range (dwReadPos-nSamplesWanted, dwReadPos), but don't re-read data we've already read.
	DWORD readStart;
	if(dwReadPos > nSamplesWanted)
		readStart = dwReadPos - nSamplesWanted;
	else
		readStart = 0;
	
	if(readStart < m_LastReadPos)
		readStart = m_LastReadPos;

	// Lock the buffer.
	LPVOID pData[2];
	DWORD dataLen[2];

	hr = m_pCaptureBuffer->Lock(
		readStart % NumCaptureBufferBytes(),	// Offset.
		dwReadPos - readStart,					// Number of bytes to lock.
		&pData[0],								// Buffer 1.
		&dataLen[0],							// Buffer 1 length.
		&pData[1],								// Buffer 2.
		&dataLen[1],							// Buffer 2 length.
		0										// Flags.
	);

	if(FAILED(hr))
		return 0;

	// Hopefully we didn't get too much data back!
	if((dataLen[0]+dataLen[1]) > nSamplesWanted)
	{
		assert(false);
		m_pCaptureBuffer->Unlock(pData[0], dataLen[0], pData[1], dataLen[1]);
		return 0;
	}

	// Copy the data to the output.
	memcpy(pOut, pData[0], dataLen[0]);
	memcpy(&pOut[dataLen[0]/2], pData[1], dataLen[1]);

	m_pCaptureBuffer->Unlock(pData[0], dataLen[0], pData[1], dataLen[1]);

	// Update the shiz.
	m_LastReadPos = dwReadPos;
	return (dataLen[0] + dataLen[1]) >> 1;
}
bool VoiceRecord_DSound::Init(int sampleRate)
{
	HRESULT hr;
	DSCBUFFERDESC dscDesc;
	DirectSoundCaptureCreateFn createFn;

	
	Term();


	WAVEFORMATEX recordFormat =
	{
		WAVE_FORMAT_PCM,		// wFormatTag
		1,						// nChannels
		sampleRate,				// nSamplesPerSec
		sampleRate*2,			// nAvgBytesPerSec
		2,						// nBlockAlign
		16,						// wBitsPerSample
		sizeof(WAVEFORMATEX)	// cbSize
	};


	
	// Load the DSound DLL.
	m_hInstDS = LoadLibrary("dsound.dll");
	if(!m_hInstDS)
		goto HandleError;

	createFn = (DirectSoundCaptureCreateFn)GetProcAddress(m_hInstDS, "DirectSoundCaptureCreate");
	if(!createFn)
		goto HandleError;

	hr = createFn(NULL, &m_pCapture, NULL);
	if(FAILED(hr))
		goto HandleError;

	// Create the capture buffer.
	memset(&dscDesc, 0, sizeof(dscDesc));
	dscDesc.dwSize = sizeof(dscDesc);
	dscDesc.dwFlags = 0;
	dscDesc.dwBufferBytes = recordFormat.nAvgBytesPerSec;
	dscDesc.lpwfxFormat = &recordFormat;

	hr = m_pCapture->CreateCaptureBuffer(&dscDesc, &m_pCaptureBuffer, NULL);
	if(FAILED(hr))
		goto HandleError;


	// Figure out how many bytes we got in our capture buffer.
	DSCBCAPS caps;
	memset(&caps, 0, sizeof(caps));
	caps.dwSize = sizeof(caps);

	hr = m_pCaptureBuffer->GetCaps(&caps);
	if(FAILED(hr))
		goto HandleError;

	m_nCaptureBufferBytes = caps.dwBufferBytes;


	// Set it up so we get notification when the buffer wraps.
	m_hWrapEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	if(!m_hWrapEvent)
		goto HandleError;

	DSBPOSITIONNOTIFY dsbNotify;
	dsbNotify.dwOffset = dscDesc.dwBufferBytes - 1;
	dsbNotify.hEventNotify = m_hWrapEvent;
	
	// Get the IDirectSoundNotify interface.
	LPDIRECTSOUNDNOTIFY pNotify;
	hr = m_pCaptureBuffer->QueryInterface(IID_IDirectSoundNotify, (void**)&pNotify);
	if(FAILED(hr))
		goto HandleError;
	
	hr = pNotify->SetNotificationPositions(1, &dsbNotify);
	pNotify->Release();
	if(FAILED(hr))
		goto HandleError;

	// Start capturing.
	hr = m_pCaptureBuffer->Start(DSCBSTART_LOOPING);
	if(FAILED(hr))
		return false;

	return true;


HandleError:;
	Term();
	return false;
}
Esempio n. 14
0
uae_u8 sampler_getsample (int channel)
{
#if 0
	int cur_pos;
	static int cap_pos;
	static float diffsample;
#endif
	static double doffset_offset;
	HRESULT hr;
	DWORD t;
	void *p1, *p2;
	DWORD len1, len2;
	evt cycles;
	int sample, samplecnt;
	double doffset;
	int offset;

	if (!currprefs.sampler_stereo)
		channel = 0;

	if (!inited) {
		DWORD pos;
		if (!capture_init ()) {
			capture_free ();
			return 0;
		}
		inited = 1;
		oldcycles = get_cycles ();
		oldoffset = -1;
		doffset_offset = 0;
		hr = lpDSB2r->GetCurrentPosition (&t, &pos);
		if (FAILED (hr)) {
			sampler_free ();
			return 0;
		}		
		if (t >= pos)
			safediff = t - pos;
		else
			safediff = recordbufferframes * SAMPLESIZE - pos + t;
		write_log (_T("SAMPLER: safediff %d %d\n"), safediff, safediff + sampleframes * SAMPLESIZE);
		safediff += 4 * sampleframes * SAMPLESIZE;

#if 0
		diffsample = 0;
		safepos = -recordbufferframes / 10 * SAMPLESIZE;
		hr = lpDSB2r->GetCurrentPosition (&t, &pos);
		cap_pos = pos;
		cap_pos += safepos;
		if (cap_pos < 0)
			cap_pos += recordbufferframes * SAMPLESIZE;
		if (cap_pos >= recordbufferframes * SAMPLESIZE)
			cap_pos -= recordbufferframes * SAMPLESIZE;
		if (FAILED (hr)) {
			sampler_free ();
			return 0;
		}
#endif
	}
	if (clockspersample < 1)
		return 0;
	uae_s16 *sbuf = (uae_s16*)samplebuffer;

	vsynccnt = 0;
	sample = 0;
	samplecnt = 0;
	cycles = (int)get_cycles () - (int)oldcycles;
	doffset = doffset_offset + cycles / clockspersample;
	offset = (int)doffset;
	if (oldoffset < 0 || offset >= sampleframes || offset < 0) {
		if (offset >= sampleframes) {
			doffset -= offset;
			doffset_offset = doffset;
		}
		if (oldoffset >= 0 && offset >= sampleframes) {
			while (oldoffset < sampleframes) {
				sample += sbuf[oldoffset * SAMPLESIZE / 2 + channel];
				oldoffset++;
				samplecnt++;
			}
		}
		hr = lpDSB2r->GetCurrentPosition (&t, NULL);
		int pos = t;
		pos -= safediff;
		if (pos < 0)
			pos += recordbufferframes * SAMPLESIZE;
		hr = lpDSB2r->Lock (pos, sampleframes * SAMPLESIZE, &p1, &len1, &p2, &len2, 0);
		if (FAILED (hr)) {
			write_log (_T("SAMPLER: Lock() failed %x\n"), hr);
			return 0;
		}
		memcpy (samplebuffer, p1, len1);
		if (p2)
			memcpy (samplebuffer + len1, p2, len2);
		lpDSB2r->Unlock (p1, len1, p2, len2);

#if 0
		cap_pos = t;
		cap_pos += sampleframes * SAMPLESIZE;
		if (cap_pos < 0)
			cap_pos += RECORDBUFFER * SAMPLESIZE;
		if (cap_pos >= RECORDBUFFER * SAMPLESIZE)
			cap_pos -= RECORDBUFFER * SAMPLESIZE;

		hr = lpDSB2r->GetCurrentPosition (&t, &pos);
		cur_pos = pos;
		if (FAILED (hr))
			return 0;

		cur_pos += safepos;
		if (cur_pos < 0)
			cur_pos += RECORDBUFFER * SAMPLESIZE;
		if (cur_pos >= RECORDBUFFER * SAMPLESIZE)
			cur_pos -= RECORDBUFFER * SAMPLESIZE;

		int diff;
		if (cur_pos >= cap_pos)
			diff = cur_pos - cap_pos;
		else
			diff = RECORDBUFFER * SAMPLESIZE - cap_pos + cur_pos;
		if (diff > RECORDBUFFER * SAMPLESIZE / 2)
			diff -= RECORDBUFFER * SAMPLESIZE; 
		diff /= SAMPLESIZE;

		int diff2 = 100 * diff / (RECORDBUFFER / 2);
		diffsample = -pow (diff2 < 0 ? -diff2 : diff2, 3.1);
		if (diff2 < 0)
			diffsample = -diffsample;
		write_log (_T("%d\n"), diff);

		write_log (_T("CAP=%05d CUR=%05d (%-05d) OFF=%05d %f\n"),
			cap_pos / SAMPLESIZE, cur_pos / SAMPLESIZE, (cap_pos - cur_pos) / SAMPLESIZE, offset, doffset_offset);
#endif

		if (offset < 0)
			offset = 0;
		if (offset >= sampleframes)
			offset -= sampleframes;

		oldoffset = 0;
		oldcycles = get_cycles ();
	}

	while (oldoffset <= offset) {
		sample += sbuf[oldoffset * SAMPLESIZE / 2 + channel];
		samplecnt++;
		oldoffset++;
	}
	oldoffset = offset;

	if (samplecnt > 0)
		sample /= samplecnt;
#if 1
	 /* yes, not 256, without this max recording volume would still be too quiet on my sound cards */
	sample /= 128;
	if (sample < -128)
		sample = 0;
	else if (sample > 127)
		sample = 127;
	return (uae_u8)(sample - 128);
#else
	return (Uae_u8)((sample / 256) - 128);
#endif
}
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;
}
int audioStreamer_ds::Read(char *buf, int len) // returns 0 if blocked, < 0 if error, > 0 if data
{
  if (!m_inbuf) return -1;
  if (!m_has_started)
  {
    m_inbuf->Start(DSCBSTART_LOOPING);
    m_has_started=1;
  }

  int cappos;
  m_inbuf->GetCurrentPosition(NULL,(DWORD *)&cappos);
  if (cappos < m_last_pos) m_i_dw++;
  m_last_pos=cappos;

  if ((m_i_dw - m_i_lw) * m_totalbufsize + cappos - m_bufpos >= (unsigned int)m_totalbufsize/2) // detect overrun, set to cappos
  {
    m_i_lw=m_i_dw;
    m_bufpos=0;
    while (m_bufpos < cappos-m_bufsize) m_bufpos += m_bufsize;
    if (m_bufpos >= m_totalbufsize) 
    {
      m_i_lw++;
      m_bufpos -= m_totalbufsize;
    }
//    audiostream_onover();
  }

  for (;;)
  {
    if (m_i_lw < m_i_dw || m_bufpos + m_bufsize < cappos) break;

    Sleep(DS_SLEEP);
    m_inbuf->GetCurrentPosition(NULL,(DWORD*)&cappos);

    if (cappos < m_last_pos) m_i_dw++;
    m_last_pos=cappos;
  }

  //audiostream_instance->g_sound_in_overruns = (m_i_lw < m_i_dw ? (m_totalbufsize+cappos) : cappos ) -m_bufpos;

  void *v1=0, *v2=0;
  DWORD lv1=0, lv2=0;
  
  if (m_inbuf->Lock(m_bufpos,len,&v1,&lv1,&v2,&lv2,FALSE) == DS_OK)
  {
    int l1=min((int)lv1,len);
    memcpy(buf,v1,l1);
    if (l1 < len && v2 && lv2) memcpy(buf+l1,v2,min((int)lv2,len-l1));
    m_inbuf->Unlock(v1,lv1,v2,lv2);

    m_bufpos += len;
    if (m_bufpos >= m_totalbufsize) 
    {
      m_i_lw++;
      m_bufpos -= m_totalbufsize;
    }
  }
  else 
  {
    return -1;
  }

  return len;
}