int audioStreamer_ds::Open(int iswrite, int srate, int nch, int bps, int sleep, int nbufs, int bufsize, GUID *device) { // todo: use device m_sleep = sleep >= 0 ? sleep : 0; GUID zero={0,}; if (!memcmp(device,&zero,sizeof(zero))) device=NULL; m_nch = nch; m_srate=srate; m_bps=bps; int fmt_align=(bps>>3)*nch; int fmt_mul=fmt_align*srate; WAVEFORMATEX wfx={ WAVE_FORMAT_PCM, nch, srate, fmt_mul, fmt_align, bps, 0 }; m_totalbufsize=nbufs*bufsize; if (iswrite) { DirectSoundCreate(device,&m_lpds,NULL); if (m_lpds) { HWND hWnd = GetForegroundWindow(); if (hWnd == NULL) hWnd = GetDesktopWindow(); m_lpds->SetCooperativeLevel(hWnd,DSSCL_PRIORITY); // create a secondary buffer for now DSBUFFERDESC ds={sizeof(ds),DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_GLOBALFOCUS,m_totalbufsize,0,&wfx, }; m_lpds->CreateSoundBuffer(&ds,&m_outbuf,NULL); } } else { DirectSoundCaptureCreate(device,&m_lpcap,NULL); if (m_lpcap) { DSCBUFFERDESC ds={sizeof(ds),0,m_totalbufsize,0,&wfx, }; m_lpcap->CreateCaptureBuffer(&ds,&m_inbuf,NULL); } } m_bufsize=bufsize; return 0; }
nuiAudioDevice_DirectSound::nuiAudioDevice_DirectSound(GUID IGuid, GUID OGuid, const nglString& rInName, const nglString& rOutName, const nglString& rInModule, const nglString& rOutModule) : nuiAudioDevice() { mInName = rInName; mOutName = rOutName; if (rOutName.IsEmpty()) mName = rInName; else mName = rOutName; mManufacturer = rOutModule; mIsPresent = false; mHasInput = false; mHasOutput = false; mIDeviceID = IGuid; mODeviceID = OGuid; mpDirectSound = NULL; mpDirectSoundCapture = NULL; mAPIName = API_NAME; mpRingBuffer = NULL; mpInputBuffer = NULL; mpOutputBuffer = NULL; mpProcessingTh = NULL; mpOutputTh = NULL; mNotifInputEvent[0] = NULL; mNotifInputEvent[1] = NULL; mNotifOutputEvent[0] = NULL; mNotifOutputEvent[1] = NULL; HRESULT hr; // Get Input device caps: hr = DirectSoundCaptureCreate(&mIDeviceID, &mpDirectSoundCapture, NULL); if (hr != S_OK || !mpDirectSoundCapture) { NGL_LOG(_T("nuiAudioDevice_DirectSound"), NGL_LOG_INFO, _T("constructor ERROR : could not create DirectSoundCapture object!\n")); } // Get Output device caps: hr = DirectSoundCreate(&mODeviceID, &mpDirectSound, NULL); if (hr != S_OK || !mpDirectSound) { NGL_LOG(_T("nuiAudioDevice_DirectSound"), NGL_LOG_ERROR, _T("constructor ERROR : could not create DirectSound object!\n")); // if there is no output, consider the device as not valid return; } Init(); }
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; }
/* ============ Media Producer Interface ================= */ int tdav_producer_dsound_prepare(tmedia_producer_t* self, const tmedia_codec_t* codec) { HRESULT hr; WAVEFORMATEX wfx = {0}; DSCBUFFERDESC dsbd = {0}; tdav_producer_dsound_t* dsound = (tdav_producer_dsound_t*)self; if(!dsound || !codec){ TSK_DEBUG_ERROR("Invalid parameter"); return -1; } if(dsound->device || dsound->captureBuffer){ TSK_DEBUG_ERROR("Producer already prepared"); return -2; } TDAV_PRODUCER_AUDIO(dsound)->channels = codec->plugin->audio.channels; TDAV_PRODUCER_AUDIO(dsound)->rate = codec->plugin->rate; /* Create capture device */ if((hr = DirectSoundCaptureCreate(NULL, &dsound->device, NULL) != DS_OK)){ tdav_win32_print_error("DirectSoundCaptureCreate", hr); return -3; } /* Creates the capture buffer */ wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = TDAV_PRODUCER_AUDIO(dsound)->channels; wfx.nSamplesPerSec = TDAV_PRODUCER_AUDIO(dsound)->rate; wfx.wBitsPerSample = TDAV_PRODUCER_AUDIO(dsound)->bits_per_sample; wfx.nBlockAlign = (wfx.nChannels * wfx.wBitsPerSample/8); wfx.nAvgBytesPerSec = (wfx.nSamplesPerSec * wfx.nBlockAlign); /* Average bytes (count) for each notification */ dsound->bytes_per_notif = ((wfx.nAvgBytesPerSec * TDAV_PRODUCER_AUDIO(dsound)->ptime)/1000); dsbd.dwSize = sizeof(DSCBUFFERDESC); dsbd.dwBufferBytes = (TDAV_DSOUNS_PRODUCER_NOTIF_POS_COUNT * dsound->bytes_per_notif); dsbd.lpwfxFormat = &wfx; if((hr = IDirectSoundCapture_CreateCaptureBuffer(dsound->device, &dsbd, &dsound->captureBuffer, NULL)) != DS_OK){ tdav_win32_print_error("IDirectSoundCapture_CreateCaptureBuffer", hr); return -4; } return 0; }
void *DSOUND_Capture_Init (int rate) { dsndcapture_t *result; DSCBUFFERDESC bufdesc = {0}; WAVEFORMATEX wfxFormat = {0}; Com_DPrintf("DSOUND_Capture_Init: rate %d\n", rate); wfxFormat.wFormatTag = WAVE_FORMAT_PCM; wfxFormat.nChannels = 1; wfxFormat.nSamplesPerSec = rate; wfxFormat.wBitsPerSample = 8*inputwidth; wfxFormat.nBlockAlign = wfxFormat.nChannels * (wfxFormat.wBitsPerSample / 8); wfxFormat.nAvgBytesPerSec = wfxFormat.nSamplesPerSec * wfxFormat.nBlockAlign; wfxFormat.cbSize = 0; bufdesc.dwSize = sizeof(bufdesc); bufdesc.dwBufferBytes = bufferbytes; bufdesc.dwFlags = 0; bufdesc.dwReserved = 0; bufdesc.lpwfxFormat = &wfxFormat; result = Z_Malloc(sizeof(*result)); if (FAILED(DirectSoundCaptureCreate(NULL, &result->DSCapture, NULL))) { Com_Printf_State (PRINT_FAIL, "DirectSound: Couldn't create a capture device\n"); } else if (FAILED(IDirectSoundCapture_CreateCaptureBuffer(result->DSCapture, &bufdesc, &result->DSCaptureBuffer, NULL))) { Com_Printf_State (PRINT_FAIL, "DirectSound: Couldn't create a capture buffer\n"); } else { Com_DPrintf("DSOUND_Capture_Init: OK\n"); return result; } // failure, lets clean up. if (result->DSCapture) { IDirectSoundCapture_Release(result->DSCapture); } Z_Free(result); return NULL; }
nuiAudioDevice_DirectSound::nuiAudioDevice_DirectSound() : nuiAudioDevice() { mInName = _T("Default Device"); mOutName = _T("Default Device"); mIsPresent = false; mHasInput = false; mHasOutput = false; mpDirectSound = NULL; mpDirectSoundCapture = NULL; mAPIName = API_NAME; mpRingBuffer = NULL; mpInputBuffer = NULL; mpOutputBuffer = NULL; mpProcessingTh = NULL; mpOutputTh = NULL; mNotifInputEvent[0] = NULL; mNotifInputEvent[1] = NULL; mNotifOutputEvent[0] = NULL; mNotifOutputEvent[1] = NULL; HRESULT hr; // Get Input device caps: hr = DirectSoundCaptureCreate(NULL, &mpDirectSoundCapture, NULL); if (hr != S_OK || !mpDirectSoundCapture) { NGL_LOG(_T("nuiAudioDevice_DirectSound"), NGL_LOG_INFO, _T("constructor ERROR : could not create DirectSoundCapture object!\n")); } // Get Output device caps: hr = DirectSoundCreate(NULL, &mpDirectSound, NULL); if (hr != S_OK || !mpDirectSound) { NGL_LOG(_T("nuiAudioDevice_DirectSound"), NGL_LOG_ERROR, _T("constructor ERROR : could not create DirectSound object!\n"));// if there is no output, consider the device as not valid return; } Init(); }
HRESULT SoundCapture::Open( DWORD dwSampleRate, WORD wBitPerSample, WORD wChannels ) { GUID deviceGuid = GUID_NULL; HRESULT hr = DirectSoundCaptureCreate( &deviceGuid, &m_pDSCapture, NULL ); m_dwNextCaptureOffset = 0; WAVEFORMATEX wfxInput; ZeroMemory ( &wfxInput, sizeof(wfxInput) ); wfxInput.wFormatTag = WAVE_FORMAT_PCM; wfxInput.nSamplesPerSec = dwSampleRate; wfxInput.wBitsPerSample = wBitPerSample; wfxInput.nChannels = wChannels; wfxInput.nBlockAlign = wfxInput.nChannels * ( wfxInput.wBitsPerSample / 8 ); wfxInput.nAvgBytesPerSec = wfxInput.nBlockAlign * wfxInput.nSamplesPerSec; DWORD dwNotifySize = max( 1024, wfxInput.nAvgBytesPerSec / 8 ); dwNotifySize -= dwNotifySize % wfxInput.nBlockAlign; m_dwCaptureBufferSize = dwNotifySize * NUM_REC_NOTIFICATIONS; DSCBUFFERDESC dscbd; ZeroMemory( &dscbd, sizeof(dscbd) ); dscbd.dwSize = sizeof(dscbd); dscbd.dwBufferBytes = m_dwCaptureBufferSize; dscbd.lpwfxFormat = &wfxInput; // Set the format during creatation hr = m_pDSCapture->CreateCaptureBuffer( &dscbd, &m_pDSBCapture, NULL ); DSBPOSITIONNOTIFY arrPosNotify[NUM_REC_NOTIFICATIONS + 1]; ZeroMemory( &arrPosNotify, sizeof( DSBPOSITIONNOTIFY ) * ( NUM_REC_NOTIFICATIONS + 1 ) ); m_hNotificationEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); hr = m_pDSBCapture->QueryInterface( IID_IDirectSoundNotify, (VOID**)&m_pDSNotify ); for ( int i = 0; i < NUM_REC_NOTIFICATIONS; i++ ) { arrPosNotify[i].dwOffset = (dwNotifySize * i) + dwNotifySize - 1; arrPosNotify[i].hEventNotify = m_hNotificationEvent; } hr = m_pDSNotify->SetNotificationPositions( NUM_REC_NOTIFICATIONS, arrPosNotify ); return S_OK; }
//----------------------------------------------------------------------------- // Name: InitDirectSound() // Desc: Initilizes DirectSound //----------------------------------------------------------------------------- HRESULT CCaptureSound::InitDirectSound( GUID* pDeviceGuid ) { HRESULT hr; m_dwCaptureBufferSize = 0; m_dwNotifySize = 0; // g_pWaveFile = NULL; // Initialize COM if( FAILED( hr = CoInitialize(NULL) ) ) { printf( "CoInitialize" ); return hr; } // Create IDirectSoundCapture using the preferred capture device //if( FAILED( hr = DirectSoundCaptureCreate( pDeviceGuid, &m_pDSCapture, NULL ) ) ) //DirectSoundCaptureCreate?? //in here ,use DSDEVID_DefaultVoiceCapture if( FAILED( hr = DirectSoundCaptureCreate(&DSDEVID_DefaultVoiceCapture, &m_pDSCapture, NULL ) ) ) //DSDEVID_DefaultCapture?? DSDEVID_DefaultVoiceCapture { //DirectSoundCreate8(NULL,&dsound_handle->g_pDsd,NULL) printf("DirectSoundCaptureCreate"); return hr; } //{WAVE_FORMAT_PCM, 1, 8000, 16000, 2, 16, 0} //Ĭ����Ƶ��ʽ // wFormatTag, nChannels, nSamplesPerSec, mAvgBytesPerSec, // nBlockAlign, wBitsPerSample, cbSize m_wfxInput.wFormatTag= WAVE_FORMAT_PCM; m_wfxInput.nChannels=1; m_wfxInput.nSamplesPerSec=8000; m_wfxInput.wBitsPerSample=16; m_wfxInput.nBlockAlign = m_wfxInput.nChannels * ( m_wfxInput.wBitsPerSample / 8 ); m_wfxInput.nAvgBytesPerSec = m_wfxInput.nBlockAlign * m_wfxInput.nSamplesPerSec; m_wfxInput.cbSize=0; return S_OK; }
HRESULT DSW_InitInputDevice( DSoundWrapper *dsw, LPGUID lpGUID ) { HRESULT hr = DirectSoundCaptureCreate( lpGUID, &dsw->dsw_pDirectSoundCapture, NULL ); if( hr != DS_OK ) return hr; return hr; }
PaError PaHost_OpenStream( internalPortAudioStream *past ) { HRESULT hr; PaError result = paNoError; PaHostSoundControl *pahsc; int numBytes, maxChannels; unsigned int minNumBuffers; internalPortAudioDevice *pad; DSoundWrapper *dsw; /* Allocate and initialize host data. */ pahsc = (PaHostSoundControl *) PaHost_AllocateFastMemory(sizeof(PaHostSoundControl)); /* MEM */ if( pahsc == NULL ) { result = paInsufficientMemory; goto error; } memset( pahsc, 0, sizeof(PaHostSoundControl) ); past->past_DeviceData = (void *) pahsc; pahsc->pahsc_TimerID = 0; dsw = &pahsc->pahsc_DSoundWrapper; DSW_Init( dsw ); /* Allocate native buffer. */ maxChannels = ( past->past_NumOutputChannels > past->past_NumInputChannels ) ? past->past_NumOutputChannels : past->past_NumInputChannels; pahsc->pahsc_BytesPerBuffer = past->past_FramesPerUserBuffer * maxChannels * sizeof(short); if( maxChannels > 0 ) { pahsc->pahsc_NativeBuffer = (short *) PaHost_AllocateFastMemory(pahsc->pahsc_BytesPerBuffer); /* MEM */ if( pahsc->pahsc_NativeBuffer == NULL ) { result = paInsufficientMemory; goto error; } } else { result = paInvalidChannelCount; goto error; } DBUG(("PaHost_OpenStream: pahsc_MinFramesPerHostBuffer = %d\n", pahsc->pahsc_MinFramesPerHostBuffer )); minNumBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate ); past->past_NumUserBuffers = ( minNumBuffers > past->past_NumUserBuffers ) ? minNumBuffers : past->past_NumUserBuffers; numBytes = pahsc->pahsc_BytesPerBuffer * past->past_NumUserBuffers; if( numBytes < DSBSIZE_MIN ) { result = paBufferTooSmall; goto error; } if( numBytes > DSBSIZE_MAX ) { result = paBufferTooBig; goto error; } pahsc->pahsc_FramesPerDSBuffer = past->past_FramesPerUserBuffer * past->past_NumUserBuffers; { int msecLatency = (int) ((pahsc->pahsc_FramesPerDSBuffer * 1000) / past->past_SampleRate); PRINT(("PortAudio on DirectSound - Latency = %d frames, %d msec\n", pahsc->pahsc_FramesPerDSBuffer, msecLatency )); } /* ------------------ OUTPUT */ if( (past->past_OutputDeviceID >= 0) && (past->past_NumOutputChannels > 0) ) { DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", past->past_OutputDeviceID)); pad = Pa_GetInternalDevice( past->past_OutputDeviceID ); hr = DirectSoundCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSound, NULL ); /* If this fails, then try each output device until we find one that works. */ if( hr != DS_OK ) { int i; ERR_RPT(("Creation of requested Audio Output device '%s' failed.\n", ((pad->pad_lpGUID == NULL) ? "Default" : pad->pad_Info.name) )); for( i=0; i<Pa_CountDevices(); i++ ) { pad = Pa_GetInternalDevice( i ); if( pad->pad_Info.maxOutputChannels >= past->past_NumOutputChannels ) { DBUG(("Try device '%s' instead.\n", pad->pad_Info.name )); hr = DirectSoundCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSound, NULL ); if( hr == DS_OK ) { ERR_RPT(("Using device '%s' instead.\n", pad->pad_Info.name )); break; } } } } if( hr != DS_OK ) { ERR_RPT(("PortAudio: DirectSoundCreate() failed!\n")); result = paHostError; sPaHostError = hr; goto error; } hr = DSW_InitOutputBuffer( dsw, (unsigned long) (past->past_SampleRate + 0.5), past->past_NumOutputChannels, numBytes ); DBUG(("DSW_InitOutputBuffer() returns %x\n", hr)); if( hr != DS_OK ) { result = paHostError; sPaHostError = hr; goto error; } past->past_FrameCount = pahsc->pahsc_DSoundWrapper.dsw_FramesWritten; } #if SUPPORT_AUDIO_CAPTURE /* ------------------ INPUT */ if( (past->past_InputDeviceID >= 0) && (past->past_NumInputChannels > 0) ) { pad = Pa_GetInternalDevice( past->past_InputDeviceID ); hr = DirectSoundCaptureCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSoundCapture, NULL ); /* If this fails, then try each input device until we find one that works. */ if( hr != DS_OK ) { int i; ERR_RPT(("Creation of requested Audio Capture device '%s' failed.\n", ((pad->pad_lpGUID == NULL) ? "Default" : pad->pad_Info.name) )); for( i=0; i<Pa_CountDevices(); i++ ) { pad = Pa_GetInternalDevice( i ); if( pad->pad_Info.maxInputChannels >= past->past_NumInputChannels ) { PRINT(("Try device '%s' instead.\n", pad->pad_Info.name )); hr = DirectSoundCaptureCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSoundCapture, NULL ); if( hr == DS_OK ) break; } } } if( hr != DS_OK ) { ERR_RPT(("PortAudio: DirectSoundCaptureCreate() failed!\n")); result = paHostError; sPaHostError = hr; goto error; } hr = DSW_InitInputBuffer( dsw, (unsigned long) (past->past_SampleRate + 0.5), past->past_NumInputChannels, numBytes ); DBUG(("DSW_InitInputBuffer() returns %x\n", hr)); if( hr != DS_OK ) { ERR_RPT(("PortAudio: DSW_InitInputBuffer() returns %x\n", hr)); result = paHostError; sPaHostError = hr; goto error; } } #endif /* SUPPORT_AUDIO_CAPTURE */ /* Calculate scalar used in CPULoad calculation. */ { LARGE_INTEGER frequency; if( QueryPerformanceFrequency( &frequency ) == 0 ) { pahsc->pahsc_InverseTicksPerUserBuffer = 0.0; } else { pahsc->pahsc_InverseTicksPerUserBuffer = past->past_SampleRate / ( (double)frequency.QuadPart * past->past_FramesPerUserBuffer ); DBUG(("pahsc_InverseTicksPerUserBuffer = %g\n", pahsc->pahsc_InverseTicksPerUserBuffer )); } } return result; error: PaHost_CloseStream( past ); return result; }
/************************************************************************************ ** Extract capabilities info from each device. */ static BOOL CALLBACK Pa_EnumProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrvName, LPVOID lpContext ) { HRESULT hr; LPDIRECTSOUND lpDirectSound; #if SUPPORT_AUDIO_CAPTURE LPDIRECTSOUNDCAPTURE lpDirectSoundCapture; #endif /* SUPPORT_AUDIO_CAPTURE */ int isInput = (int) lpContext; /* Passed from Pa_CountDevices() */ internalPortAudioDevice *pad; if( sDeviceIndex >= sNumDevices ) { sEnumerationError = paInternalError; return FALSE; } pad = &sDevices[sDeviceIndex]; /* Copy GUID to static array. Set pointer. */ if( lpGUID == NULL ) { pad->pad_lpGUID = NULL; } else { memcpy( &pad->pad_GUID, lpGUID, sizeof(GUID) ); pad->pad_lpGUID = &pad->pad_GUID; } pad->pad_Info.sampleRates = pad->pad_SampleRates; /* Point to array. */ /* Allocate room for descriptive name. */ if( lpszDesc != NULL ) { int len = strlen(lpszDesc); pad->pad_Info.name = (char *)malloc( len+1 ); if( pad->pad_Info.name == NULL ) { sEnumerationError = paInsufficientMemory; return FALSE; } memcpy( (void *) pad->pad_Info.name, lpszDesc, len+1 ); } #if SUPPORT_AUDIO_CAPTURE if( isInput ) { /********** Input ******************************/ DSCCAPS caps; if( lpGUID == NULL ) sDefaultInputDeviceID = sDeviceIndex; hr = DirectSoundCaptureCreate( lpGUID, &lpDirectSoundCapture, NULL ); if( hr != DS_OK ) { pad->pad_Info.maxInputChannels = 0; DBUG(("Cannot create Capture for %s. Result = 0x%x\n", lpszDesc, hr )); } else { /* Query device characteristics. */ caps.dwSize = sizeof(caps); IDirectSoundCapture_GetCaps( lpDirectSoundCapture, &caps ); /* printf("caps.dwFormats = 0x%x\n", caps.dwFormats ); */ pad->pad_Info.maxInputChannels = caps.dwChannels; /* Determine sample rates from flags. */ if( caps.dwChannels == 2 ) { int index = 0; if( caps.dwFormats & WAVE_FORMAT_1S16) pad->pad_SampleRates[index++] = 11025.0; if( caps.dwFormats & WAVE_FORMAT_2S16) pad->pad_SampleRates[index++] = 22050.0; if( caps.dwFormats & WAVE_FORMAT_4S16) pad->pad_SampleRates[index++] = 44100.0; pad->pad_Info.numSampleRates = index; } else if( caps.dwChannels == 1 ) { int index = 0; if( caps.dwFormats & WAVE_FORMAT_1M16) pad->pad_SampleRates[index++] = 11025.0; if( caps.dwFormats & WAVE_FORMAT_2M16) pad->pad_SampleRates[index++] = 22050.0; if( caps.dwFormats & WAVE_FORMAT_4M16) pad->pad_SampleRates[index++] = 44100.0; pad->pad_Info.numSampleRates = index; } else pad->pad_Info.numSampleRates = 0; IDirectSoundCapture_Release( lpDirectSoundCapture ); } } else #endif /* SUPPORT_AUDIO_CAPTURE */ { /********** Output ******************************/ DSCAPS caps; if( lpGUID == NULL ) sDefaultOutputDeviceID = sDeviceIndex; /* Create interfaces for each object. */ hr = DirectSoundCreate( lpGUID, &lpDirectSound, NULL ); if( hr != DS_OK ) { pad->pad_Info.maxOutputChannels = 0; DBUG(("Cannot create dsound for %s. Result = 0x%x\n", lpszDesc, hr )); } else { /* Query device characteristics. */ caps.dwSize = sizeof(caps); IDirectSound_GetCaps( lpDirectSound, &caps ); pad->pad_Info.maxOutputChannels = ( caps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1; /* Get sample rates. */ pad->pad_SampleRates[0] = (double) caps.dwMinSecondarySampleRate; pad->pad_SampleRates[1] = (double) caps.dwMaxSecondarySampleRate; if( caps.dwFlags & DSCAPS_CONTINUOUSRATE ) pad->pad_Info.numSampleRates = -1; else if( caps.dwMinSecondarySampleRate == caps.dwMaxSecondarySampleRate ) { if( caps.dwMinSecondarySampleRate == 0 ) { /* ** On my Thinkpad 380Z, DirectSoundV6 returns min-max=0 !! ** But it supports continuous sampling. ** So fake range of rates, and hope it really supports it. */ pad->pad_SampleRates[0] = 11025.0f; pad->pad_SampleRates[1] = 48000.0f; pad->pad_Info.numSampleRates = -1; /* continuous range */ DBUG(("PA - Reported rates both zero. Setting to fake values for device #%d\n", sDeviceIndex )); } else { pad->pad_Info.numSampleRates = 1; } } else if( (caps.dwMinSecondarySampleRate < 1000.0) && (caps.dwMaxSecondarySampleRate > 50000.0) ) { /* The EWS88MT drivers lie, lie, lie. The say they only support two rates, 100 & 100000. ** But we know that they really support a range of rates! ** So when we see a ridiculous set of rates, assume it is a range. */ pad->pad_Info.numSampleRates = -1; DBUG(("PA - Sample rate range used instead of two odd values for device #%d\n", sDeviceIndex )); } else pad->pad_Info.numSampleRates = 2; IDirectSound_Release( lpDirectSound ); } } pad->pad_Info.nativeSampleFormats = paInt16; sDeviceIndex++; return( TRUE ); }
static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName) { DSoundCaptureData *data = NULL; WAVEFORMATEXTENSIBLE InputType; DSCBUFFERDESC DSCBDescription; LPGUID guid = NULL; HRESULT hr, hrcom; ALuint samples; if(!CaptureDeviceList) { /* Initialize COM to prevent name truncation */ hrcom = CoInitialize(NULL); hr = DirectSoundCaptureEnumerateA(DSoundEnumCaptureDevices, NULL); if(FAILED(hr)) ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); if(SUCCEEDED(hrcom)) CoUninitialize(); } if(!deviceName && NumCaptureDevices > 0) { deviceName = CaptureDeviceList[0].name; guid = &CaptureDeviceList[0].guid; } else { ALuint i; for(i = 0;i < NumCaptureDevices;i++) { if(strcmp(deviceName, CaptureDeviceList[i].name) == 0) { guid = &CaptureDeviceList[i].guid; break; } } if(i == NumCaptureDevices) return ALC_INVALID_VALUE; } switch(device->FmtType) { case DevFmtByte: case DevFmtUShort: case DevFmtUInt: WARN("%s capture samples not supported\n", DevFmtTypeString(device->FmtType)); return ALC_INVALID_ENUM; case DevFmtUByte: case DevFmtShort: case DevFmtInt: case DevFmtFloat: break; } //Initialise requested device data = calloc(1, sizeof(DSoundCaptureData)); if(!data) return ALC_OUT_OF_MEMORY; hr = DS_OK; //DirectSoundCapture Init code if(SUCCEEDED(hr)) hr = DirectSoundCaptureCreate(guid, &data->DSC, NULL); if(SUCCEEDED(hr)) { memset(&InputType, 0, sizeof(InputType)); switch(device->FmtChans) { case DevFmtMono: InputType.dwChannelMask = SPEAKER_FRONT_CENTER; break; case DevFmtStereo: InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; break; case DevFmtQuad: InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break; case DevFmtX51: InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break; case DevFmtX51Side: InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; break; case DevFmtX61: InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_CENTER | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; break; case DevFmtX71: InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; break; } InputType.Format.wFormatTag = WAVE_FORMAT_PCM; InputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans); InputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; InputType.Format.nBlockAlign = InputType.Format.nChannels*InputType.Format.wBitsPerSample/8; InputType.Format.nSamplesPerSec = device->Frequency; InputType.Format.nAvgBytesPerSec = InputType.Format.nSamplesPerSec*InputType.Format.nBlockAlign; InputType.Format.cbSize = 0; if(InputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat) { InputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; InputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); InputType.Samples.wValidBitsPerSample = InputType.Format.wBitsPerSample; if(device->FmtType == DevFmtFloat) InputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; else InputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; } samples = device->UpdateSize * device->NumUpdates; samples = maxu(samples, 100 * device->Frequency / 1000); memset(&DSCBDescription, 0, sizeof(DSCBUFFERDESC)); DSCBDescription.dwSize = sizeof(DSCBUFFERDESC); DSCBDescription.dwFlags = 0; DSCBDescription.dwBufferBytes = samples * InputType.Format.nBlockAlign; DSCBDescription.lpwfxFormat = &InputType.Format; hr = IDirectSoundCapture_CreateCaptureBuffer(data->DSC, &DSCBDescription, &data->DSCbuffer, NULL); } if(SUCCEEDED(hr)) { data->Ring = CreateRingBuffer(InputType.Format.nBlockAlign, device->UpdateSize * device->NumUpdates); if(data->Ring == NULL) hr = DSERR_OUTOFMEMORY; } if(FAILED(hr)) { ERR("Device init failed: 0x%08lx\n", hr); DestroyRingBuffer(data->Ring); data->Ring = NULL; if(data->DSCbuffer != NULL) IDirectSoundCaptureBuffer_Release(data->DSCbuffer); data->DSCbuffer = NULL; if(data->DSC) IDirectSoundCapture_Release(data->DSC); data->DSC = NULL; free(data); return ALC_INVALID_VALUE; } data->BufferBytes = DSCBDescription.dwBufferBytes; SetDefaultWFXChannelOrder(device); device->DeviceName = strdup(deviceName); device->ExtraData = data; return ALC_NO_ERROR; }
// //////////////////////////////////////////////////////////////////////// BOOL NETinitAudioCapture(VOID) { HRESULT hr; WAVEFORMATEX wfx; NetPlay.bAllowCaptureRecord = FALSE; hr = DirectSoundCaptureCreate( NULL,&lpDirectSoundCapture, NULL); if(hr != DS_OK) { DBPRINTF(("NETPLAY:Failed to create capture interface.")); if(hr == DSERR_NOAGGREGATION) { DBPRINTF(("DSERR_NOAGGREGATION")); } if(hr == DSERR_OUTOFMEMORY) { DBPRINTF(("DSERR_OUTOFMEMORY")); } if(hr == DSERR_INVALIDPARAM) { DBPRINTF(("DSERR_INVALIDPARAM")); } return FALSE; } ZeroMemory(&captureBuff, sizeof(captureBuff)); lpDirectSoundCaptureBuffer = NULL; wfx.wFormatTag = WAVE_FORMAT_PCM; //set audio format wfx.nChannels = AUDIOCHANNELS; wfx.nSamplesPerSec = SAMPLERATE; wfx.nAvgBytesPerSec = SAMPLERATE * (BITSPERSAMPLE /8) * AUDIOCHANNELS ; wfx.nBlockAlign = (AUDIOCHANNELS * BITSPERSAMPLE) / 8 ; wfx.wBitsPerSample = BITSPERSAMPLE; wfx.cbSize = 0; captureBuff.dwSize = sizeof(DSCBUFFERDESC); captureBuff.dwFlags = DSCBCAPS_WAVEMAPPED; captureBuff.dwBufferBytes= SAMPLETIME * wfx.nAvgBytesPerSec; // SAMPLETIME second’s worth of audio captureBuff.lpwfxFormat = &wfx; hr = IDirectSoundCapture_CreateCaptureBuffer(lpDirectSoundCapture, &captureBuff, &lpDirectSoundCaptureBuffer, NULL); if(hr != DS_OK) { if( hr == DSERR_INVALIDPARAM) {DBPRINTF(("NETPLAY:no capturebuffer,inv param")); } if( hr == DSERR_BADFORMAT) {DBPRINTF(("NETPLAY:no capturebuffer,badformat")); } if( hr == DSERR_GENERIC) {DBPRINTF(("NETPLAY:no capturebuffer,generic")); } if( hr == DSERR_NODRIVER) {DBPRINTF(("NETPLAY:no capturebuffer,nodriver")); } if( hr == DSERR_OUTOFMEMORY) {DBPRINTF(("NETPLAY:no capturebuffer,memory")); } if( hr == DSERR_UNINITIALIZED) {DBPRINTF(("NETPLAY:no capturebuffer,uninit")); } return FALSE; } NetPlay.bAllowCaptureRecord = TRUE; // allowCapture = TRUE; return(TRUE); }
/* * Initialize DirectSound recorder device */ static pj_status_t init_capture_stream( struct dsound_stream *ds_strm, int dev_id, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned buffer_count) { HRESULT hr; PCMWAVEFORMAT pcmwf; DSCBUFFERDESC dscbdesc; DSBPOSITIONNOTIFY dsPosNotify[MAX_PACKET_BUFFER_COUNT]; unsigned bytes_per_frame; unsigned i; PJ_ASSERT_RETURN(buffer_count <= MAX_PACKET_BUFFER_COUNT, PJ_EINVAL); /* Check device id */ if (dev_id == -1) dev_id = 0; PJ_ASSERT_RETURN(dev_id>=0 && dev_id < (int)dev_count, PJ_EINVAL); /* * Creating recorder device. */ hr = DirectSoundCaptureCreate(dev_info[dev_id].lpGuid, &ds_strm->ds.capture.lpDs, NULL); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); /* Init wave format to initialize buffer */ init_waveformatex( &pcmwf, clock_rate, channel_count); bytes_per_frame = samples_per_frame * BYTES_PER_SAMPLE; /* * Setup capture buffer using sound buffer structure that was passed * to play buffer creation earlier. */ pj_bzero(&dscbdesc, sizeof(DSCBUFFERDESC)); dscbdesc.dwSize = sizeof(DSCBUFFERDESC); dscbdesc.dwFlags = DSCBCAPS_WAVEMAPPED ; dscbdesc.dwBufferBytes = buffer_count * bytes_per_frame; dscbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf; hr = IDirectSoundCapture_CreateCaptureBuffer( ds_strm->ds.capture.lpDs, &dscbdesc, &ds_strm->ds.capture.lpDsBuffer, NULL); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); /* * Create event for play notification. */ ds_strm->hEvent = CreateEvent( NULL, FALSE, FALSE, NULL); if (ds_strm->hEvent == NULL) return pj_get_os_error(); /* * Setup notifications for recording. */ hr = IDirectSoundCaptureBuffer_QueryInterface( ds_strm->ds.capture.lpDsBuffer, &IID_IDirectSoundNotify, (LPVOID *)&ds_strm->lpDsNotify); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); for (i=0; i<buffer_count; ++i) { dsPosNotify[i].dwOffset = i * bytes_per_frame; dsPosNotify[i].hEventNotify = ds_strm->hEvent; } hr = IDirectSoundNotify_SetNotificationPositions( ds_strm->lpDsNotify, buffer_count, dsPosNotify); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); hr = IDirectSoundCaptureBuffer_GetCurrentPosition( ds_strm->ds.capture.lpDsBuffer, NULL, &ds_strm->dwBytePos ); if (FAILED(hr)) return PJ_RETURN_OS_ERROR(hr); ds_strm->timestamp.u64 = 0; ds_strm->dwDsBufferSize = buffer_count * bytes_per_frame; /* * Capture latency must always be on a frame boundry, * so compute it based off the calculated buffer_count. */ ds_strm->latency = buffer_count * samples_per_frame * 1000 / clock_rate / channel_count; /* Done setting up recorder device. */ PJ_LOG(5,(THIS_FILE, " DirectSound capture \"%s\" initialized (clock_rate=%d, " "channel_count=%d, samples_per_frame=%d (%dms))", dev_info[dev_id].info.name, clock_rate, channel_count, samples_per_frame, samples_per_frame * 1000 / clock_rate)); return PJ_SUCCESS; }
/* nInterval is in SECONDS. The buffer we create is 3 times the interval, so we make three notifications that will be placed at every interval. pProc will be called at approximately the interval specified. */ HRESULT WaveCapture::Initialize(int nDevice, WAVEFORMATEX* pFormat, WAVECAPTUREPROC pProc, PVOID pUser, int nInterval) { DSCCAPS dsc; DSCBUFFERDESC1 dscbDesc; HRESULT hr; DSBPOSITIONNOTIFY NotifyPositions[3]; IDirectSoundNotify* pdsn; this->Uninitialize(); this->pProc = pProc; this->pUser = pUser; this->nInterval = nInterval; // Validation. if(pFormat->wFormatTag != WAVE_FORMAT_PCM) { return E_FAIL; } // Copy the wave format for our own purposes. memcpy(&this->Format, pFormat, sizeof(WAVEFORMATEX)); m_iDevice = nDevice; memset(&m_Device, 0, sizeof(GUID)); DirectSoundCaptureEnumerate(WaveCapture::DSEnumCallback, this); // Create DirectSoundCapture object. if(FAILED(hr = DirectSoundCaptureCreate(&m_Device, &this->pdsc, NULL))) { return E_FAIL; } /* Here is where we should check the capabilities of the sound card against the format that was passed in. */ dsc.dwSize = sizeof(DSCCAPS); if(FAILED(hr = this->pdsc->GetCaps(&dsc))) { SAFE_RELEASE(this->pdsc); return E_FAIL; } /* Create the capture buffer. */ dscbDesc.dwSize = sizeof(dscbDesc); dscbDesc.dwFlags = DSCBCAPS_WAVEMAPPED; dscbDesc.dwBufferBytes = (pFormat->nAvgBytesPerSec * nInterval) * 3; dscbDesc.dwReserved = 0; dscbDesc.lpwfxFormat = &this->Format; if(FAILED(hr = this->pdsc->CreateCaptureBuffer((DSCBUFFERDESC*)&dscbDesc, &this->pdsb, NULL))) { SAFE_RELEASE(this->pdsc); return E_FAIL; } /* Create the notifications */ this->hEvents[0] = CreateEvent(NULL, FALSE, FALSE, NULL); this->hEvents[1] = CreateEvent(NULL, FALSE, FALSE, NULL); this->hEvents[2] = CreateEvent(NULL, FALSE, FALSE, NULL); this->hEvents[3] = CreateEvent(NULL, FALSE, FALSE, NULL); NotifyPositions[0].dwOffset = 0; NotifyPositions[0].hEventNotify = this->hEvents[0]; NotifyPositions[1].dwOffset = (this->Format.nAvgBytesPerSec * nInterval); NotifyPositions[1].hEventNotify = this->hEvents[1]; NotifyPositions[2].dwOffset = (this->Format.nAvgBytesPerSec * nInterval) * 2; NotifyPositions[2].hEventNotify = this->hEvents[2]; if(FAILED(hr = this->pdsb->QueryInterface(IID_IDirectSoundNotify, (PVOID*)&pdsn))) { SAFE_RELEASE(this->pdsb); SAFE_RELEASE(this->pdsc); return E_FAIL; } if(FAILED(hr = pdsn->SetNotificationPositions(3, NotifyPositions))) { SAFE_RELEASE(pdsn); SAFE_RELEASE(this->pdsb); SAFE_RELEASE(this->pdsc); return E_FAIL; } SAFE_RELEASE(pdsn); /* Create our own buffer so when we pass data to pProc, the data is ALWAYS contiguous. */ this->nBufferSize = (pFormat->nAvgBytesPerSec * nInterval) * 3; this->pBuffer = (PBYTE)malloc(this->nBufferSize); /* Initialize our own information. */ this->dwLastPosition = 0; this->nPassesLeft = 1; /* Now create our recording thread so life can continue. */ UINT dwThreadId; this->hThread = (HANDLE)_beginthreadex( 0, 0, WaveCapture::RecordingThread, this, 0, &dwThreadId); return S_OK; }