⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winsnd2.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 2 页
字号:
/*mediastreamer2 library - modular sound and video processing and streamingCopyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.*/#include "mediastreamer2/mssndcard.h"#include "mediastreamer2/msfilter.h"#include "mediastreamer2/msticker.h"#include <mmsystem.h>#ifdef _MSC_VER#include <mmreg.h>#endif#include <msacm.h>#if defined(_WIN32_WCE)//#define DISABLE_SPEEX//#define WCE_OPTICON_WORKAROUND 1000#endif#ifndef DISABLE_SPEEX#include <speex/speex_preprocess.h>#endif#define WINSND_NBUFS 10#define WINSND_OUT_NBUFS 20#define WINSND_NSAMPLES 320#define WINSND_MINIMUMBUFFER 5static MSFilter *ms_winsnd_read_new(MSSndCard *card);static MSFilter *ms_winsnd_write_new(MSSndCard *card);typedef struct WinSndCard{	int in_devid;	int out_devid;}WinSndCard;static void winsndcard_set_level(MSSndCard *card, MSSndCardMixerElem e, int percent){    MMRESULT mr = MMSYSERR_NOERROR;    DWORD dwVolume = 0xFFFF;    dwVolume = ((0xFFFF) * percent) / 100;	switch(e){		case MS_SND_CARD_MASTER:            /*mr = waveOutSetVolume(d->waveoutdev, dwVolume); */	        if (mr != MMSYSERR_NOERROR)	        {                ms_warning("Failed to set master volume. (waveOutSetVolume:0x%i)", mr);                return;	        }        break;        case MS_SND_CARD_CAPTURE:		break;		case MS_SND_CARD_PLAYBACK:		break;        default:			ms_warning("winsnd_card_set_level: unsupported command.");	}}static int winsndcard_get_level(MSSndCard *card, MSSndCardMixerElem e){	switch(e){		case MS_SND_CARD_MASTER:            /*mr=waveOutGetVolume(d->waveoutdev, &dwVolume);*/            /* Transform to 0 to 100 scale*/            /*dwVolume = (dwVolume *100) / (0xFFFF);*/            return 60;        break;        case MS_SND_CARD_CAPTURE:		break;		case MS_SND_CARD_PLAYBACK:		break;		default:			ms_warning("winsnd_card_get_level: unsupported command.");			return -1;	}	return -1;}static void winsndcard_set_source(MSSndCard *card, MSSndCardCapture source){	switch(source){		case MS_SND_CARD_MIC:		break;		case MS_SND_CARD_LINE:		break;	}	}static void winsndcard_init(MSSndCard *card){	WinSndCard *c=(WinSndCard *)ms_new(WinSndCard,1);	card->data=c;}static void winsndcard_uninit(MSSndCard *card){	ms_free(card->data);}static void winsndcard_detect(MSSndCardManager *m);static  MSSndCard *winsndcard_dup(MSSndCard *obj);MSSndCardDesc winsnd_card_desc={	"WINSND",	winsndcard_detect,	winsndcard_init,	winsndcard_set_level,	winsndcard_get_level,	winsndcard_set_source,	ms_winsnd_read_new,	ms_winsnd_write_new,	winsndcard_uninit,	winsndcard_dup};static  MSSndCard *winsndcard_dup(MSSndCard *obj){	MSSndCard *card=ms_snd_card_new(&winsnd_card_desc);	card->name=ms_strdup(obj->name);	card->data=ms_new(WinSndCard,1);	memcpy(card->data,obj->data,sizeof(WinSndCard));	return card;}static MSSndCard *winsndcard_new(const char *name, int in_dev, int out_dev, unsigned cap){	MSSndCard *card=ms_snd_card_new(&winsnd_card_desc);	WinSndCard *d=(WinSndCard*)card->data;	card->name=ms_strdup(name);	d->in_devid=in_dev;	d->out_devid=out_dev;	card->capabilities=cap;	return card;}static void add_or_update_card(MSSndCardManager *m, const char *name, int indev, int outdev, unsigned int capability){	MSSndCard *card;	const MSList *elem=ms_snd_card_manager_get_list(m);	for(;elem!=NULL;elem=elem->next){		card=(MSSndCard*)elem->data;		if (strcmp(card->name,name)==0){			/*update already entered card */			WinSndCard *d=(WinSndCard*)card->data;			card->capabilities|=capability;			if (indev!=-1) 				d->in_devid=indev;			if (outdev!=-1)				d->out_devid=outdev;							return;		}	}	/* add this new card:*/	ms_snd_card_manager_add_card(m,winsndcard_new(name,indev,outdev,capability));}static void winsndcard_detect(MSSndCardManager *m){    MMRESULT mr = NOERROR;    unsigned int nOutDevices = waveOutGetNumDevs ();    unsigned int nInDevices = waveInGetNumDevs ();    unsigned int item;    if (nOutDevices>nInDevices)		nInDevices = nOutDevices;    for (item = 0; item < nInDevices; item++){		        WAVEINCAPS incaps;        WAVEOUTCAPS outcaps;        mr = waveInGetDevCaps (item, &incaps, sizeof (WAVEINCAPS));        if (mr == MMSYSERR_NOERROR)		{#if defined(_WIN32_WCE)			char card[256];			snprintf(card, sizeof(card), "Input card %i", item);			add_or_update_card(m,card,item,-1,MS_SND_CARD_CAP_CAPTURE);			/* _tprintf(L"new card: %s", incaps.szPname); */#else			add_or_update_card(m,incaps.szPname,item,-1,MS_SND_CARD_CAP_CAPTURE);#endif		}    	mr = waveOutGetDevCaps (item, &outcaps, sizeof (WAVEOUTCAPS));        if (mr == MMSYSERR_NOERROR)		{#if defined(_WIN32_WCE)			char card[256];			snprintf(card, sizeof(card), "Output card %i", item);    		add_or_update_card(m,card,-1,item,MS_SND_CARD_CAP_PLAYBACK);			/* _tprintf(L"new card: %s", outcaps.szPname); */#else    		add_or_update_card(m,outcaps.szPname,-1,item,MS_SND_CARD_CAP_PLAYBACK);#endif		}    }}typedef struct WinSnd{	int dev_id;	HWAVEIN indev;	HWAVEOUT outdev;	WAVEFORMATEX wfx;	WAVEHDR hdrs_read[WINSND_NBUFS];	WAVEHDR hdrs_write[WINSND_OUT_NBUFS];	queue_t rq;	ms_mutex_t mutex;	unsigned int bytes_read;	unsigned int nbufs_playing;	bool_t running;	int32_t stat_input;	int32_t stat_output;	int32_t stat_notplayed;	int32_t stat_minimumbuffer;	queue_t write_rq;#ifndef DISABLE_SPEEX	SpeexPreprocessState *pst;	int pst_frame_size;#endif	int ready;	int workaround; /* workaround for opticon audio device */}WinSnd;static void winsnd_apply_settings(WinSnd *d){	d->wfx.nBlockAlign=d->wfx.nChannels*d->wfx.wBitsPerSample/8;	d->wfx.nAvgBytesPerSec=d->wfx.nSamplesPerSec*d->wfx.nBlockAlign;}#ifndef _TRUE_TIMEstatic uint64_t winsnd_get_cur_time( void *data){	WinSnd *d=(WinSnd*)data;	uint64_t curtime=((uint64_t)d->bytes_read*1000)/(uint64_t)d->wfx.nAvgBytesPerSec;	/* ms_debug("winsnd_get_cur_time: bytes_read=%u return %lu\n",d->bytes_read,(unsigned long)curtime); */	return curtime;}#endifstatic void winsnd_init(MSFilter *f){	WinSnd *d=(WinSnd *)ms_new0(WinSnd,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);	qinit(&d->write_rq);#ifndef DISABLE_SPEEX	d->pst=NULL;	d->pst_frame_size=0;#endif	d->ready=0;	d->workaround=0;	ms_mutex_init(&d->mutex,NULL);	f->data=d;	d->stat_input=0;	d->stat_output=0;	d->stat_notplayed=0;	d->stat_minimumbuffer=WINSND_MINIMUMBUFFER;}static void winsnd_uninit(MSFilter *f){	WinSnd *d=(WinSnd*)f->data;	flushq(&d->rq,0);	flushq(&d->write_rq,0);#ifndef DISABLE_SPEEX	if (d->pst!=NULL)	    speex_preprocess_state_destroy(d->pst);	d->pst=NULL;	d->pst_frame_size=0;#endif	d->ready=0;	d->workaround=0;	ms_mutex_destroy(&d->mutex);	ms_free(f->data);}static void add_input_buffer(WinSnd *d, WAVEHDR *hdr, int buflen){	mblk_t *m=allocb(buflen,0);	MMRESULT mr;	memset(hdr,0,sizeof(*hdr));	if (buflen==0) ms_error("add_input_buffer: buflen=0 !");	hdr->lpData=(LPSTR)m->b_wptr;	hdr->dwBufferLength=buflen;	hdr->dwFlags = 0;	hdr->dwUser = (DWORD)m;	mr = waveInPrepareHeader (d->indev,hdr,sizeof(*hdr));	if (mr != MMSYSERR_NOERROR){		ms_error("waveInPrepareHeader() error");		return ;	}	mr=waveInAddBuffer(d->indev,hdr,sizeof(*hdr));	if (mr != MMSYSERR_NOERROR){		ms_error("waveInAddBuffer() error");		return ;	}}static void CALLBACK read_callback (HWAVEIN waveindev, UINT uMsg, DWORD dwInstance, DWORD dwParam1,                DWORD dwParam2){	WAVEHDR *wHdr=(WAVEHDR *) dwParam1;	MSFilter *f=(MSFilter *)dwInstance;	WinSnd *d=(WinSnd*)f->data;	mblk_t *m;	int bsize;	switch (uMsg){		case WIM_OPEN:			ms_debug("read_callback : WIM_OPEN");		break;		case WIM_CLOSE:			ms_debug("read_callback : WIM_CLOSE");		break;		case WIM_DATA:			bsize=wHdr->dwBytesRecorded;			if (bsize<=0) {#if 0				if (d->running==TRUE) /* avoid adding buffer back when calling waveInReset */				{					MMRESULT mr;					mr=waveInAddBuffer(d->indev,wHdr,sizeof(*wHdr));					if (mr != MMSYSERR_NOERROR){						ms_error("waveInAddBuffer() error");						return ;					}					ms_warning("read_callback : EMPTY DATA, WIM_DATA (%p,%i)",wHdr,bsize);				}				m=(mblk_t*)wHdr->dwUser;				wHdr->dwUser=0;				freemsg(m);				return;#endif			}			/* ms_warning("read_callback : WIM_DATA (%p,%i)",wHdr,bsize); */			m=(mblk_t*)wHdr->dwUser;			m->b_wptr+=bsize;			wHdr->dwUser=0;			ms_mutex_lock(&d->mutex);			putq(&d->rq,m);			ms_mutex_unlock(&d->mutex);			d->bytes_read+=wHdr->dwBufferLength;			d->stat_input++;			d->stat_input++;#ifdef WIN32_TIMERS			if (f->ticker->TimeEvent!=NULL)				SetEvent(f->ticker->TimeEvent);#endif		break;	}}static void winsnd_read_preprocess(MSFilter *f){	WinSnd *d=(WinSnd*)f->data;	MMRESULT mr;	int i;	int bsize;	DWORD dwFlag;	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 | WAVE_FORMAT_DIRECT;  mr = waveInOpen (&d->indev, d->dev_id, &d->wfx,              (DWORD) read_callback, (DWORD)f, dwFlag);	if (mr != MMSYSERR_NOERROR)	{    ms_error("Failed to prepare windows sound device. (waveInOpen:0x%i)", mr);    if (d->dev_id != WAVE_MAPPER)		    dwFlag = WAVE_MAPPED | CALLBACK_FUNCTION;    mr = waveInOpen (&d->indev, d->dev_id, &d->wfx,              (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)f, 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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -