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); }
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; }
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; }
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; }
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; }
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; }
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; }