📄 winsnd3.c
字号:
(DWORD) read_callback, (DWORD)f, dwFlag); if (mr != MMSYSERR_NOERROR) { ms_error("Failed to prepare windows sound device. (waveInOpen:0x%i)", mr); mr = waveInOpen (&d->indev, WAVE_MAPPER, &d->wfx, (DWORD) read_callback, (DWORD)d, CALLBACK_FUNCTION); if (mr != MMSYSERR_NOERROR) { d->indev=NULL; ms_error("Failed to prepare windows sound device. (waveInOpen:0x%i)", mr); return ; } } bsize=WINSND_NSAMPLES*d->wfx.nAvgBytesPerSec/8000; ms_debug("Using input buffers of %i bytes",bsize); for(i=0;i<WINSND_NBUFS;++i){ WAVEHDR *hdr=&d->hdrs_read[i]; add_input_buffer(d,hdr,bsize); } d->running=TRUE; mr=waveInStart(d->indev); if (mr != MMSYSERR_NOERROR){ ms_error("waveInStart() error"); return ; }#ifndef _TRUE_TIME ms_ticker_set_time_func(f->ticker,winsnd_get_cur_time,d);#endif}static void winsnd_read_postprocess(MSFilter *f){ WinSnd *d=(WinSnd*)f->data; MMRESULT mr; int i;#ifndef _TRUE_TIME ms_ticker_set_time_func(f->ticker,NULL,NULL);#endif d->running=FALSE; mr=waveInStop(d->indev); if (mr != MMSYSERR_NOERROR){ ms_error("waveInStop() error"); return ; } mr=waveInReset(d->indev); 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; } d->outcurbuf=0; d->overrun=FALSE; d->nsamples=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 ; } d->ready=0; d->workaround=0;}static void playout_buf(WinSnd *d, WAVEHDR *hdr, mblk_t *m){ MMRESULT mr; hdr->dwUser=(DWORD)m; hdr->lpData=(LPSTR)m->b_rptr; hdr->dwBufferLength=msgdsize(m); hdr->dwFlags = 0; mr = waveOutPrepareHeader(d->outdev,hdr,sizeof(*hdr)); if (mr != MMSYSERR_NOERROR){ ms_error("waveOutPrepareHeader() error"); d->stat_notplayed++; } mr=waveOutWrite(d->outdev,hdr,sizeof(*hdr)); if (mr != MMSYSERR_NOERROR){ ms_error("waveOutWrite() error"); d->stat_notplayed++; }else { d->nbufs_playing++; }}static void winsnd_write_process(MSFilter *f){ WinSnd *d=(WinSnd*)f->data; mblk_t *m; MMRESULT mr; mblk_t *old; if (d->outdev==NULL) { ms_queue_flush(f->inputs[0]); return; } if (d->overrun){ ms_warning("nbufs_playing=%i",d->nbufs_playing); if (d->nbufs_playing>0){ ms_queue_flush(f->inputs[0]); return; } else d->overrun=FALSE; } while(1){ int outcurbuf=d->outcurbuf % WINSND_OUT_NBUFS; WAVEHDR *hdr=&d->hdrs_write[outcurbuf]; old=(mblk_t*)hdr->dwUser; if (d->nsamples==0){ int tmpsize=WINSND_OUT_DELAY*d->wfx.nAvgBytesPerSec; mblk_t *tmp=allocb(tmpsize,0); memset(tmp->b_wptr,0,tmpsize); tmp->b_wptr+=tmpsize; playout_buf(d,hdr,tmp); d->outcurbuf++; d->nsamples+=WINSND_OUT_DELAY*d->wfx.nSamplesPerSec; continue; } m=ms_queue_get(f->inputs[0]); if (!m) break; d->nsamples+=msgdsize(m)/d->wfx.nBlockAlign; /*if the output buffer has finished to play, unprepare it*/ if (hdr->dwFlags & WHDR_DONE){ mr=waveOutUnprepareHeader(d->outdev,hdr,sizeof(*hdr)); if (mr != MMSYSERR_NOERROR){ ms_error("waveOutUnprepareHeader error"); } freemsg(old); old=NULL; hdr->dwFlags=0; hdr->dwUser=0; } if (old==NULL){ /* a free wavheader */ playout_buf(d,hdr,m); }else{ /* no more free wavheader, overrun !*/ ms_warning("WINSND overrun, restarting"); d->overrun=TRUE; d->nsamples=0; waveOutReset(d->outdev); } d->outcurbuf++; }}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 + -