📄 winsnd2.c
字号:
if (mr != MMSYSERR_NOERROR){ ms_error("waveInReset() error"); return ; } for(i=0;i<WINSND_NBUFS;++i){ WAVEHDR *hdr=&d->hdrs_read[i]; if (hdr->dwFlags & WHDR_PREPARED) { mr = waveInUnprepareHeader(d->indev,hdr,sizeof (*hdr)); if (mr != MMSYSERR_NOERROR){ ms_error("waveInUnPrepareHeader() error"); } } } mr = waveInClose(d->indev); if (mr != MMSYSERR_NOERROR){ ms_error("waveInClose() error"); return ; } 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 winsnd_read_process(MSFilter *f){ WinSnd *d=(WinSnd*)f->data; mblk_t *m; int i; ms_mutex_lock(&d->mutex); while((m=getq(&d->rq))!=NULL){ ms_queue_put(f->outputs[0],m); } ms_mutex_unlock(&d->mutex); for(i=0;i<WINSND_NBUFS;++i){ WAVEHDR *hdr=&d->hdrs_read[i]; if (hdr->dwUser==0) { MMRESULT mr; mr=waveInUnprepareHeader(d->indev,hdr,sizeof(*hdr)); if (mr!=MMSYSERR_NOERROR) ms_warning("winsnd_read_process: Fail to unprepare header!"); add_input_buffer(d,hdr,hdr->dwBufferLength); } }}static void CALLBACKwrite_callback(HWAVEOUT outdev, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2){ WAVEHDR *hdr=(WAVEHDR *) dwParam1; WinSnd *d=(WinSnd*)dwInstance; switch (uMsg){ case WOM_OPEN: break; case WOM_CLOSE: case WOM_DONE: if (hdr){ d->nbufs_playing--; } if (d->stat_output==0) { d->stat_input=1; /* reset */ d->stat_notplayed=0; } d->stat_output++; break; }}static void winsnd_write_preprocess(MSFilter *f){ WinSnd *d=(WinSnd*)f->data; MMRESULT mr; DWORD dwFlag; int i; d->stat_input=0; d->stat_output=0; d->stat_notplayed=0; d->stat_minimumbuffer=WINSND_MINIMUMBUFFER; winsnd_apply_settings(d); /* Init Microphone device */ dwFlag = CALLBACK_FUNCTION; if (d->dev_id != WAVE_MAPPER) dwFlag = WAVE_MAPPED | CALLBACK_FUNCTION; mr = waveOutOpen (&d->outdev, d->dev_id, &d->wfx, (DWORD) write_callback, (DWORD)d, dwFlag); if (mr != MMSYSERR_NOERROR) { ms_error("Failed to open windows sound device %i. (waveOutOpen:0x%i)",d->dev_id, mr); mr = waveOutOpen (&d->outdev, WAVE_MAPPER, &d->wfx, (DWORD) write_callback, (DWORD)d, CALLBACK_FUNCTION); if (mr != MMSYSERR_NOERROR) { ms_error("Failed to open windows sound device %i. (waveOutOpen:0x%i)",d->dev_id, mr); d->outdev=NULL; return ; } } for(i=0;i<WINSND_OUT_NBUFS;++i){ WAVEHDR *hdr=&d->hdrs_write[i]; hdr->dwFlags=0; hdr->dwUser=0; }}static void winsnd_write_postprocess(MSFilter *f){ WinSnd *d=(WinSnd*)f->data; MMRESULT mr; int i; if (d->outdev==NULL) return; mr=waveOutReset(d->outdev); if (mr != MMSYSERR_NOERROR){ ms_error("waveOutReset() error"); return ; } for(i=0;i<WINSND_OUT_NBUFS;++i){ WAVEHDR *hdr=&d->hdrs_write[i]; mblk_t *old; if (hdr->dwFlags & WHDR_DONE){ mr=waveOutUnprepareHeader(d->outdev,hdr,sizeof(*hdr)); if (mr != MMSYSERR_NOERROR){ ms_error("waveOutUnprepareHeader error"); } old=(mblk_t*)hdr->dwUser; if (old) freemsg(old); hdr->dwUser=0; } } mr=waveOutClose(d->outdev); if (mr != MMSYSERR_NOERROR){ ms_error("waveOutClose() error"); return ; } ms_message("Shutting down sound device (playing: %i) (d->write_rq.q_mcount=%i) (input-output: %i) (notplayed: %i)", d->nbufs_playing, d->write_rq.q_mcount, d->stat_input - d->stat_output, d->stat_notplayed); flushq(&d->write_rq,0); d->ready=0; d->workaround=0;#ifndef DISABLE_SPEEX if (d->pst!=NULL) speex_preprocess_state_destroy(d->pst); d->pst=NULL; d->pst_frame_size=0;#endif}static void winsnd_write_process(MSFilter *f){ WinSnd *d=(WinSnd*)f->data; mblk_t *m,*old; MMRESULT mr; int i; int discarded=0; int possible_size=0; if (d->outdev==NULL) { ms_queue_flush(f->inputs[0]); return; } while((m=ms_queue_get(f->inputs[0]))!=NULL){ possible_size = msgdsize(m);#ifndef DISABLE_SPEEX if (d->pst_frame_size==0) { d->pst_frame_size=possible_size; d->pst = speex_preprocess_state_init(d->pst_frame_size/2, d->wfx.nSamplesPerSec); if (d->pst!=NULL) { float f; i=1; speex_preprocess_ctl(d->pst, SPEEX_PREPROCESS_SET_VAD, &i); i=0; speex_preprocess_ctl(d->pst, SPEEX_PREPROCESS_SET_DENOISE, &i); i=0; speex_preprocess_ctl(d->pst, SPEEX_PREPROCESS_SET_AGC, &i); f=8000; speex_preprocess_ctl(d->pst, SPEEX_PREPROCESS_SET_AGC_LEVEL, &f); i=0; speex_preprocess_ctl(d->pst, SPEEX_PREPROCESS_SET_DEREVERB, &i); } }#endif putq(&d->write_rq,m); }#ifdef AMD_HACK /* too many sound card are crappy on windows... */ d->stat_minimumbuffer=15; if (d->wfx.nSamplesPerSec>=32000) /* better results for high rates */ d->stat_minimumbuffer=8;#endif if (d->wfx.nSamplesPerSec>=32000) /* better results for high rates */ { if (d->nbufs_playing+d->write_rq.q_mcount<4) { d->ready=0; } } else { if (d->nbufs_playing+d->write_rq.q_mcount<7) { d->ready=0; } }#if defined(WCE_OPTICON_WORKAROUND) if (d->workaround==0) { d->workaround=1; Sleep(WCE_OPTICON_WORKAROUND); }#endif while((m=peekq(&d->write_rq))!=NULL){#ifndef DISABLE_SPEEX int vad=1; if (d->pst!=NULL && msgdsize(m)==d->pst_frame_size && d->pst_frame_size<=4096) { char tmp[4096]; memcpy(tmp, m->b_rptr, msgdsize(m)); vad = speex_preprocess(d->pst, (short*)tmp, NULL); if (d->ready==0) { if (vad==0) { int missing; missing = 10 - d->write_rq.q_mcount - d->nbufs_playing; if (d->wfx.nSamplesPerSec>=32000) /* better results for high rates */ missing = 6 - d->write_rq.q_mcount - d->nbufs_playing; ms_message("WINSND trouble: inserting %i silence", missing); while(missing>0) { old=dupb(m); putq(&d->write_rq,old); missing--; } } d->ready=1; } }#else if (d->ready==0) { int missing; missing = 10 - d->write_rq.q_mcount - d->nbufs_playing; if (d->wfx.nSamplesPerSec>=32000) /* better results for high rates */ missing = 6 - d->write_rq.q_mcount - d->nbufs_playing; ms_message("WINSND trouble: inserting %i silence", missing); while(missing>0) { old=dupb(m); putq(&d->write_rq,old); missing--; } d->ready=1; }#endif for(i=0;i<d->stat_minimumbuffer;++i){ WAVEHDR *hdr=&d->hdrs_write[i]; if (hdr->dwFlags & WHDR_DONE){ old=(mblk_t*)hdr->dwUser; mr=waveOutUnprepareHeader(d->outdev,hdr,sizeof(*hdr)); if (mr != MMSYSERR_NOERROR){ ms_error("waveOutUnprepareHeader error"); } freemsg(old); hdr->dwUser=0; } if (hdr->dwUser==0){ hdr->lpData=(LPSTR)m->b_rptr; hdr->dwBufferLength=msgdsize(m); hdr->dwFlags = 0; hdr->dwUser = (DWORD)m; mr = waveOutPrepareHeader(d->outdev,hdr,sizeof(*hdr)); if (mr != MMSYSERR_NOERROR){ ms_error("waveOutPrepareHeader() error"); getq(&d->write_rq); freemsg(m); discarded++; d->stat_notplayed++; break; } mr=waveOutWrite(d->outdev,hdr,sizeof(*hdr)); if (mr != MMSYSERR_NOERROR){ ms_error("waveOutWrite() error"); getq(&d->write_rq); freemsg(m); discarded++; d->stat_notplayed++; break; }else { getq(&d->write_rq); d->nbufs_playing++; /* ms_debug("waveOutWrite() done"); */ } break; } } if (i==d->stat_minimumbuffer){ //ms_error("winsnd_write_process: All buffers are busy.");#ifndef DISABLE_SPEEX if (d->pst==NULL) { /* initial behavior (detection in process?) */ getq(&d->write_rq); freemsg(m); discarded++; d->stat_notplayed++; } else { if (vad==0) { getq(&d->write_rq); freemsg(m); ms_message("WINSND trouble: silence removed"); discarded++; d->stat_notplayed++; } }#else getq(&d->write_rq); freemsg(m); discarded++; d->stat_notplayed++;#endif break; } }}static int set_rate(MSFilter *f, void *arg){ WinSnd *d=(WinSnd*)f->data; d->wfx.nSamplesPerSec=*((int*)arg); return 0;}static int set_nchannels(MSFilter *f, void *arg){ WinSnd *d=(WinSnd*)f->data; d->wfx.nChannels=*((int*)arg); return 0;}static int winsnd_get_stat_input(MSFilter *f, void *arg){ WinSnd *d=(WinSnd*)f->data; return d->stat_input;}static int winsnd_get_stat_ouptut(MSFilter *f, void *arg){ WinSnd *d=(WinSnd*)f->data; return d->stat_output;}static int winsnd_get_stat_discarded(MSFilter *f, void *arg){ WinSnd *d=(WinSnd*)f->data; return d->stat_notplayed;}static MSFilterMethod winsnd_methods[]={ { MS_FILTER_SET_SAMPLE_RATE , set_rate }, { MS_FILTER_SET_NCHANNELS , set_nchannels }, { MS_FILTER_GET_STAT_INPUT, winsnd_get_stat_input }, { MS_FILTER_GET_STAT_OUTPUT, winsnd_get_stat_ouptut }, { MS_FILTER_GET_STAT_DISCARDED, winsnd_get_stat_discarded }, { 0 , NULL }};MSFilterDesc winsnd_read_desc={ MS_WINSND_READ_ID, "MSWinSndRead", "Sound capture filter for Windows Sound drivers", MS_FILTER_OTHER, NULL, 0, 1, winsnd_init, winsnd_read_preprocess, winsnd_read_process, winsnd_read_postprocess, winsnd_uninit, winsnd_methods};MSFilterDesc winsnd_write_desc={ MS_WINSND_WRITE_ID, "MSWinSndWrite", "Sound playback filter for Windows Sound drivers", MS_FILTER_OTHER, NULL, 1, 0, winsnd_init, winsnd_write_preprocess, winsnd_write_process, winsnd_write_postprocess, winsnd_uninit, winsnd_methods};MSFilter *ms_winsnd_read_new(MSSndCard *card){ MSFilter *f=ms_filter_new_from_desc(&winsnd_read_desc); WinSndCard *wc=(WinSndCard*)card->data; WinSnd *d=(WinSnd*)f->data; d->dev_id=wc->in_devid; return f;}MSFilter *ms_winsnd_write_new(MSSndCard *card){ MSFilter *f=ms_filter_new_from_desc(&winsnd_write_desc); WinSndCard *wc=(WinSndCard*)card->data; WinSnd *d=(WinSnd*)f->data; d->dev_id=wc->out_devid; return f;}MS_FILTER_DESC_EXPORT(winsnd_read_desc)MS_FILTER_DESC_EXPORT(winsnd_write_desc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -