📄 winsndds.cpp
字号:
WinSndDs *d=(WinSndDs*)data; uint64_t curtime=((uint64_t)d->bytes_read*1000)/(uint64_t)d->wfx.nAvgBytesPerSec; /* ms_debug("winsndds_get_cur_time: bytes_read=%u return %lu\n",d->bytes_read,(unsigned long)curtime); */ return curtime;}static void winsndds_init(MSFilter *f){ WinSndDs *d=(WinSndDs *)ms_new0(WinSndDs,1); d->wfx.wFormatTag = WAVE_FORMAT_PCM; d->wfx.cbSize = 0; d->wfx.nAvgBytesPerSec = 16000; d->wfx.nBlockAlign = 2; d->wfx.nChannels = 1; d->wfx.nSamplesPerSec = 8000; d->wfx.wBitsPerSample = 16; qinit(&d->rq); ms_mutex_init(&d->mutex,NULL); f->data=d; d->stat_input=0; d->stat_output=0; d->stat_notplayed=0; d->stat_minimumbuffer=WINSNDDS_MINIMUMBUFFER; d->framesPerDSBuffer = 4096*3; //320 * (8000 / 1000); d->thread = NULL; ms_mutex_init(&d->thread_lock,NULL); ms_cond_init(&d->thread_cond,NULL); d->thread_running = FALSE; ms_bufferizer_init(&d->output_buff);}static void winsndds_uninit(MSFilter *f){ WinSndDs *d=(WinSndDs*)f->data; d->thread = NULL; d->thread_running = FALSE; ms_cond_destroy(&d->thread_cond); ms_mutex_destroy(&d->thread_lock); ms_bufferizer_uninit(&d->output_buff); flushq(&d->rq,0); ms_mutex_destroy(&d->mutex); ms_free(f->data);}static void winsndds_read_preprocess(MSFilter *f){ WinSndDs *d=(WinSndDs*)f->data; DSCBUFFERDESC captureDesc; HRESULT hr; d->stat_input=0; d->stat_output=0; d->stat_notplayed=0; d->stat_minimumbuffer=WINSNDDS_MINIMUMBUFFER; winsndds_apply_settings(d); ms_DirectSoundCaptureCreate( &d->in_guid, &d->lpDirectSoundCapture, NULL ); d->inputSize = d->framesPerDSBuffer * 1 * sizeof(short); ZeroMemory(&captureDesc, sizeof(DSCBUFFERDESC)); captureDesc.dwSize = sizeof(DSCBUFFERDESC); captureDesc.dwFlags = 0; captureDesc.dwBufferBytes = d->framesPerDSBuffer * 1 * sizeof(short); //bytesPerBuffer; captureDesc.lpwfxFormat = &d->wfx; // Create the capture buffer if ((hr = IDirectSoundCapture_CreateCaptureBuffer( d->lpDirectSoundCapture, &captureDesc, &d->lpDirectSoundInputBuffer, NULL)) != DS_OK) { return; /* hr; */ } d->readOffset = 0; // reset last read position to start of buffer hr = IDirectSoundCaptureBuffer_Start( d->lpDirectSoundInputBuffer, DSCBSTART_LOOPING ); ms_ticker_set_time_func(f->ticker,winsndds_get_cur_time,d); d->thread_running=TRUE; ms_thread_create(&d->thread,NULL,winsndds_read_thread,d); ms_mutex_lock(&d->thread_lock); ms_cond_wait(&d->thread_cond,&d->thread_lock); ms_mutex_unlock(&d->thread_lock); return; /* DS_OK; */}static void winsndds_read_postprocess(MSFilter *f){ WinSndDs *d=(WinSndDs*)f->data; ms_mutex_lock(&d->thread_lock); d->thread_running=FALSE; ms_cond_wait(&d->thread_cond,&d->thread_lock); ms_mutex_unlock(&d->thread_lock); ms_thread_join(d->thread,NULL); ms_ticker_set_time_func(f->ticker,NULL,NULL); if( d->lpDirectSoundInputBuffer ) { IDirectSoundCaptureBuffer_Stop( d->lpDirectSoundInputBuffer ); IDirectSoundCaptureBuffer_Release( d->lpDirectSoundInputBuffer ); d->lpDirectSoundInputBuffer = NULL; } if( d->lpDirectSoundCapture ) { IDirectSoundCapture_Release( d->lpDirectSoundCapture ); d->lpDirectSoundCapture = NULL; } ms_message("Shutting down sound device (playing: %i) (input-output: %i) (notplayed: %i)", d->nbufs_playing, d->stat_input - d->stat_output, d->stat_notplayed); flushq(&d->rq,0);}static void winsndds_read_process(MSFilter *f){ WinSndDs *d=(WinSndDs*)f->data; mblk_t *m; ms_mutex_lock(&d->mutex); while((m=getq(&d->rq))!=NULL){ ms_queue_put(f->outputs[0],m); } ms_mutex_unlock(&d->mutex);}static void winsndds_write_preprocess(MSFilter *f){ WinSndDs *d=(WinSndDs*)f->data; DWORD dwDataLen; DWORD playCursor; HWND hWnd; HRESULT hr; LPDIRECTSOUNDBUFFER pPrimaryBuffer; DSBUFFERDESC primaryDesc; DSBUFFERDESC secondaryDesc; unsigned char* pDSBuffData; d->stat_input=0; d->stat_output=0; d->stat_notplayed=0; d->stat_minimumbuffer=WINSNDDS_MINIMUMBUFFER; winsndds_apply_settings(d); ms_DirectSoundCreate( &d->out_guid, &d->lpDirectSound, NULL ); hWnd = GetDesktopWindow(); if ((hr = IDirectSound_SetCooperativeLevel( d->lpDirectSound, hWnd, DSSCL_EXCLUSIVE)) != DS_OK) { return ; } ZeroMemory(&primaryDesc, sizeof(DSBUFFERDESC)); primaryDesc.dwSize = sizeof(DSBUFFERDESC); primaryDesc.dwFlags = DSBCAPS_PRIMARYBUFFER; // all panning, mixing, etc done by synth primaryDesc.dwBufferBytes = 0; primaryDesc.lpwfxFormat = NULL; // Create the buffer if ((hr = IDirectSound_CreateSoundBuffer( d->lpDirectSound, &primaryDesc, &pPrimaryBuffer, NULL)) != DS_OK) { return ;//hr; } if ((hr = IDirectSoundBuffer_SetFormat( pPrimaryBuffer, &d->wfx)) != DS_OK) { return ;//hr; } // Setup the secondary buffer description ZeroMemory(&secondaryDesc, sizeof(DSBUFFERDESC)); secondaryDesc.dwSize = sizeof(DSBUFFERDESC); secondaryDesc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; secondaryDesc.dwBufferBytes = d->framesPerDSBuffer * 1 * sizeof(short); //bytesPerBuffer; secondaryDesc.lpwfxFormat = &d->wfx; // Create the secondary buffer if ((hr = IDirectSound_CreateSoundBuffer( d->lpDirectSound, &secondaryDesc, &d->lpDirectSoundOutputBuffer, NULL)) != DS_OK) { return ;//hr; } // Lock the DS buffer if ((hr = IDirectSoundBuffer_Lock( d->lpDirectSoundOutputBuffer, 0, d->framesPerDSBuffer * 1 * sizeof(short), (LPVOID*)&pDSBuffData, &dwDataLen, NULL, 0, 0)) != DS_OK) { return ;//hr; } // Zero the DS buffer ZeroMemory(pDSBuffData, dwDataLen); // Unlock the DS buffer if ((hr = IDirectSoundBuffer_Unlock( d->lpDirectSoundOutputBuffer, pDSBuffData, dwDataLen, NULL, 0)) != DS_OK) { return ;//hr; } // Let DSound set the starting write position because if we set it to zero, it looks like the // buffer is full to begin with. This causes a long pause before sound starts when using large buffers. hr = IDirectSoundBuffer_GetCurrentPosition( d->lpDirectSoundOutputBuffer, &playCursor, &d->outputBufferWriteOffsetBytes ); if( hr != DS_OK ) { return ;//hr; } hr = IDirectSoundBuffer_SetCurrentPosition( d->lpDirectSoundOutputBuffer, 0 ); if( hr != DS_OK ) { return ;//hr; } hr = IDirectSoundBuffer_Play( d->lpDirectSoundOutputBuffer, 0, 0, DSBPLAY_LOOPING); if( hr != DS_OK ) { return ;//hr; } return ;//hr;}static void winsndds_write_postprocess(MSFilter *f){ WinSndDs *d=(WinSndDs*)f->data; if( d->lpDirectSoundOutputBuffer ) { IDirectSoundBuffer_Stop( d->lpDirectSoundOutputBuffer ); IDirectSoundBuffer_Release( d->lpDirectSoundOutputBuffer ); d->lpDirectSoundOutputBuffer = NULL; } if( d->lpDirectSound ) { IDirectSound_Release( d->lpDirectSound ); d->lpDirectSound = NULL; } ms_message("Shutting down sound device (playing: %i) (input-output: %i) (notplayed: %i)", d->nbufs_playing, d->stat_input - d->stat_output, d->stat_notplayed);}static void winsndds_write_process(MSFilter *f){ WinSndDs *d=(WinSndDs*)f->data; int discarded=0; static int fillme=0; if (d->lpDirectSound==NULL) { ms_queue_flush(f->inputs[0]); return; } ms_bufferizer_put_from_queue(&d->output_buff,f->inputs[0]); if (fillme==0) { if (ms_bufferizer_get_avail(&d->output_buff)>=4096*3) { fillme=1; return; } return; } int msize = 4096;// 1280; while (ms_bufferizer_get_avail(&d->output_buff)>=msize) { LPBYTE lpOutBuf1 = NULL; LPBYTE lpOutBuf2 = NULL; DWORD dwOutSize1 = 0; DWORD dwOutSize2 = 0; HRESULT hr; char input[4096]; hr = IDirectSoundBuffer_Lock ( d->lpDirectSoundOutputBuffer, d->outputBufferWriteOffsetBytes, msize, //bytesToXfer, (void **) &lpOutBuf1, &dwOutSize1, (void **) &lpOutBuf2, &dwOutSize2, DSBLOCK_FROMWRITECURSOR); if (hr != DS_OK) { ms_error("DirectSound IDirectSoundBuffer_Lock failed, hresult = 0x%x\n", hr); continue; } if (dwOutSize1==0) { ms_error("no free room to play sample\n"); } else if (dwOutSize1+dwOutSize2!=msize) { ms_bufferizer_read(&d->output_buff,(uint8_t*)input,dwOutSize1+dwOutSize2); memcpy(lpOutBuf1, input, dwOutSize1); memcpy(lpOutBuf2, input+dwOutSize1, dwOutSize2); } else if (dwOutSize1>=msize) { ms_bufferizer_read(&d->output_buff,(uint8_t*)input,msize); memcpy(lpOutBuf1, input, msize); } else { ms_bufferizer_read(&d->output_buff,(uint8_t*)input,msize); memcpy(lpOutBuf1, input, dwOutSize1); memcpy(lpOutBuf2, input+dwOutSize1, dwOutSize2); } IDirectSoundBuffer_Unlock( d->lpDirectSoundOutputBuffer, lpOutBuf1, dwOutSize1, lpOutBuf2, dwOutSize2); if (dwOutSize1==0) break; if (dwOutSize1+dwOutSize2!=msize) break; } if (discarded>0) ms_warning("Extra data for sound card removed (%i buf), (playing: %i) (input-output: %i)", discarded, d->nbufs_playing, d->stat_input - d->stat_output);}static int set_rate(MSFilter *f, void *arg){ WinSndDs *d=(WinSndDs*)f->data; d->wfx.nSamplesPerSec=*((int*)arg); return 0;}static int set_nchannels(MSFilter *f, void *arg){ WinSndDs *d=(WinSndDs*)f->data; d->wfx.nChannels=*((int*)arg); return 0;}static int winsndds_get_stat_input(MSFilter *f, void *arg){ WinSndDs *d=(WinSndDs*)f->data; return d->stat_input;}static int winsndds_get_stat_ouptut(MSFilter *f, void *arg){ WinSndDs *d=(WinSndDs*)f->data; return d->stat_output;}static int winsndds_get_stat_discarded(MSFilter *f, void *arg){ WinSndDs *d=(WinSndDs*)f->data; return d->stat_notplayed;}static MSFilterMethod winsndds_methods[]={ { MS_FILTER_SET_SAMPLE_RATE , set_rate }, { MS_FILTER_SET_NCHANNELS , set_nchannels }, { MS_FILTER_GET_STAT_INPUT, winsndds_get_stat_input }, { MS_FILTER_GET_STAT_OUTPUT, winsndds_get_stat_ouptut }, { MS_FILTER_GET_STAT_DISCARDED, winsndds_get_stat_discarded }, { 0 , NULL }};MSFilterDesc winsndds_read_desc={ MS_WINSNDDS_READ_ID, "MSWinSndRead", "Sound capture filter for Windows Sound drivers", MS_FILTER_OTHER, NULL, 0, 1, winsndds_init, winsndds_read_preprocess, winsndds_read_process, winsndds_read_postprocess, winsndds_uninit, winsndds_methods};MSFilterDesc winsndds_write_desc={ MS_WINSNDDS_WRITE_ID, "MSWinSndWrite", "Sound playback filter for Windows Sound drivers", MS_FILTER_OTHER, NULL, 1, 0, winsndds_init, winsndds_write_preprocess, winsndds_write_process, winsndds_write_postprocess, winsndds_uninit, winsndds_methods};MSFilter *ms_winsndds_read_new(MSSndCard *card){ MSFilter *f=ms_filter_new_from_desc(&winsndds_read_desc); WinSndDsCard *wc=(WinSndDsCard*)card->data; WinSndDs *d=(WinSndDs*)f->data; d->dev_id=wc->in_devid; memcpy(&d->in_guid, &wc->in_guid, sizeof(GUID)); memcpy(&d->out_guid, &wc->out_guid, sizeof(GUID)); return f;}MSFilter *ms_winsndds_write_new(MSSndCard *card){ MSFilter *f=ms_filter_new_from_desc(&winsndds_write_desc); WinSndDsCard *wc=(WinSndDsCard*)card->data; WinSndDs *d=(WinSndDs*)f->data; d->dev_id=wc->out_devid; memcpy(&d->in_guid, &wc->in_guid, sizeof(GUID)); memcpy(&d->out_guid, &wc->out_guid, sizeof(GUID)); return f;}MS_FILTER_DESC_EXPORT(winsndds_read_desc)MS_FILTER_DESC_EXPORT(winsndds_write_desc)#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -